forked from OSchip/llvm-project
Move ELF to HasReliableSymbolDifference=true. Also take the opportunity to put
symbols defined in merge sections in independent atoms. llvm-svn: 114786
This commit is contained in:
parent
b590a927cd
commit
75d65b9a03
|
@ -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
|
||||
void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
|
@ -502,7 +509,7 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
|
|||
if (!Target.isAbsolute()) {
|
||||
const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
|
||||
MCSymbolData &SD = Asm.getSymbolData(*Symbol);
|
||||
const MCSymbolData *Base = Asm.getAtom(Layout, &SD);
|
||||
const MCSymbolData *Base = getAtom(SD);
|
||||
MCFragment *F = SD.getFragment();
|
||||
|
||||
// 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 (F && !SD.isExternal()) {
|
||||
if (Base != &SD) {
|
||||
Index = F->getParent()->getOrdinal() + LocalSymbolData.size() + 1;
|
||||
|
||||
MCSectionData *FSD = F->getParent();
|
||||
|
@ -523,8 +530,6 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
|
|||
Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
|
||||
} else
|
||||
Index = getSymbolIndexInSymbolTable(Asm, Symbol);
|
||||
if (Base != &SD)
|
||||
Value += Layout.getSymbolAddress(&SD) - Layout.getSymbolAddress(Base);
|
||||
Addend = Value;
|
||||
// Compensate for the addend on i386.
|
||||
if (Is64Bit)
|
||||
|
@ -537,11 +542,14 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
|
|||
|
||||
MCSectionData *FSD = F->getParent();
|
||||
// Offset of the symbol in the section
|
||||
Addend = Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
|
||||
Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
|
||||
} else {
|
||||
FixedValue = Value;
|
||||
return;
|
||||
Index = getSymbolIndexInSymbolTable(Asm, Symbol);
|
||||
}
|
||||
Addend = Value;
|
||||
// Compensate for the addend on i386.
|
||||
if (Is64Bit)
|
||||
Value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -149,20 +149,43 @@ void MCELFStreamer::InitSections() {
|
|||
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) {
|
||||
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
|
||||
// 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 pointer when we emit the next fragment.
|
||||
MCDataFragment *F = getOrCreateDataFragment();
|
||||
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
|
||||
|
||||
assert(!SD.getFragment() && "Unexpected fragment on symbol data!");
|
||||
SD.setFragment(F);
|
||||
SD.setOffset(F->getContents().size());
|
||||
|
||||
Symbol->setSection(*CurSection);
|
||||
}
|
||||
|
||||
void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
|
||||
|
@ -476,7 +499,37 @@ void MCELFStreamer::EmitInstruction(const MCInst &Inst) {
|
|||
}
|
||||
|
||||
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,
|
||||
|
|
|
@ -191,6 +191,12 @@ public:
|
|||
: X86AsmBackend(T), OSType(_OSType) {
|
||||
HasAbsolutizedSet = 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 {
|
||||
|
|
|
@ -83,7 +83,7 @@ declare i32 @puts(i8* nocapture) nounwind
|
|||
; 64: # Relocation 2
|
||||
; 64: (('r_offset', 15)
|
||||
; 64: ('r_type', 10)
|
||||
; 64: ('r_addend', 6)
|
||||
; 64: ('r_addend', 0)
|
||||
; 64: ),
|
||||
; 64: # Relocation 3
|
||||
; 64: (('r_offset', 20)
|
||||
|
|
|
@ -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…
Reference in New Issue