Skip to content

Commit a7bdc7e

Browse files
committedJan 22, 2015
Add the option, -indirect-symbols, used with -macho to print the Mach-O indirect symbol table to llvm-objdump.
llvm-svn: 226848
1 parent f15d7a5 commit a7bdc7e

File tree

4 files changed

+148
-3
lines changed

4 files changed

+148
-3
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
RUN: llvm-objdump -macho -indirect-symbols %p/Inputs/hello.exe.macho-x86_64 | FileCheck %s
2+
3+
CHECK: Indirect symbols for (__TEXT,__stubs) 1 entries
4+
CHECK: address index name
5+
CHECK: 0x0000000100000f6c 2 _printf
6+
CHECK: Indirect symbols for (__DATA,__nl_symbol_ptr) 2 entries
7+
CHECK: address index name
8+
CHECK: 0x0000000100001000 3 dyld_stub_binder
9+
CHECK: 0x0000000100001008 ABSOLUTE
10+
CHECK: Indirect symbols for (__DATA,__la_symbol_ptr) 1 entries
11+
CHECK: address index name
12+
CHECK: 0x0000000100001010 2 _printf

‎llvm/tools/llvm-objdump/MachODump.cpp

+133-2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ cl::opt<bool>
7575
cl::desc("Print archive headers for Mach-O archives "
7676
"(requires -macho)"));
7777

78+
cl::opt<bool>
79+
llvm::IndirectSymbols("indirect-symbols",
80+
cl::desc("Print indirect symbol table for Mach-O "
81+
"objects (requires -macho)"));
82+
7883
static cl::list<std::string>
7984
ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
8085
cl::ZeroOrMore);
@@ -260,6 +265,130 @@ static void getSectionsAndSymbols(const MachO::mach_header Header,
260265
}
261266
}
262267

268+
static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
269+
uint32_t n, uint32_t count,
270+
uint32_t stride, uint64_t addr) {
271+
MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
272+
uint32_t nindirectsyms = Dysymtab.nindirectsyms;
273+
if (n > nindirectsyms)
274+
outs() << " (entries start past the end of the indirect symbol "
275+
"table) (reserved1 field greater than the table size)";
276+
else if (n + count > nindirectsyms)
277+
outs() << " (entries extends past the end of the indirect symbol "
278+
"table)";
279+
outs() << "\n";
280+
uint32_t cputype = O->getHeader().cputype;
281+
if (cputype & MachO::CPU_ARCH_ABI64)
282+
outs() << "address index";
283+
else
284+
outs() << "address index";
285+
if (verbose)
286+
outs() << " name\n";
287+
else
288+
outs() << "\n";
289+
for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
290+
if (cputype & MachO::CPU_ARCH_ABI64)
291+
outs() << format("0x%016" PRIx64, addr + j * stride) << " ";
292+
else
293+
outs() << format("0x%08" PRIx32, addr + j * stride) << " ";
294+
MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
295+
uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
296+
if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
297+
outs() << "LOCAL\n";
298+
continue;
299+
}
300+
if (indirect_symbol ==
301+
(MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
302+
outs() << "LOCAL ABSOLUTE\n";
303+
continue;
304+
}
305+
if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
306+
outs() << "ABSOLUTE\n";
307+
continue;
308+
}
309+
outs() << format("%5u ", indirect_symbol);
310+
MachO::symtab_command Symtab = O->getSymtabLoadCommand();
311+
if (indirect_symbol < Symtab.nsyms) {
312+
symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
313+
SymbolRef Symbol = *Sym;
314+
StringRef SymName;
315+
Symbol.getName(SymName);
316+
outs() << SymName;
317+
} else {
318+
outs() << "?";
319+
}
320+
outs() << "\n";
321+
}
322+
}
323+
324+
static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
325+
uint32_t LoadCommandCount = O->getHeader().ncmds;
326+
MachOObjectFile::LoadCommandInfo Load = O->getFirstLoadCommandInfo();
327+
for (unsigned I = 0;; ++I) {
328+
if (Load.C.cmd == MachO::LC_SEGMENT_64) {
329+
MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
330+
for (unsigned J = 0; J < Seg.nsects; ++J) {
331+
MachO::section_64 Sec = O->getSection64(Load, J);
332+
uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
333+
if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
334+
section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
335+
section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
336+
section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
337+
section_type == MachO::S_SYMBOL_STUBS) {
338+
uint32_t stride;
339+
if (section_type == MachO::S_SYMBOL_STUBS)
340+
stride = Sec.reserved2;
341+
else
342+
stride = 8;
343+
if (stride == 0) {
344+
outs() << "Can't print indirect symbols for (" << Sec.segname << ","
345+
<< Sec.sectname << ") "
346+
<< "(size of stubs in reserved2 field is zero)\n";
347+
continue;
348+
}
349+
uint32_t count = Sec.size / stride;
350+
outs() << "Indirect symbols for (" << Sec.segname << ","
351+
<< Sec.sectname << ") " << count << " entries";
352+
uint32_t n = Sec.reserved1;
353+
PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
354+
}
355+
}
356+
} else if (Load.C.cmd == MachO::LC_SEGMENT) {
357+
MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
358+
for (unsigned J = 0; J < Seg.nsects; ++J) {
359+
MachO::section Sec = O->getSection(Load, J);
360+
uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
361+
if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
362+
section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
363+
section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
364+
section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
365+
section_type == MachO::S_SYMBOL_STUBS) {
366+
uint32_t stride;
367+
if (section_type == MachO::S_SYMBOL_STUBS)
368+
stride = Sec.reserved2;
369+
else
370+
stride = 4;
371+
if (stride == 0) {
372+
outs() << "Can't print indirect symbols for (" << Sec.segname << ","
373+
<< Sec.sectname << ") "
374+
<< "(size of stubs in reserved2 field is zero)\n";
375+
continue;
376+
}
377+
uint32_t count = Sec.size / stride;
378+
outs() << "Indirect symbols for (" << Sec.segname << ","
379+
<< Sec.sectname << ") " << count << " entries";
380+
uint32_t n = Sec.reserved1;
381+
PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
382+
}
383+
}
384+
}
385+
if (I == LoadCommandCount - 1)
386+
break;
387+
else
388+
Load = O->getNextLoadCommandInfo(Load);
389+
}
390+
}
391+
263392
// checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
264393
// and if it is and there is a list of architecture flags is specified then
265394
// check to make sure this Mach-O file is one of those architectures or all
@@ -305,9 +434,9 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
305434
StringRef ArchitectureName = StringRef()) {
306435
// If we are doing some processing here on the Mach-O file print the header
307436
// info. And don't print it otherwise like in the case of printing the
308-
// UniversalHeaders.
437+
// UniversalHeaders or ArchiveHeaders.
309438
if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind ||
310-
LazyBind || WeakBind) {
439+
LazyBind || WeakBind || IndirectSymbols) {
311440
outs() << Filename;
312441
if (!ArchiveMemberName.empty())
313442
outs() << '(' << ArchiveMemberName << ')';
@@ -318,6 +447,8 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
318447

319448
if (Disassemble)
320449
DisassembleMachO(Filename, MachOOF);
450+
if (IndirectSymbols)
451+
PrintIndirectSymbols(MachOOF, true);
321452
if (Relocations)
322453
PrintRelocations(MachOOF);
323454
if (SectionHeaders)

‎llvm/tools/llvm-objdump/llvm-objdump.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,8 @@ int main(int argc, char **argv) {
893893
&& !LazyBind
894894
&& !WeakBind
895895
&& !(UniversalHeaders && MachOOpt)
896-
&& !(ArchiveHeaders && MachOOpt)) {
896+
&& !(ArchiveHeaders && MachOOpt)
897+
&& !(IndirectSymbols && MachOOpt)) {
897898
cl::PrintHelpMessage();
898899
return 2;
899900
}

‎llvm/tools/llvm-objdump/llvm-objdump.h

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ extern cl::opt<bool> LazyBind;
3636
extern cl::opt<bool> WeakBind;
3737
extern cl::opt<bool> UniversalHeaders;
3838
extern cl::opt<bool> ArchiveHeaders;
39+
extern cl::opt<bool> IndirectSymbols;
3940
extern cl::opt<bool> Relocations;
4041
extern cl::opt<bool> SectionHeaders;
4142
extern cl::opt<bool> SectionContents;

0 commit comments

Comments
 (0)