- if (Target.isAbsolute()) { // constant
- // SymbolNum of 0 indicates the absolute section.
- Type = RIT_X86_64_Unsigned;
- Index = 0;
-
- // FIXME: I believe this is broken, I don't think the linker can
- // understand it. I think it would require a local relocation, but I'm not
- // sure if that would work either. The official way to get an absolute
- // PCrel relocation is to use an absolute symbol (which we don't support
- // yet).
- if (IsPCRel) {
- IsExtern = 1;
- Type = RIT_X86_64_Branch;
- }
- } else if (Target.getSymB()) { // A - B + constant
- const MCSymbol *A = &Target.getSymA()->getSymbol();
- MCSymbolData &A_SD = Asm.getSymbolData(*A);
- const MCSymbolData *A_Base = Asm.getAtom(Layout, &A_SD);
-
- const MCSymbol *B = &Target.getSymB()->getSymbol();
- MCSymbolData &B_SD = Asm.getSymbolData(*B);
- const MCSymbolData *B_Base = Asm.getAtom(Layout, &B_SD);
-
- // Neither symbol can be modified.
- if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
- Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None)
- report_fatal_error("unsupported relocation of modified symbol");
-
- // We don't support PCrel relocations of differences. Darwin 'as' doesn't
- // implement most of these correctly.
- if (IsPCRel)
- report_fatal_error("unsupported pc-relative relocation of difference");
-
- // We don't currently support any situation where one or both of the
- // symbols would require a local relocation. This is almost certainly
- // unused and may not be possible to encode correctly.
- if (!A_Base || !B_Base)
- report_fatal_error("unsupported local relocations in difference");
-
- // Darwin 'as' doesn't emit correct relocations for this (it ends up with
- // a single SIGNED relocation); reject it for now.
- if (A_Base == B_Base)
- report_fatal_error("unsupported relocation with identical base");
-
- Value += Layout.getSymbolAddress(&A_SD) - Layout.getSymbolAddress(A_Base);
- Value -= Layout.getSymbolAddress(&B_SD) - Layout.getSymbolAddress(B_Base);
-
- Index = A_Base->getIndex();
- IsExtern = 1;
- Type = RIT_X86_64_Unsigned;
-
- MachRelocationEntry MRE;
- MRE.Word0 = FixupOffset;
- MRE.Word1 = ((Index << 0) |
- (IsPCRel << 24) |
- (Log2Size << 25) |
- (IsExtern << 27) |
- (Type << 28));
- Relocations[Fragment->getParent()].push_back(MRE);
-
- Index = B_Base->getIndex();
- IsExtern = 1;
- Type = RIT_X86_64_Subtractor;
- } else {
- const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
- MCSymbolData &SD = Asm.getSymbolData(*Symbol);
- const MCSymbolData *Base = Asm.getAtom(Layout, &SD);
-
- // Relocations inside debug sections always use local relocations when
- // possible. This seems to be done because the debugger doesn't fully
- // understand x86_64 relocation entries, and expects to find values that
- // have already been fixed up.
- if (Symbol->isInSection()) {
- const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(
- Fragment->getParent()->getSection());
- if (Section.hasAttribute(MCSectionMachO::S_ATTR_DEBUG))
- Base = 0;
- }