@@ -384,11 +384,26 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
384384 const MCFragment *Fragment,
385385 const MCFixup &Fixup, MCValue Target,
386386 uint64_t &FixedValue) {
387-
388- if (Target.getSymB ())
389- report_fatal_error (" Handling Target.SymB for relocation is unimplemented." );
390-
391- const MCSymbol &SymA = Target.getSymA ()->getSymbol ();
387+ auto getIndex = [this ](const MCSymbol *Sym,
388+ const MCSectionXCOFF *ContainingCsect) {
389+ // If we could not find the symbol directly in SymbolIndexMap, this symbol
390+ // could either be a temporary symbol or an undefined symbol. In this case,
391+ // we would need to have the relocation reference its csect instead.
392+ return SymbolIndexMap.find (Sym) != SymbolIndexMap.end ()
393+ ? SymbolIndexMap[Sym]
394+ : SymbolIndexMap[ContainingCsect->getQualNameSymbol ()];
395+ };
396+
397+ auto getVirtualAddress = [this ,
398+ &Layout](const MCSymbol *Sym,
399+ const MCSectionXCOFF *ContainingCsect) {
400+ // If Sym is a csect, return csect's address.
401+ // If Sym is a label, return csect's address + label's offset from the csect.
402+ return SectionMap[ContainingCsect]->Address +
403+ (Sym->isDefined () ? Layout.getSymbolOffset (*Sym) : 0 );
404+ };
405+
406+ const MCSymbol *const SymA = &Target.getSymA ()->getSymbol ();
392407
393408 MCAsmBackend &Backend = Asm.getBackend ();
394409 bool IsPCRel = Backend.getFixupKindInfo (Fixup.getKind ()).Flags &
@@ -399,26 +414,15 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
399414 std::tie (Type, SignAndSize) =
400415 TargetObjectWriter->getRelocTypeAndSignSize (Target, Fixup, IsPCRel);
401416
402- const MCSectionXCOFF *SymASec =
403- getContainingCsect (cast<MCSymbolXCOFF>(&SymA));
417+ const MCSectionXCOFF *SymASec = getContainingCsect (cast<MCSymbolXCOFF>(SymA));
404418 assert (SectionMap.find (SymASec) != SectionMap.end () &&
405419 " Expected containing csect to exist in map." );
406420
407- // If we could not find SymA directly in SymbolIndexMap, this symbol could
408- // either be a temporary symbol or an undefined symbol. In this case, we
409- // would need to have the relocation reference its csect instead.
410- uint32_t Index = SymbolIndexMap.find (&SymA) != SymbolIndexMap.end ()
411- ? SymbolIndexMap[&SymA]
412- : SymbolIndexMap[SymASec->getQualNameSymbol ()];
413-
421+ const uint32_t Index = getIndex (SymA, SymASec);
414422 if (Type == XCOFF::RelocationType::R_POS)
415423 // The FixedValue should be symbol's virtual address in this object file
416424 // plus any constant value that we might get.
417- // Notice that SymA.isDefined() could return false, but SymASec could still
418- // be a defined csect. One of the example is the TOC-base symbol.
419- FixedValue = SectionMap[SymASec]->Address +
420- (SymA.isDefined () ? Layout.getSymbolOffset (SymA) : 0 ) +
421- Target.getConstant ();
425+ FixedValue = getVirtualAddress (SymA, SymASec) + Target.getConstant ();
422426 else if (Type == XCOFF::RelocationType::R_TOC)
423427 // The FixedValue should be the TC entry offset from TOC-base.
424428 FixedValue = SectionMap[SymASec]->Address - TOCCsects.front ().Address ;
@@ -435,6 +439,33 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
435439 assert (SectionMap.find (RelocationSec) != SectionMap.end () &&
436440 " Expected containing csect to exist in map." );
437441 SectionMap[RelocationSec]->Relocations .push_back (Reloc);
442+
443+ if (!Target.getSymB ())
444+ return ;
445+
446+ const MCSymbol *const SymB = &Target.getSymB ()->getSymbol ();
447+ if (SymA == SymB)
448+ report_fatal_error (" relocation for opposite term is not yet supported" );
449+
450+ const MCSectionXCOFF *SymBSec = getContainingCsect (cast<MCSymbolXCOFF>(SymB));
451+ assert (SectionMap.find (SymBSec) != SectionMap.end () &&
452+ " Expected containing csect to exist in map." );
453+ if (SymASec == SymBSec)
454+ report_fatal_error (
455+ " relocation for paired relocatable term is not yet supported" );
456+
457+ assert (Type == XCOFF::RelocationType::R_POS &&
458+ " SymA must be R_POS here if it's not opposite term or paired "
459+ " relocatable term." );
460+ const uint32_t IndexB = getIndex (SymB, SymBSec);
461+ // SymB must be R_NEG here, given the general form of Target(MCValue) is
462+ // "SymbolA - SymbolB + imm64".
463+ const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
464+ XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
465+ SectionMap[RelocationSec]->Relocations .push_back (RelocB);
466+ // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
467+ // now we just need to fold "- SymbolB" here.
468+ FixedValue -= getVirtualAddress (SymB, SymBSec);
438469}
439470
440471void XCOFFObjectWriter::writeSections (const MCAssembler &Asm,
0 commit comments