aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-objdump/MachODump.cpp
diff options
context:
space:
mode:
authorDaniel Bertalan <dani@danielbertalan.dev>2022-08-12 15:10:58 +0200
committerDaniel Bertalan <dani@danielbertalan.dev>2022-08-18 09:29:27 +0200
commit11443ef85dbe4f3930f726b1be4d7f90f99d1021 (patch)
tree9e0c385d02e25463d41933e15024b6f1da52244c /llvm/tools/llvm-objdump/MachODump.cpp
parented342d9d29898952e2d1fcd40716e83ed5b9f202 (diff)
downloadllvm-11443ef85dbe4f3930f726b1be4d7f90f99d1021.zip
llvm-11443ef85dbe4f3930f726b1be4d7f90f99d1021.tar.gz
llvm-11443ef85dbe4f3930f726b1be4d7f90f99d1021.tar.bz2
[llvm-objdump] Support dumping segment information with -chained_fixups
This commit adds the definitions for `dyld_chained_starts_in_image`, `dyld_chained_starts_in_segment`, and related enums. Dumping their contents is possible with the -chained_fixups flag of llvm-otool. The chained-fixups.yaml test was changed to cover bindings/rebases, as well as weak imports, weak symbols and flat namespace symbols. Now that we have actual fixup entries, the __DATA segment contains data that would need to be hexdumped in YAML. We also test empty pages (to look for the "DYLD_CHAINED_PTR_START_NONE" annotation), so the YAML would end up quite large. So instead, this commit includes a binary file. When Apple's effort to upstream their chained fixups code continues, we'll replace this code with the then-upstreamed code. But we need something in the meantime for testing ld64.lld's chained fixups code. Differential Revision: https://reviews.llvm.org/D131961
Diffstat (limited to 'llvm/tools/llvm-objdump/MachODump.cpp')
-rw-r--r--llvm/tools/llvm-objdump/MachODump.cpp80
1 files changed, 80 insertions, 0 deletions
diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp
index a2593cf..d95b1c4 100644
--- a/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/llvm/tools/llvm-objdump/MachODump.cpp
@@ -1195,6 +1195,20 @@ static void printMachOChainedFixups(object::MachOObjectFile *Obj) {
reportError(std::move(Err), Obj->getFileName());
}
+static SmallVector<std::string> GetSegmentNames(object::MachOObjectFile *O) {
+ SmallVector<std::string> Ret;
+ for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) {
+ if (Command.C.cmd == MachO::LC_SEGMENT) {
+ MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
+ Ret.push_back(SLC.segname);
+ } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
+ MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command);
+ Ret.push_back(SLC.segname);
+ }
+ }
+ return Ret;
+}
+
static void
PrintChainedFixupsHeader(const MachO::dyld_chained_fixups_header &H) {
outs() << "chained fixups header (LC_DYLD_CHAINED_FIXUPS)\n";
@@ -1224,6 +1238,50 @@ PrintChainedFixupsHeader(const MachO::dyld_chained_fixups_header &H) {
outs() << '\n';
}
+static constexpr std::array<StringRef, 13> PointerFormats{
+ "DYLD_CHAINED_PTR_ARM64E",
+ "DYLD_CHAINED_PTR_64",
+ "DYLD_CHAINED_PTR_32",
+ "DYLD_CHAINED_PTR_32_CACHE",
+ "DYLD_CHAINED_PTR_32_FIRMWARE",
+ "DYLD_CHAINED_PTR_64_OFFSET",
+ "DYLD_CHAINED_PTR_ARM64E_KERNEL",
+ "DYLD_CHAINED_PTR_64_KERNEL_CACHE",
+ "DYLD_CHAINED_PTR_ARM64E_USERLAND",
+ "DYLD_CHAINED_PTR_ARM64E_FIRMWARE",
+ "DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE",
+ "DYLD_CHAINED_PTR_ARM64E_USERLAND24",
+};
+
+static void
+PrintChainedFixupsSegment(const MachOObjectFile::ChainedFixupsSegment &Segment,
+ StringRef SegName) {
+ outs() << "chained starts in segment " << Segment.SegIdx << " (" << SegName
+ << ")\n";
+ outs() << " size = " << Segment.Header.size << '\n';
+ outs() << " page_size = " << format("0x%0" PRIx16, Segment.Header.page_size)
+ << '\n';
+
+ outs() << " pointer_format = " << Segment.Header.pointer_format;
+ if ((Segment.Header.pointer_format - 1) <
+ MachO::DYLD_CHAINED_PTR_ARM64E_USERLAND24)
+ outs() << " (" << PointerFormats[Segment.Header.pointer_format - 1] << ")";
+ outs() << '\n';
+
+ outs() << " segment_offset = "
+ << format("0x%0" PRIx64, Segment.Header.segment_offset) << '\n';
+ outs() << " max_valid_pointer = " << Segment.Header.max_valid_pointer
+ << '\n';
+ outs() << " page_count = " << Segment.Header.page_count << '\n';
+ for (auto [Index, PageStart] : enumerate(Segment.PageStarts)) {
+ outs() << " page_start[" << Index << "] = " << PageStart;
+ // FIXME: Support DYLD_CHAINED_PTR_START_MULTI (32-bit only)
+ if (PageStart == MachO::DYLD_CHAINED_PTR_START_NONE)
+ outs() << " (DYLD_CHAINED_PTR_START_NONE)";
+ outs() << '\n';
+ }
+}
+
static void PrintChainedFixups(MachOObjectFile *O) {
// MachOObjectFile::getChainedFixupsHeader() reads LC_DYLD_CHAINED_FIXUPS.
// FIXME: Support chained fixups in __TEXT,__chain_starts section too.
@@ -1234,6 +1292,28 @@ static void PrintChainedFixups(MachOObjectFile *O) {
PrintChainedFixupsHeader(*ChainedFixupHeader);
+ auto [SegCount, Segments] =
+ unwrapOrError(O->getChainedFixupsSegments(), O->getFileName());
+
+ auto SegNames = GetSegmentNames(O);
+
+ size_t StartsIdx = 0;
+ outs() << "chained starts in image\n";
+ outs() << " seg_count = " << SegCount << '\n';
+ for (size_t I = 0; I < SegCount; ++I) {
+ uint64_t SegOffset = 0;
+ if (StartsIdx < Segments.size() && I == Segments[StartsIdx].SegIdx) {
+ SegOffset = Segments[StartsIdx].Offset;
+ ++StartsIdx;
+ }
+
+ outs() << " seg_offset[" << I << "] = " << SegOffset << " ("
+ << SegNames[I] << ")\n";
+ }
+
+ for (const MachOObjectFile::ChainedFixupsSegment &S : Segments)
+ PrintChainedFixupsSegment(S, SegNames[S.SegIdx]);
+
// FIXME: Print more things.
}