From 8c9aa922a94bd788ea061be7555fb5b1db3a5312 Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Sat, 2 Oct 2010 00:13:41 +0000 Subject: [PATCH] This adds a Darwin x86_64 relocation encoding for a subtraction expression where both symbols are "local", that is non-external symbols, and there is no "base" for the symbols used in the expression, that is the section has no non-temporary symbols. This case looks like this: % cat local_reloc_A-B.s .long 0 LB: .long 1 .long LA - LB - 4 .long 2 LA: .long 3 which llvm-mc will not encode without this patch, generates a "unsupported local relocations in difference" error, but the Darwin assembler will encode with relocation entries like this: % otool -rv a.out l.out a.out: Relocation information (__TEXT,__text) 2 entries address pcrel length extern type scattered symbolnum/value 00000008 False long False SUB False 1 (__TEXT,__text) 00000008 False long False UNSIGND False 1 (__TEXT,__text) which is very similar to what is encoded when the symbols don't have the leading 'L' and they are not temporary symbols. Which llvm-mc and the Darwin assembler will encoded like this: Relocation information (__TEXT,__text) 2 entries address pcrel length extern type scattered symbolnum/value 00000008 False long True SUB False B 00000008 False long True UNSIGND False A This is the missing relocation encoding needed to allow the Mach-O x86 Dwarf file and line table to be emitted. So this patch also removes the TODO from the if() statement in MCMachOStreamer::Finish() that didn't call MCDwarfFileTable::Emit() for 64-bit targets. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115389 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCMachOStreamer.cpp | 10 +-------- lib/MC/MachObjectWriter.cpp | 42 +++++++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 42de0ae1b5d..a10a63ee6a4 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -441,15 +441,7 @@ void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { void MCMachOStreamer::Finish() { // Dump out the dwarf file & directory tables and line tables. - if (getContext().hasDwarfFiles() && - // TODO: This not enabled for 64-bit Mach-O targets. As there are needed - // changes in the handling of 64-bit relocation entries for dwarf Mach-O - // sections that need to made. Currently it gets - // LLVM ERROR: unsupported local relocations in difference - // due dealing with "a-b" expressions made up for dwarf line entries - // because the line section has no non-local symbols thus it can't find - // an atom symbol for the base. - getAssembler().getBackend().getPointerSize() != 8) { + if (getContext().hasDwarfFiles()) { const MCSection *DwarfLineSection = getContext().getMachOSection("__DWARF", "__debug_line", MCSectionMachO::S_ATTR_DEBUG, diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index 689aabc333d..4bb05350edd 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -616,22 +616,32 @@ public: 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"); + // The support for the situation where one or both of the symbols would + // require a local relocation is handled just like if the symbols were + // external. This is certainly used in the case of debug sections where + // the section has only temporary symbols and thus the symbols don't have + // base symbols. This is encoded using the section ordinal and + // non-extern relocation entries. // 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) + // a single SIGNED relocation); reject it for now. Except the case where + // both symbols don't have a base, equal but both NULL. + if (A_Base == B_Base && A_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); + Value += Layout.getSymbolAddress(&A_SD) - + (A_Base == NULL ? 0 : Layout.getSymbolAddress(A_Base)); + Value -= Layout.getSymbolAddress(&B_SD) - + (B_Base == NULL ? 0 : Layout.getSymbolAddress(B_Base)); - Index = A_Base->getIndex(); - IsExtern = 1; + if (A_Base) { + Index = A_Base->getIndex(); + IsExtern = 1; + } + else { + Index = A_SD.getFragment()->getParent()->getOrdinal() + 1; + IsExtern = 0; + } Type = RIT_X86_64_Unsigned; MachRelocationEntry MRE; @@ -643,8 +653,14 @@ public: (Type << 28)); Relocations[Fragment->getParent()].push_back(MRE); - Index = B_Base->getIndex(); - IsExtern = 1; + if (B_Base) { + Index = B_Base->getIndex(); + IsExtern = 1; + } + else { + Index = B_SD.getFragment()->getParent()->getOrdinal() + 1; + IsExtern = 0; + } Type = RIT_X86_64_Subtractor; } else { const MCSymbol *Symbol = &Target.getSymA()->getSymbol(); -- 2.34.1