From 96e8b4cb368936a331a8638f5339b8606e5d963e Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Thu, 22 Jun 2017 17:41:22 +0000 Subject: [PATCH] Updated llvm-objdump symbolic disassembly with x86_64 Mach-O MH_KEXT_BUNDLE file types so it symbolically disassembles operands using the external relocation entries. rdar://31521343 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306037 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 6 +++ lib/Object/MachOObjectFile.cpp | 39 ++++++++++++---- .../X86/Inputs/kextbundle.macho-x86_64 | Bin 0 -> 4152 bytes .../X86/macho-disassembly-kextbundle.test | 9 ++++ tools/llvm-objdump/MachODump.cpp | 42 ++++++++++++++++-- 5 files changed, 83 insertions(+), 13 deletions(-) create mode 100755 test/tools/llvm-objdump/X86/Inputs/kextbundle.macho-x86_64 create mode 100644 test/tools/llvm-objdump/X86/macho-disassembly-kextbundle.test diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 3fc726f4ccb..2c3c89d1054 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -304,6 +304,12 @@ public: relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; + relocation_iterator extrel_begin() const; + relocation_iterator extrel_end() const; + iterator_range external_relocations() const { + return make_range(extrel_begin(), extrel_end()); + } + void moveRelocationNext(DataRefImpl &Rel) const override; uint64_t getRelocationOffset(DataRefImpl Rel) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 7804bbe06f8..2e4da9f15aa 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -1951,13 +1951,29 @@ MachOObjectFile::section_rel_end(DataRefImpl Sec) const { return relocation_iterator(RelocationRef(Ret, this)); } +relocation_iterator MachOObjectFile::extrel_begin() const { + DataRefImpl Ret; + Ret.d.a = 0; // Would normally be a section index. + Ret.d.b = 0; // Index into the external relocations + return relocation_iterator(RelocationRef(Ret, this)); +} + +relocation_iterator MachOObjectFile::extrel_end() const { + MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand(); + DataRefImpl Ret; + Ret.d.a = 0; // Would normally be a section index. + Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations + return relocation_iterator(RelocationRef(Ret, this)); +} + void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { ++Rel.d.b; } uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const { - assert(getHeader().filetype == MachO::MH_OBJECT && - "Only implemented for MH_OBJECT"); + assert((getHeader().filetype == MachO::MH_OBJECT || + getHeader().filetype == MachO::MH_KEXT_BUNDLE) && + "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE"); MachO::any_relocation_info RE = getRelocation(Rel); return getAnyRelocationAddress(RE); } @@ -4086,15 +4102,20 @@ MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { MachO::any_relocation_info MachOObjectFile::getRelocation(DataRefImpl Rel) const { - DataRefImpl Sec; - Sec.d.a = Rel.d.a; uint32_t Offset; - if (is64Bit()) { - MachO::section_64 Sect = getSection64(Sec); - Offset = Sect.reloff; + if (getHeader().filetype == MachO::MH_OBJECT) { + DataRefImpl Sec; + Sec.d.a = Rel.d.a; + if (is64Bit()) { + MachO::section_64 Sect = getSection64(Sec); + Offset = Sect.reloff; + } else { + MachO::section Sect = getSection(Sec); + Offset = Sect.reloff; + } } else { - MachO::section Sect = getSection(Sec); - Offset = Sect.reloff; + MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand(); + Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations } auto P = reinterpret_cast( diff --git a/test/tools/llvm-objdump/X86/Inputs/kextbundle.macho-x86_64 b/test/tools/llvm-objdump/X86/Inputs/kextbundle.macho-x86_64 new file mode 100755 index 0000000000000000000000000000000000000000..ea9938b8631d4ba10c9aa3066a10292d9a4d07b0 GIT binary patch literal 4152 zcmX^A>+L^w1_nlE1_lOhAZ7*P4U7y7tw0(CB!Tz^5XZ-dxJHD4M9_c$c0SNduvtt{ z>G=4P)QS>>T6FU^@I&N4ZU6xgp9R8%kSq)h$lUn&)QtGFqQu-(h$y;w2cYITKsAB* zAV1;)Ab)xQaeTawr=Pd0izm#lF#n;^7Epsg{saaW9Dw{Q0pbDGgV-8C8l)BEuK*xM z1|WSfj4Y0gtpGFx*&b=2B9J}3L56$hD_NiKId*gb!^VxJK%r4E8UmvsFd71*Aut*O zqaiRF0;3@?8UmvsFd71*AutR=Ak?GtDX2fr5PNt62#7%a#8?%?z*r%`D8R$cF#*_7 zQ~`?10P%(Y5CH2}GdS`Iv@tpJvO)EM`l$Rs^|1aov_Ja~D$TGJ*lz|(>nbqBr{(7} K#3v;dfu#ViW;|j5 literal 0 HcmV?d00001 diff --git a/test/tools/llvm-objdump/X86/macho-disassembly-kextbundle.test b/test/tools/llvm-objdump/X86/macho-disassembly-kextbundle.test new file mode 100644 index 00000000000..b6c53a22f0c --- /dev/null +++ b/test/tools/llvm-objdump/X86/macho-disassembly-kextbundle.test @@ -0,0 +1,9 @@ +// RUN: llvm-objdump -d -m -no-show-raw-insn -full-leading-addr -print-imm-hex %p/Inputs/kextbundle.macho-x86_64 | FileCheck %s + +CHECK: (__TEXT,__text) section +CHECK: _foo: +CHECK: 0000000000000fb0 pushq %rbp +CHECK: 0000000000000fb1 movq %rsp, %rbp +CHECK: 0000000000000fb4 callq _bar +CHECK: 0000000000000fb9 popq %rbp +CHECK: 0000000000000fba retq diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 960ef6be414..ec4c44a2665 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -1921,11 +1921,45 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, if (Arch == Triple::x86_64) { if (Size != 1 && Size != 2 && Size != 4 && Size != 0) return 0; + // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external + // relocation entries of a linked image (if any) for an entry that matches + // this segment offset. if (info->O->getHeader().filetype != MachO::MH_OBJECT) { - // TODO: - // Search the external relocation entries of a fully linked image - // (if any) for an entry that matches this segment offset. - // uint64_t seg_offset = (Pc + Offset); + uint64_t seg_offset = Pc + Offset; + bool reloc_found = false; + DataRefImpl Rel; + MachO::any_relocation_info RE; + bool isExtern = false; + SymbolRef Symbol; + for (const RelocationRef &Reloc : info->O->external_relocations()) { + uint64_t RelocOffset = Reloc.getOffset(); + if (RelocOffset == seg_offset) { + Rel = Reloc.getRawDataRefImpl(); + RE = info->O->getRelocation(Rel); + // external relocation entries should always be external. + isExtern = info->O->getPlainRelocationExternal(RE); + if (isExtern) { + symbol_iterator RelocSym = Reloc.getSymbol(); + Symbol = *RelocSym; + } + reloc_found = true; + break; + } + } + if (reloc_found && isExtern) { + // The Value passed in will be adjusted by the Pc if the instruction + // adds the Pc. But for x86_64 external relocation entries the Value + // is the offset from the external symbol. + if (info->O->getAnyRelocationPCRel(RE)) + op_info->Value -= Pc + Offset + Size; + Expected SymName = Symbol.getName(); + if (!SymName) + report_error(info->O->getFileName(), SymName.takeError()); + const char *name = SymName->data(); + op_info->AddSymbol.Present = 1; + op_info->AddSymbol.Name = name; + return 1; + } return 0; } // In MH_OBJECT filetypes search the section's relocation entries (if any) -- 2.50.1