Skip to content

Commit 6031c8b

Browse files
cmeBgZun
authored andcommitted
Add LTO section reporting tool. (#12)
* Add LTO section predicting & reporting tool.
1 parent 705711f commit 6031c8b

File tree

2 files changed

+167
-0
lines changed

2 files changed

+167
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
set(LLVM_LINK_COMPONENTS
2+
Core
3+
IRReader
4+
Support
5+
)
6+
7+
add_llvm_tool(llvm-lto-predict-sections
8+
llvm-lto-predict-sections.cpp
9+
)
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
//===-- llvm-lto-predict-sections: predict symbols and sections for LTO bitcode
2+
//---===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This program reports the sections and symbols that may be present in final
11+
// link from included LTO bitcode files.
12+
//
13+
// This is a best-effort attempt to predict the sections. Inherently,
14+
// it can't know whether sections may be removed by the LTO
15+
// process. Mergeable sections can't be accounted for either.
16+
//
17+
//===----------------------------------------------------------------------===//
18+
19+
#include "llvm/ADT/StringExtras.h"
20+
#include "llvm/Bitcode/BitcodeWriter.h"
21+
#include "llvm/IR/LLVMContext.h"
22+
#include "llvm/IRReader/IRReader.h"
23+
#include "llvm/Support/CommandLine.h"
24+
#include "llvm/Support/SourceMgr.h"
25+
#include "llvm/Support/raw_ostream.h"
26+
27+
using namespace llvm;
28+
29+
static cl::OptionCategory OptionsCategory("Section Options");
30+
31+
static cl::opt<std::string> InputFilename(cl::Positional,
32+
cl::desc("<input bitcode file>"),
33+
cl::init("-"),
34+
cl::value_desc("filename"),
35+
cl::cat(OptionsCategory));
36+
37+
static cl::opt<bool>
38+
FFunctionSections("ffunction-sections", cl::Prefix, cl::init(false),
39+
cl::desc("Place each function in its own section"),
40+
cl::cat(OptionsCategory));
41+
42+
static cl::opt<bool>
43+
FDataSections("fdata-sections", cl::Prefix, cl::init(false),
44+
cl::desc("Place each data object in its own section"),
45+
cl::cat(OptionsCategory));
46+
47+
static cl::opt<bool> SymbolsReport("symbols", cl::Prefix, cl::init(false),
48+
cl::desc("Report symbol names"),
49+
cl::cat(OptionsCategory));
50+
51+
static cl::opt<bool> SectionsReport("sections", cl::Prefix, cl::init(false),
52+
cl::desc("Report section names"),
53+
cl::cat(OptionsCategory));
54+
55+
static cl::opt<bool>
56+
MapReport("map", cl::Prefix, cl::init(false),
57+
cl::desc("Report mapping of symbols to sections"),
58+
cl::cat(OptionsCategory));
59+
60+
std::string FunctionSectionName(Function &F) {
61+
if (F.hasSection()) {
62+
return F.getSection().str();
63+
} else {
64+
if (FFunctionSections) {
65+
return ".text." + F.getName().str();
66+
} else {
67+
return ".text";
68+
}
69+
}
70+
}
71+
72+
std::string GlobalSectionName(GlobalVariable &G) {
73+
if (G.hasSection()) {
74+
return G.getSection().str();
75+
} else {
76+
std::string Prefix;
77+
if (G.isConstant()) {
78+
Prefix = ".rodata";
79+
} else {
80+
if (G.hasInitializer() && !G.getInitializer()->isZeroValue()) {
81+
Prefix = ".data";
82+
} else {
83+
Prefix = ".bss";
84+
}
85+
}
86+
if (FDataSections) {
87+
if (G.getName().str()[0] == '.') {
88+
return Prefix + G.getName().str();
89+
} else {
90+
return Prefix + "." + G.getName().str();
91+
}
92+
} else {
93+
return Prefix;
94+
}
95+
}
96+
}
97+
98+
std::map<std::string, std::string> SymbolsToSectionsMap;
99+
std::set<std::string> SectionNames;
100+
std::set<std::string> SymbolNames;
101+
102+
int main(int argc, char **argv) {
103+
LLVMContext Context;
104+
SMDiagnostic Err;
105+
cl::HideUnrelatedOptions({&OptionsCategory});
106+
cl::ParseCommandLineOptions(argc, argv, "LLVM LTO section tool\n");
107+
108+
std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context);
109+
110+
if (!M) {
111+
Err.print(argv[0], errs());
112+
return 1;
113+
}
114+
115+
auto RecordSymbol = [](std::string SymbolName, std::string SectionName) {
116+
if (SectionsReport || MapReport) {
117+
SectionNames.insert(SectionName);
118+
}
119+
if (SymbolsReport || MapReport) {
120+
SymbolNames.insert(SymbolName);
121+
}
122+
if (MapReport) {
123+
SymbolsToSectionsMap[SymbolName] = SectionName;
124+
}
125+
};
126+
127+
for (GlobalVariable &G : M->globals()) {
128+
RecordSymbol(G.getName().str(), GlobalSectionName(G));
129+
}
130+
131+
for (Function &F : M->functions()) {
132+
RecordSymbol(F.getName().str(), FunctionSectionName(F));
133+
}
134+
135+
if (SectionsReport) {
136+
outs() << SectionNames.size() << " sections:\n";
137+
for (auto &S : SectionNames) {
138+
outs() << S << "\n";
139+
}
140+
}
141+
142+
if (SymbolsReport) {
143+
outs() << SymbolNames.size() << " symbols:\n";
144+
for (auto &S : SymbolNames) {
145+
outs() << S << "\n";
146+
}
147+
}
148+
149+
if (MapReport) {
150+
outs() << SymbolNames.size() << " symbols in " << SectionNames.size()
151+
<< " sections\n";
152+
for (auto &M : SymbolsToSectionsMap) {
153+
outs() << M.first << " " << M.second << "\n";
154+
}
155+
}
156+
157+
return 0;
158+
}

0 commit comments

Comments
 (0)