From a167fe18776ff58f70a46244a644801ada11036a Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Tue, 27 Jan 2015 21:28:24 +0000 Subject: [PATCH] dd the option, -link-opt-hints to llvm-objdump used with -macho to print the Mach-O AArch64 linker optimization hints for ADRP code optimization. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227246 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 2 + lib/Object/MachOObjectFile.cpp | 27 ++++++- .../Inputs/link-opt-hints.macho-aarch64 | Bin 0 -> 984 bytes .../AArch64/macho-link-opt-hints.test | 11 +++ tools/llvm-objdump/MachODump.cpp | 67 +++++++++++++++++- tools/llvm-objdump/llvm-objdump.cpp | 3 +- tools/llvm-objdump/llvm-objdump.h | 1 + 7 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 test/tools/llvm-objdump/AArch64/Inputs/link-opt-hints.macho-aarch64 create mode 100644 test/tools/llvm-objdump/AArch64/macho-link-opt-hints.test diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index bee1f6ce0b0..a552aca91d7 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -395,6 +395,7 @@ public: MachO::symtab_command getSymtabLoadCommand() const; MachO::dysymtab_command getDysymtabLoadCommand() const; MachO::linkedit_data_command getDataInCodeLoadCommand() const; + MachO::linkedit_data_command getLinkOptHintsLoadCommand() const; ArrayRef getDyldInfoRebaseOpcodes() const; ArrayRef getDyldInfoBindOpcodes() const; ArrayRef getDyldInfoWeakBindOpcodes() const; @@ -437,6 +438,7 @@ private: const char *SymtabLoadCmd; const char *DysymtabLoadCmd; const char *DataInCodeLoadCmd; + const char *LinkOptHintsLoadCmd; const char *DyldInfoLoadCmd; const char *UuidLoadCmd; bool HasPageZeroSegment; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 4f544074c3d..4a1c311dd09 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -248,8 +248,9 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64bits, std::error_code &EC) : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), - DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr), - UuidLoadCmd(nullptr), HasPageZeroSegment(false) { + DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr), + DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr), + HasPageZeroSegment(false) { uint32_t LoadCommandCount = this->getHeader().ncmds; if (LoadCommandCount == 0) return; @@ -280,6 +281,13 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, return; } DataInCodeLoadCmd = Load.Ptr; + } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { + // Multiple linker optimization hint tables + if (LinkOptHintsLoadCmd) { + EC = object_error::parse_failed; + return; + } + LinkOptHintsLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_DYLD_INFO || Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { // Multiple dyldinfo load commands @@ -2497,6 +2505,21 @@ MachOObjectFile::getDataInCodeLoadCommand() const { return Cmd; } +MachO::linkedit_data_command +MachOObjectFile::getLinkOptHintsLoadCommand() const { + if (LinkOptHintsLoadCmd) + return getStruct(this, LinkOptHintsLoadCmd); + + // If there is no LinkOptHintsLoadCmd return a load command with zero'ed + // fields. + MachO::linkedit_data_command Cmd; + Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; + Cmd.cmdsize = sizeof(MachO::linkedit_data_command); + Cmd.dataoff = 0; + Cmd.datasize = 0; + return Cmd; +} + ArrayRef MachOObjectFile::getDyldInfoRebaseOpcodes() const { if (!DyldInfoLoadCmd) return ArrayRef(); diff --git a/test/tools/llvm-objdump/AArch64/Inputs/link-opt-hints.macho-aarch64 b/test/tools/llvm-objdump/AArch64/Inputs/link-opt-hints.macho-aarch64 new file mode 100644 index 0000000000000000000000000000000000000000..12d33fcdf7514fd23dbca0b3bec5465938cb3b60 GIT binary patch literal 984 zcma)5KWGzS6n}S#_SBkIT&fh>45CX)B2w%S(h@odu`M-&gYtQ#|BhbDk-I=k91j10 zgF_A-92_#5EsK+&MHj(AE8^s!TOAyPED>Y;y~}s{HB%q_zTf-3_kHi)_wnxiuOEMg zi8O-o5(iqL;t0_h;Ig8_pt8J>{s*}y(nE+dVlpp;x4P{~0TQA(f4%r$N8VHEa6KLV zLoCNQ7AK!6G9hfsTdkOOW;zTF)@#U(qmmue;k!kah#bj6lw7Z3ZLR;)2m5Qu_zB5A zH>cQuq$%Y1+nfgzQ8#SzKw^u0p@y30NW7>e#)bO+ArjxtiAZM*{x~KZk~eP zo7kQ~{>L`_(?oSwpY1Rn>D1}vXy^M~3eZb^R@=>LC*uprdyR$U1v8PnPrr>*6ifu# z&$(W&__apCH|)JL>@TB<$NM>dXFo1RD2F@tEMvQcizQ!R~YR78tXTx&+4gLb}h{ zaWH1h=Jy5PH1x6YA>DRnpc8T~;Zlw@4mMc8<^fe-WsRm9sS zRZk4$&kkr3Wz*WiuOM8{ENzO?#->=Wnw1q2ZnaFp!903v2lH#DWs~idopiWn$j&ca R$%r%+#1sZN3|_={{sN8ehqnL# literal 0 HcmV?d00001 diff --git a/test/tools/llvm-objdump/AArch64/macho-link-opt-hints.test b/test/tools/llvm-objdump/AArch64/macho-link-opt-hints.test new file mode 100644 index 00000000000..932bc4fa838 --- /dev/null +++ b/test/tools/llvm-objdump/AArch64/macho-link-opt-hints.test @@ -0,0 +1,11 @@ +RUN: llvm-objdump -m -link-opt-hints %p/Inputs/link-opt-hints.macho-aarch64 | FileCheck %s + +CHECK: Linker optimiztion hints (8 total bytes) +CHECK: identifier 8 AdrpLdrGot +CHECK: narguments 2 +CHECK: value 0x18 +CHECK: value 0x1c +CHECK: identifier 7 AdrpAdd +CHECK: narguments 2 +CHECK: value 0x6c +CHECK: value 0x70 diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 67aa6a3c1ad..e103842e54f 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -36,6 +36,7 @@ #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/GraphWriter.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/MachO.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/TargetRegistry.h" @@ -85,6 +86,11 @@ cl::opt cl::desc("Print the data in code table for Mach-O objects " "(requires -macho)")); +cl::opt + llvm::LinkOptHints("link-opt-hints", + cl::desc("Print the linker optimization hints for " + "Mach-O objects (requires -macho)")); + static cl::list ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), cl::ZeroOrMore); @@ -436,6 +442,63 @@ static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) { } } +static void PrintLinkOptHints(MachOObjectFile *O) { + MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand(); + const char *loh = O->getData().substr(LohLC.dataoff, 1).data(); + uint32_t nloh = LohLC.datasize; + outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n"; + for (uint32_t i = 0; i < nloh;) { + unsigned n; + uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n); + i += n; + outs() << " identifier " << identifier << " "; + if (i >= nloh) + return; + switch (identifier) { + case 1: + outs() << "AdrpAdrp\n"; + break; + case 2: + outs() << "AdrpLdr\n"; + break; + case 3: + outs() << "AdrpAddLdr\n"; + break; + case 4: + outs() << "AdrpLdrGotLdr\n"; + break; + case 5: + outs() << "AdrpAddStr\n"; + break; + case 6: + outs() << "AdrpLdrGotStr\n"; + break; + case 7: + outs() << "AdrpAdd\n"; + break; + case 8: + outs() << "AdrpLdrGot\n"; + break; + default: + outs() << "Unknown identifier value\n"; + break; + } + uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n); + i += n; + outs() << " narguments " << narguments << "\n"; + if (i >= nloh) + return; + + for (uint32_t j = 0; j < narguments; j++) { + uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n); + i += n; + outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n"; + if (i >= nloh) + return; + } + } +} + // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file // and if it is and there is a list of architecture flags is specified then // check to make sure this Mach-O file is one of those architectures or all @@ -483,7 +546,7 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF, // info. And don't print it otherwise like in the case of printing the // UniversalHeaders or ArchiveHeaders. if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || - LazyBind || WeakBind || IndirectSymbols || DataInCode) { + LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints) { outs() << Filename; if (!ArchiveMemberName.empty()) outs() << '(' << ArchiveMemberName << ')'; @@ -498,6 +561,8 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF, PrintIndirectSymbols(MachOOF, true); if (DataInCode) PrintDataInCodeTable(MachOOF, true); + if (LinkOptHints) + PrintLinkOptHints(MachOOF); if (Relocations) PrintRelocations(MachOOF); if (SectionHeaders) diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 1204a973d45..4935f98eca1 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -905,7 +905,8 @@ int main(int argc, char **argv) { && !(UniversalHeaders && MachOOpt) && !(ArchiveHeaders && MachOOpt) && !(IndirectSymbols && MachOOpt) - && !(DataInCode && MachOOpt)) { + && !(DataInCode && MachOOpt) + && !(LinkOptHints && MachOOpt)) { cl::PrintHelpMessage(); return 2; } diff --git a/tools/llvm-objdump/llvm-objdump.h b/tools/llvm-objdump/llvm-objdump.h index 9bc9622c0a9..402632daea7 100644 --- a/tools/llvm-objdump/llvm-objdump.h +++ b/tools/llvm-objdump/llvm-objdump.h @@ -38,6 +38,7 @@ extern cl::opt UniversalHeaders; extern cl::opt ArchiveHeaders; extern cl::opt IndirectSymbols; extern cl::opt DataInCode; +extern cl::opt LinkOptHints; extern cl::opt Relocations; extern cl::opt SectionHeaders; extern cl::opt SectionContents; -- 2.34.1