From 7118c738672aab128807f97460ed7102f2b4e0b4 Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Fri, 26 Sep 2014 22:20:44 +0000 Subject: [PATCH] =?UTF-8?q?Update=20llvm-objdump=E2=80=99s=20Mach-O=20symb?= =?UTF-8?q?olizer=20code=20to=20print=20the=20name=20of=20symbol=20stubs.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So in fully linked images when a call is made through a stub it now gets a comment like the following in the disassembly: callq 0x100000f6c ## symbol stub for: _printf indicating the call is to a symbol stub and which symbol it is for. This is done for branch reference types and seeing if the branch target is in a stub section and if so using the indirect symbol table entry for that stub and using that symbol table entries symbol name. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218546 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../X86/macho-symbolized-disassembly.test | 1 + tools/llvm-objdump/MachODump.cpp | 97 ++++++++++++++++++- 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/test/tools/llvm-objdump/X86/macho-symbolized-disassembly.test b/test/tools/llvm-objdump/X86/macho-symbolized-disassembly.test index 01105fbf3fd..65153161449 100644 --- a/test/tools/llvm-objdump/X86/macho-symbolized-disassembly.test +++ b/test/tools/llvm-objdump/X86/macho-symbolized-disassembly.test @@ -5,3 +5,4 @@ OBJ: 0000000000000008 leaq L_.str(%rip), %rax ## literal pool for: "Hello w OBJ: 0000000000000026 callq _printf EXE: 0000000100000f38 leaq 0x4f(%rip), %rax ## literal pool for: "Hello world\n" +EXE: 0000000100000f56 callq 0x100000f6c ## symbol stub for: _printf diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 414a867ebca..43f0661a05a 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -413,6 +413,94 @@ const char *GuessCstringPointer(uint64_t ReferenceValue, return nullptr; } +// GuessIndirectSymbol returns the name of the indirect symbol for the +// ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe +// an address of a symbol stub or a lazy or non-lazy pointer to associate the +// symbol name being referenced by the stub or pointer. +static const char *GuessIndirectSymbol(uint64_t ReferenceValue, + struct DisassembleInfo *info) { + uint32_t LoadCommandCount = info->O->getHeader().ncmds; + MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo(); + MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); + MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); + for (unsigned I = 0;; ++I) { + if (Load.C.cmd == MachO::LC_SEGMENT_64) { + MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); + for (unsigned J = 0; J < Seg.nsects; ++J) { + MachO::section_64 Sec = info->O->getSection64(Load, J); + uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; + if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || + section_type == MachO::S_LAZY_SYMBOL_POINTERS || + section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || + section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || + section_type == MachO::S_SYMBOL_STUBS) && + ReferenceValue >= Sec.addr && + ReferenceValue < Sec.addr + Sec.size) { + uint32_t stride; + if (section_type == MachO::S_SYMBOL_STUBS) + stride = Sec.reserved2; + else + stride = 8; + if (stride == 0) + return nullptr; + uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; + if (index < Dysymtab.nindirectsyms) { + uint32_t indirect_symbol = + info->O->getIndirectSymbolTableEntry(Dysymtab, index); + if (indirect_symbol < Symtab.nsyms) { + symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); + SymbolRef Symbol = *Sym; + StringRef SymName; + Symbol.getName(SymName); + const char *name = SymName.data(); + return name; + } + } + } + } + } else if (Load.C.cmd == MachO::LC_SEGMENT) { + MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); + for (unsigned J = 0; J < Seg.nsects; ++J) { + MachO::section Sec = info->O->getSection(Load, J); + uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; + if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || + section_type == MachO::S_LAZY_SYMBOL_POINTERS || + section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || + section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || + section_type == MachO::S_SYMBOL_STUBS) && + ReferenceValue >= Sec.addr && + ReferenceValue < Sec.addr + Sec.size) { + uint32_t stride; + if (section_type == MachO::S_SYMBOL_STUBS) + stride = Sec.reserved2; + else + stride = 4; + if (stride == 0) + return nullptr; + uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; + if (index < Dysymtab.nindirectsyms) { + uint32_t indirect_symbol = + info->O->getIndirectSymbolTableEntry(Dysymtab, index); + if (indirect_symbol < Symtab.nsyms) { + symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); + SymbolRef Symbol = *Sym; + StringRef SymName; + Symbol.getName(SymName); + const char *name = SymName.data(); + return name; + } + } + } + } + } + if (I == LoadCommandCount - 1) + break; + else + Load = info->O->getNextLoadCommandInfo(Load); + } + return nullptr; +} + // GuessLiteralPointer returns a string which for the item in the Mach-O file // for the address passed in as ReferenceValue for printing as a comment with // the instruction and also returns the corresponding type of that item @@ -531,7 +619,14 @@ const char *SymbolizerSymbolLookUp(void *DisInfo, uint64_t ReferenceValue, if (!name.empty()) SymbolName = name.data(); - if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { + if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { + *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); + if (*ReferenceName) + *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; + else + *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; + } + else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { *ReferenceName = GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); if (*ReferenceName == nullptr)