@@ -75,6 +75,11 @@ cl::opt<bool>
75
75
cl::desc (" Print archive headers for Mach-O archives "
76
76
" (requires -macho)" ));
77
77
78
+ cl::opt<bool >
79
+ llvm::IndirectSymbols (" indirect-symbols" ,
80
+ cl::desc (" Print indirect symbol table for Mach-O "
81
+ " objects (requires -macho)" ));
82
+
78
83
static cl::list<std::string>
79
84
ArchFlags (" arch" , cl::desc(" architecture(s) from a Mach-O file to dump" ),
80
85
cl::ZeroOrMore);
@@ -260,6 +265,130 @@ static void getSectionsAndSymbols(const MachO::mach_header Header,
260
265
}
261
266
}
262
267
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
+
263
392
// checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
264
393
// and if it is and there is a list of architecture flags is specified then
265
394
// 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,
305
434
StringRef ArchitectureName = StringRef()) {
306
435
// If we are doing some processing here on the Mach-O file print the header
307
436
// info. And don't print it otherwise like in the case of printing the
308
- // UniversalHeaders.
437
+ // UniversalHeaders or ArchiveHeaders .
309
438
if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind ||
310
- LazyBind || WeakBind) {
439
+ LazyBind || WeakBind || IndirectSymbols ) {
311
440
outs () << Filename;
312
441
if (!ArchiveMemberName.empty ())
313
442
outs () << ' (' << ArchiveMemberName << ' )' ;
@@ -318,6 +447,8 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
318
447
319
448
if (Disassemble)
320
449
DisassembleMachO (Filename, MachOOF);
450
+ if (IndirectSymbols)
451
+ PrintIndirectSymbols (MachOOF, true );
321
452
if (Relocations)
322
453
PrintRelocations (MachOOF);
323
454
if (SectionHeaders)
0 commit comments