Skip to content

Commit bc76bbc

Browse files
committed
[JITLink] Add an option to dump relocated section content.
The -dump-relocated-section-content option will dump the contents of each section after relocations are applied, and before any checks are run or code executed. llvm-svn: 358863
1 parent 584e748 commit bc76bbc

File tree

1 file changed

+82
-3
lines changed

1 file changed

+82
-3
lines changed

llvm/tools/llvm-jitlink/llvm-jitlink.cpp

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,14 @@ static cl::opt<bool> ShowAtomGraph(
8787
cl::init(false));
8888

8989
static cl::opt<bool> ShowSizes(
90-
"show-sizes",
91-
cl::desc("Show sizes: pre- and post-dead stripping, and allocations"),
92-
cl::init(false));
90+
"show-sizes",
91+
cl::desc("Show sizes pre- and post-dead stripping, and allocations"),
92+
cl::init(false));
93+
94+
static cl::opt<bool> ShowRelocatedSectionContents(
95+
"show-relocated-section-contents",
96+
cl::desc("show section contents after fixups have been applied"),
97+
cl::init(false));
9398

9499
ExitOnError ExitOnErr;
95100

@@ -139,6 +144,74 @@ static uint64_t computeTotalAtomSizes(AtomGraph &G) {
139144
return TotalSize;
140145
}
141146

147+
static void dumpSectionContents(raw_ostream &OS, AtomGraph &G) {
148+
constexpr JITTargetAddress DumpWidth = 16;
149+
static_assert(isPowerOf2_64(DumpWidth), "DumpWidth must be a power of two");
150+
151+
// Put sections in address order.
152+
std::vector<Section *> Sections;
153+
for (auto &S : G.sections())
154+
Sections.push_back(&S);
155+
156+
std::sort(Sections.begin(), Sections.end(),
157+
[](const Section *LHS, const Section *RHS) {
158+
if (LHS->atoms_empty() && RHS->atoms_empty())
159+
return false;
160+
if (LHS->atoms_empty())
161+
return false;
162+
if (RHS->atoms_empty())
163+
return true;
164+
return (*LHS->atoms().begin())->getAddress() <
165+
(*RHS->atoms().begin())->getAddress();
166+
});
167+
168+
for (auto *S : Sections) {
169+
OS << S->getName() << " content:";
170+
if (S->atoms_empty()) {
171+
OS << "\n section empty\n";
172+
continue;
173+
}
174+
175+
// Sort atoms into order, then render.
176+
std::vector<DefinedAtom *> Atoms(S->atoms().begin(), S->atoms().end());
177+
std::sort(Atoms.begin(), Atoms.end(),
178+
[](const DefinedAtom *LHS, const DefinedAtom *RHS) {
179+
return LHS->getAddress() < RHS->getAddress();
180+
});
181+
182+
JITTargetAddress NextAddr = Atoms.front()->getAddress() & ~(DumpWidth - 1);
183+
for (auto *DA : Atoms) {
184+
bool IsZeroFill = DA->isZeroFill();
185+
JITTargetAddress AtomStart = DA->getAddress();
186+
JITTargetAddress AtomSize =
187+
IsZeroFill ? DA->getZeroFillSize() : DA->getContent().size();
188+
JITTargetAddress AtomEnd = AtomStart + AtomSize;
189+
const uint8_t *AtomData =
190+
IsZeroFill ? nullptr : DA->getContent().bytes_begin();
191+
192+
// Pad any space before the atom starts.
193+
while (NextAddr != AtomStart) {
194+
if (NextAddr % DumpWidth == 0)
195+
OS << formatv("\n{0:x16}:", NextAddr);
196+
OS << " ";
197+
++NextAddr;
198+
}
199+
200+
// Render the atom content.
201+
while (NextAddr != AtomEnd) {
202+
if (NextAddr % DumpWidth == 0)
203+
OS << formatv("\n{0:x16}:", NextAddr);
204+
if (IsZeroFill)
205+
OS << " 00";
206+
else
207+
OS << formatv(" {0:x-2}", AtomData[NextAddr - AtomStart]);
208+
++NextAddr;
209+
}
210+
}
211+
OS << "\n";
212+
}
213+
}
214+
142215
Session::Session(Triple TT)
143216
: ObjLayer(ES, MemMgr, ObjectLinkingLayer::NotifyLoadedFunction(),
144217
ObjectLinkingLayer::NotifyEmittedFunction(),
@@ -181,6 +254,12 @@ void Session::modifyPassConfig(const Triple &FTT,
181254
});
182255
}
183256

257+
if (ShowRelocatedSectionContents)
258+
PassConfig.PostFixupPasses.push_back([](AtomGraph &G) -> Error {
259+
outs() << "Relocated section contents for " << G.getName() << ":\n";
260+
dumpSectionContents(outs(), G);
261+
return Error::success();
262+
});
184263
}
185264

186265
Expected<Session::FileInfo &> Session::findFileInfo(StringRef FileName) {

0 commit comments

Comments
 (0)