mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-01 02:33:44 +00:00
Move ELF to HasReliableSymbolDifference=true. Also take the opportunity to put
symbols defined in merge sections in independent atoms. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114786 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b0ba0f4170
commit
73ffea47d2
@ -487,6 +487,13 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const MCSymbolData *getAtom(const MCSymbolData &SD) {
|
||||||
|
if (!SD.getFragment())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return SD.getFragment()->getAtom();
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: this is currently X86/X86_64 only
|
// FIXME: this is currently X86/X86_64 only
|
||||||
void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
|
void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
|
||||||
const MCAsmLayout &Layout,
|
const MCAsmLayout &Layout,
|
||||||
@ -502,7 +509,7 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
|
|||||||
if (!Target.isAbsolute()) {
|
if (!Target.isAbsolute()) {
|
||||||
const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
|
const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
|
||||||
MCSymbolData &SD = Asm.getSymbolData(*Symbol);
|
MCSymbolData &SD = Asm.getSymbolData(*Symbol);
|
||||||
const MCSymbolData *Base = Asm.getAtom(Layout, &SD);
|
const MCSymbolData *Base = getAtom(SD);
|
||||||
MCFragment *F = SD.getFragment();
|
MCFragment *F = SD.getFragment();
|
||||||
|
|
||||||
// Avoid relocations for cases like jumps and calls in the same file.
|
// Avoid relocations for cases like jumps and calls in the same file.
|
||||||
@ -515,7 +522,7 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Base) {
|
if (Base) {
|
||||||
if (F && !SD.isExternal()) {
|
if (Base != &SD) {
|
||||||
Index = F->getParent()->getOrdinal() + LocalSymbolData.size() + 1;
|
Index = F->getParent()->getOrdinal() + LocalSymbolData.size() + 1;
|
||||||
|
|
||||||
MCSectionData *FSD = F->getParent();
|
MCSectionData *FSD = F->getParent();
|
||||||
@ -523,8 +530,6 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
|
|||||||
Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
|
Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
|
||||||
} else
|
} else
|
||||||
Index = getSymbolIndexInSymbolTable(Asm, Symbol);
|
Index = getSymbolIndexInSymbolTable(Asm, Symbol);
|
||||||
if (Base != &SD)
|
|
||||||
Value += Layout.getSymbolAddress(&SD) - Layout.getSymbolAddress(Base);
|
|
||||||
Addend = Value;
|
Addend = Value;
|
||||||
// Compensate for the addend on i386.
|
// Compensate for the addend on i386.
|
||||||
if (Is64Bit)
|
if (Is64Bit)
|
||||||
@ -537,11 +542,14 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
|
|||||||
|
|
||||||
MCSectionData *FSD = F->getParent();
|
MCSectionData *FSD = F->getParent();
|
||||||
// Offset of the symbol in the section
|
// Offset of the symbol in the section
|
||||||
Addend = Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
|
Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
|
||||||
} else {
|
} else {
|
||||||
FixedValue = Value;
|
Index = getSymbolIndexInSymbolTable(Asm, Symbol);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
Addend = Value;
|
||||||
|
// Compensate for the addend on i386.
|
||||||
|
if (Is64Bit)
|
||||||
|
Value = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,20 +149,43 @@ void MCELFStreamer::InitSections() {
|
|||||||
SetSectionText();
|
SetSectionText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isSymbolLinkerVisible(const MCAssembler &Asm,
|
||||||
|
const MCSymbolData &Data) {
|
||||||
|
const MCSymbol &Symbol = Data.getSymbol();
|
||||||
|
// Absolute temporary labels are never visible.
|
||||||
|
if (!Symbol.isInSection())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Asm.getBackend().doesSectionRequireSymbols(Symbol.getSection()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!Data.isExternal())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return Asm.isSymbolLinkerVisible(Symbol);
|
||||||
|
}
|
||||||
|
|
||||||
void MCELFStreamer::EmitLabel(MCSymbol *Symbol) {
|
void MCELFStreamer::EmitLabel(MCSymbol *Symbol) {
|
||||||
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
|
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
|
||||||
|
|
||||||
|
Symbol->setSection(*CurSection);
|
||||||
|
|
||||||
|
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
|
||||||
|
|
||||||
|
// We have to create a new fragment if this is an atom defining symbol,
|
||||||
|
// fragments cannot span atoms.
|
||||||
|
if (isSymbolLinkerVisible(getAssembler(), SD))
|
||||||
|
new MCDataFragment(getCurrentSectionData());
|
||||||
|
|
||||||
// FIXME: This is wasteful, we don't necessarily need to create a data
|
// FIXME: This is wasteful, we don't necessarily need to create a data
|
||||||
// fragment. Instead, we should mark the symbol as pointing into the data
|
// fragment. Instead, we should mark the symbol as pointing into the data
|
||||||
// fragment if it exists, otherwise we should just queue the label and set its
|
// fragment if it exists, otherwise we should just queue the label and set its
|
||||||
// fragment pointer when we emit the next fragment.
|
// fragment pointer when we emit the next fragment.
|
||||||
MCDataFragment *F = getOrCreateDataFragment();
|
MCDataFragment *F = getOrCreateDataFragment();
|
||||||
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
|
|
||||||
assert(!SD.getFragment() && "Unexpected fragment on symbol data!");
|
assert(!SD.getFragment() && "Unexpected fragment on symbol data!");
|
||||||
SD.setFragment(F);
|
SD.setFragment(F);
|
||||||
SD.setOffset(F->getContents().size());
|
SD.setOffset(F->getContents().size());
|
||||||
|
|
||||||
Symbol->setSection(*CurSection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
|
void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
|
||||||
@ -476,7 +499,37 @@ void MCELFStreamer::EmitInstruction(const MCInst &Inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MCELFStreamer::Finish() {
|
void MCELFStreamer::Finish() {
|
||||||
getAssembler().Finish();
|
// FIXME: We create more atoms than it is necessary. Some relocations to
|
||||||
|
// merge sections can be implemented with section address + offset,
|
||||||
|
// figure out which ones and why.
|
||||||
|
|
||||||
|
// First, scan the symbol table to build a lookup table from fragments to
|
||||||
|
// defining symbols.
|
||||||
|
DenseMap<const MCFragment*, MCSymbolData*> DefiningSymbolMap;
|
||||||
|
for (MCAssembler::symbol_iterator it = getAssembler().symbol_begin(),
|
||||||
|
ie = getAssembler().symbol_end(); it != ie; ++it) {
|
||||||
|
if (isSymbolLinkerVisible(getAssembler(), *it) &&
|
||||||
|
it->getFragment()) {
|
||||||
|
// An atom defining symbol should never be internal to a fragment.
|
||||||
|
assert(it->getOffset() == 0 && "Invalid offset in atom defining symbol!");
|
||||||
|
DefiningSymbolMap[it->getFragment()] = it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the fragment atom associations by tracking the last seen atom defining
|
||||||
|
// symbol.
|
||||||
|
for (MCAssembler::iterator it = getAssembler().begin(),
|
||||||
|
ie = getAssembler().end(); it != ie; ++it) {
|
||||||
|
MCSymbolData *CurrentAtom = 0;
|
||||||
|
for (MCSectionData::iterator it2 = it->begin(),
|
||||||
|
ie2 = it->end(); it2 != ie2; ++it2) {
|
||||||
|
if (MCSymbolData *SD = DefiningSymbolMap.lookup(it2))
|
||||||
|
CurrentAtom = SD;
|
||||||
|
it2->setAtom(CurrentAtom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->MCObjectStreamer::Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
MCStreamer *llvm::createELFStreamer(MCContext &Context, TargetAsmBackend &TAB,
|
MCStreamer *llvm::createELFStreamer(MCContext &Context, TargetAsmBackend &TAB,
|
||||||
|
@ -191,6 +191,12 @@ public:
|
|||||||
: X86AsmBackend(T), OSType(_OSType) {
|
: X86AsmBackend(T), OSType(_OSType) {
|
||||||
HasAbsolutizedSet = true;
|
HasAbsolutizedSet = true;
|
||||||
HasScatteredSymbols = true;
|
HasScatteredSymbols = true;
|
||||||
|
HasReliableSymbolDifference = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
|
||||||
|
const MCSectionELF &ES = static_cast<const MCSectionELF&>(Section);
|
||||||
|
return ES.getFlags() & MCSectionELF::SHF_MERGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isVirtualSection(const MCSection &Section) const {
|
bool isVirtualSection(const MCSection &Section) const {
|
||||||
|
@ -83,7 +83,7 @@ declare i32 @puts(i8* nocapture) nounwind
|
|||||||
; 64: # Relocation 2
|
; 64: # Relocation 2
|
||||||
; 64: (('r_offset', 15)
|
; 64: (('r_offset', 15)
|
||||||
; 64: ('r_type', 10)
|
; 64: ('r_type', 10)
|
||||||
; 64: ('r_addend', 6)
|
; 64: ('r_addend', 0)
|
||||||
; 64: ),
|
; 64: ),
|
||||||
; 64: # Relocation 3
|
; 64: # Relocation 3
|
||||||
; 64: (('r_offset', 20)
|
; 64: (('r_offset', 20)
|
||||||
|
26
test/MC/ELF/merge.s
Normal file
26
test/MC/ELF/merge.s
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s
|
||||||
|
|
||||||
|
// Test that relocations with local symbols in a mergeable section are done
|
||||||
|
// with a reference to the symbol. Not sure if this is a linker limitation,
|
||||||
|
// but this matches the behavior of gas.
|
||||||
|
|
||||||
|
.section .sec1,"aM",@progbits,16
|
||||||
|
.Lfoo:
|
||||||
|
.text
|
||||||
|
movsd .Lfoo(%rip), %xmm1
|
||||||
|
|
||||||
|
// Relocation refers to symbol 1
|
||||||
|
|
||||||
|
// CHECK: ('_relocations', [
|
||||||
|
// CHECK-NEXT: # Relocation 0
|
||||||
|
// CHECK-NEXT: (('r_offset',
|
||||||
|
// CHECK-NEXT: ('r_sym', 1)
|
||||||
|
// CHECK-NEXT: ('r_type',
|
||||||
|
// CHECK-NEXT: ('r_addend',
|
||||||
|
// CHECK-NEXT: ),
|
||||||
|
// CHECK-NEXT: ])
|
||||||
|
|
||||||
|
// Symbol number 1 is .Lfoo
|
||||||
|
|
||||||
|
// CHECK: # Symbol 1
|
||||||
|
// CHECK-NEXT: (('st_name', 1) # '.Lfoo'
|
Loading…
x
Reference in New Issue
Block a user