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
This commit is contained in:
Kevin Enderby 2010-10-02 00:13:41 +00:00
parent 5f2d1fa0f7
commit 8c9aa922a9
2 changed files with 30 additions and 22 deletions

View File

@ -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,

View File

@ -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();