@@ -342,6 +342,264 @@ static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
342
342
}
343
343
}
344
344
345
+ static void printRelocationTargetName (const MachOObjectFile *O,
346
+ const MachO::any_relocation_info &RE,
347
+ raw_string_ostream &Fmt) {
348
+ // Target of a scattered relocation is an address. In the interest of
349
+ // generating pretty output, scan through the symbol table looking for a
350
+ // symbol that aligns with that address. If we find one, print it.
351
+ // Otherwise, we just print the hex address of the target.
352
+ if (O->isRelocationScattered (RE)) {
353
+ uint32_t Val = O->getPlainRelocationSymbolNum (RE);
354
+
355
+ for (const SymbolRef &Symbol : O->symbols ()) {
356
+ Expected<uint64_t > Addr = Symbol.getAddress ();
357
+ if (!Addr)
358
+ report_error (O->getFileName (), Addr.takeError ());
359
+ if (*Addr != Val)
360
+ continue ;
361
+ Expected<StringRef> Name = Symbol.getName ();
362
+ if (!Name)
363
+ report_error (O->getFileName (), Name.takeError ());
364
+ Fmt << *Name;
365
+ return ;
366
+ }
367
+
368
+ // If we couldn't find a symbol that this relocation refers to, try
369
+ // to find a section beginning instead.
370
+ for (const SectionRef &Section : ToolSectionFilter (*O)) {
371
+ std::error_code ec;
372
+
373
+ StringRef Name;
374
+ uint64_t Addr = Section.getAddress ();
375
+ if (Addr != Val)
376
+ continue ;
377
+ if ((ec = Section.getName (Name)))
378
+ report_error (O->getFileName (), ec);
379
+ Fmt << Name;
380
+ return ;
381
+ }
382
+
383
+ Fmt << format (" 0x%x" , Val);
384
+ return ;
385
+ }
386
+
387
+ StringRef S;
388
+ bool isExtern = O->getPlainRelocationExternal (RE);
389
+ uint64_t Val = O->getPlainRelocationSymbolNum (RE);
390
+
391
+ if (O->getAnyRelocationType (RE) == MachO::ARM64_RELOC_ADDEND) {
392
+ Fmt << format (" 0x%0" PRIx64, Val);
393
+ return ;
394
+ }
395
+
396
+ if (isExtern) {
397
+ symbol_iterator SI = O->symbol_begin ();
398
+ advance (SI, Val);
399
+ Expected<StringRef> SOrErr = SI->getName ();
400
+ if (!SOrErr)
401
+ report_error (O->getFileName (), SOrErr.takeError ());
402
+ S = *SOrErr;
403
+ } else {
404
+ section_iterator SI = O->section_begin ();
405
+ // Adjust for the fact that sections are 1-indexed.
406
+ if (Val == 0 ) {
407
+ Fmt << " 0 (?,?)" ;
408
+ return ;
409
+ }
410
+ uint32_t I = Val - 1 ;
411
+ while (I != 0 && SI != O->section_end ()) {
412
+ --I;
413
+ advance (SI, 1 );
414
+ }
415
+ if (SI == O->section_end ())
416
+ Fmt << Val << " (?,?)" ;
417
+ else
418
+ SI->getName (S);
419
+ }
420
+
421
+ Fmt << S;
422
+ }
423
+
424
+ std::error_code
425
+ llvm::getMachORelocationValueString (const MachOObjectFile *Obj,
426
+ const RelocationRef &RelRef,
427
+ SmallVectorImpl<char > &Result) {
428
+ DataRefImpl Rel = RelRef.getRawDataRefImpl ();
429
+ MachO::any_relocation_info RE = Obj->getRelocation (Rel);
430
+
431
+ unsigned Arch = Obj->getArch ();
432
+
433
+ std::string FmtBuf;
434
+ raw_string_ostream Fmt (FmtBuf);
435
+ unsigned Type = Obj->getAnyRelocationType (RE);
436
+ bool IsPCRel = Obj->getAnyRelocationPCRel (RE);
437
+
438
+ // Determine any addends that should be displayed with the relocation.
439
+ // These require decoding the relocation type, which is triple-specific.
440
+
441
+ // X86_64 has entirely custom relocation types.
442
+ if (Arch == Triple::x86_64) {
443
+ switch (Type) {
444
+ case MachO::X86_64_RELOC_GOT_LOAD:
445
+ case MachO::X86_64_RELOC_GOT: {
446
+ printRelocationTargetName (Obj, RE, Fmt);
447
+ Fmt << " @GOT" ;
448
+ if (IsPCRel)
449
+ Fmt << " PCREL" ;
450
+ break ;
451
+ }
452
+ case MachO::X86_64_RELOC_SUBTRACTOR: {
453
+ DataRefImpl RelNext = Rel;
454
+ Obj->moveRelocationNext (RelNext);
455
+ MachO::any_relocation_info RENext = Obj->getRelocation (RelNext);
456
+
457
+ // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
458
+ // X86_64_RELOC_UNSIGNED.
459
+ // NOTE: Scattered relocations don't exist on x86_64.
460
+ unsigned RType = Obj->getAnyRelocationType (RENext);
461
+ if (RType != MachO::X86_64_RELOC_UNSIGNED)
462
+ report_error (Obj->getFileName (), " Expected X86_64_RELOC_UNSIGNED after "
463
+ " X86_64_RELOC_SUBTRACTOR." );
464
+
465
+ // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
466
+ // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
467
+ printRelocationTargetName (Obj, RENext, Fmt);
468
+ Fmt << " -" ;
469
+ printRelocationTargetName (Obj, RE, Fmt);
470
+ break ;
471
+ }
472
+ case MachO::X86_64_RELOC_TLV:
473
+ printRelocationTargetName (Obj, RE, Fmt);
474
+ Fmt << " @TLV" ;
475
+ if (IsPCRel)
476
+ Fmt << " P" ;
477
+ break ;
478
+ case MachO::X86_64_RELOC_SIGNED_1:
479
+ printRelocationTargetName (Obj, RE, Fmt);
480
+ Fmt << " -1" ;
481
+ break ;
482
+ case MachO::X86_64_RELOC_SIGNED_2:
483
+ printRelocationTargetName (Obj, RE, Fmt);
484
+ Fmt << " -2" ;
485
+ break ;
486
+ case MachO::X86_64_RELOC_SIGNED_4:
487
+ printRelocationTargetName (Obj, RE, Fmt);
488
+ Fmt << " -4" ;
489
+ break ;
490
+ default :
491
+ printRelocationTargetName (Obj, RE, Fmt);
492
+ break ;
493
+ }
494
+ // X86 and ARM share some relocation types in common.
495
+ } else if (Arch == Triple::x86 || Arch == Triple::arm ||
496
+ Arch == Triple::ppc) {
497
+ // Generic relocation types...
498
+ switch (Type) {
499
+ case MachO::GENERIC_RELOC_PAIR: // prints no info
500
+ return std::error_code ();
501
+ case MachO::GENERIC_RELOC_SECTDIFF: {
502
+ DataRefImpl RelNext = Rel;
503
+ Obj->moveRelocationNext (RelNext);
504
+ MachO::any_relocation_info RENext = Obj->getRelocation (RelNext);
505
+
506
+ // X86 sect diff's must be followed by a relocation of type
507
+ // GENERIC_RELOC_PAIR.
508
+ unsigned RType = Obj->getAnyRelocationType (RENext);
509
+
510
+ if (RType != MachO::GENERIC_RELOC_PAIR)
511
+ report_error (Obj->getFileName (), " Expected GENERIC_RELOC_PAIR after "
512
+ " GENERIC_RELOC_SECTDIFF." );
513
+
514
+ printRelocationTargetName (Obj, RE, Fmt);
515
+ Fmt << " -" ;
516
+ printRelocationTargetName (Obj, RENext, Fmt);
517
+ break ;
518
+ }
519
+ }
520
+
521
+ if (Arch == Triple::x86 || Arch == Triple::ppc) {
522
+ switch (Type) {
523
+ case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
524
+ DataRefImpl RelNext = Rel;
525
+ Obj->moveRelocationNext (RelNext);
526
+ MachO::any_relocation_info RENext = Obj->getRelocation (RelNext);
527
+
528
+ // X86 sect diff's must be followed by a relocation of type
529
+ // GENERIC_RELOC_PAIR.
530
+ unsigned RType = Obj->getAnyRelocationType (RENext);
531
+ if (RType != MachO::GENERIC_RELOC_PAIR)
532
+ report_error (Obj->getFileName (), " Expected GENERIC_RELOC_PAIR after "
533
+ " GENERIC_RELOC_LOCAL_SECTDIFF." );
534
+
535
+ printRelocationTargetName (Obj, RE, Fmt);
536
+ Fmt << " -" ;
537
+ printRelocationTargetName (Obj, RENext, Fmt);
538
+ break ;
539
+ }
540
+ case MachO::GENERIC_RELOC_TLV: {
541
+ printRelocationTargetName (Obj, RE, Fmt);
542
+ Fmt << " @TLV" ;
543
+ if (IsPCRel)
544
+ Fmt << " P" ;
545
+ break ;
546
+ }
547
+ default :
548
+ printRelocationTargetName (Obj, RE, Fmt);
549
+ }
550
+ } else { // ARM-specific relocations
551
+ switch (Type) {
552
+ case MachO::ARM_RELOC_HALF:
553
+ case MachO::ARM_RELOC_HALF_SECTDIFF: {
554
+ // Half relocations steal a bit from the length field to encode
555
+ // whether this is an upper16 or a lower16 relocation.
556
+ bool isUpper = (Obj->getAnyRelocationLength (RE) & 0x1 ) == 1 ;
557
+
558
+ if (isUpper)
559
+ Fmt << " :upper16:(" ;
560
+ else
561
+ Fmt << " :lower16:(" ;
562
+ printRelocationTargetName (Obj, RE, Fmt);
563
+
564
+ DataRefImpl RelNext = Rel;
565
+ Obj->moveRelocationNext (RelNext);
566
+ MachO::any_relocation_info RENext = Obj->getRelocation (RelNext);
567
+
568
+ // ARM half relocs must be followed by a relocation of type
569
+ // ARM_RELOC_PAIR.
570
+ unsigned RType = Obj->getAnyRelocationType (RENext);
571
+ if (RType != MachO::ARM_RELOC_PAIR)
572
+ report_error (Obj->getFileName (), " Expected ARM_RELOC_PAIR after "
573
+ " ARM_RELOC_HALF" );
574
+
575
+ // NOTE: The half of the target virtual address is stashed in the
576
+ // address field of the secondary relocation, but we can't reverse
577
+ // engineer the constant offset from it without decoding the movw/movt
578
+ // instruction to find the other half in its immediate field.
579
+
580
+ // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
581
+ // symbol/section pointer of the follow-on relocation.
582
+ if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
583
+ Fmt << " -" ;
584
+ printRelocationTargetName (Obj, RENext, Fmt);
585
+ }
586
+
587
+ Fmt << " )" ;
588
+ break ;
589
+ }
590
+ default : {
591
+ printRelocationTargetName (Obj, RE, Fmt);
592
+ }
593
+ }
594
+ }
595
+ } else
596
+ printRelocationTargetName (Obj, RE, Fmt);
597
+
598
+ Fmt.flush ();
599
+ Result.append (FmtBuf.begin (), FmtBuf.end ());
600
+ return std::error_code ();
601
+ }
602
+
345
603
static void PrintIndirectSymbolTable (MachOObjectFile *O, bool verbose,
346
604
uint32_t n, uint32_t count,
347
605
uint32_t stride, uint64_t addr) {
0 commit comments