mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-15 05:24:01 +00:00
On ELF we need to know which symbols are used in relocations to decide if
they should be in the symbol table or not. Instead of "guessing", just compute the symbol table after the relocations are known. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115619 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -44,7 +44,7 @@ public:
|
|||||||
bool IsPCRel,
|
bool IsPCRel,
|
||||||
const MCFragment *DF) const;
|
const MCFragment *DF) const;
|
||||||
|
|
||||||
virtual void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout);
|
virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
@ -90,7 +90,7 @@ public:
|
|||||||
/// This routine is called by the assembler after layout and relaxation is
|
/// This routine is called by the assembler after layout and relaxation is
|
||||||
/// complete, fixups have been evaluated and applied, and relocations
|
/// complete, fixups have been evaluated and applied, and relocations
|
||||||
/// generated.
|
/// generated.
|
||||||
virtual void WriteObject(const MCAssembler &Asm,
|
virtual void WriteObject(MCAssembler &Asm,
|
||||||
const MCAsmLayout &Layout) = 0;
|
const MCAsmLayout &Layout) = 0;
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
@ -41,7 +41,7 @@ public:
|
|||||||
bool IsPCRel,
|
bool IsPCRel,
|
||||||
const MCFragment *DF) const;
|
const MCFragment *DF) const;
|
||||||
|
|
||||||
virtual void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout);
|
virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/MC/ELFObjectWriter.h"
|
#include "llvm/MC/ELFObjectWriter.h"
|
||||||
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/ADT/Twine.h"
|
#include "llvm/ADT/Twine.h"
|
||||||
@ -102,7 +103,9 @@ namespace {
|
|||||||
struct ELFRelocationEntry {
|
struct ELFRelocationEntry {
|
||||||
// Make these big enough for both 32-bit and 64-bit
|
// Make these big enough for both 32-bit and 64-bit
|
||||||
uint64_t r_offset;
|
uint64_t r_offset;
|
||||||
uint64_t r_info;
|
int Index;
|
||||||
|
unsigned Type;
|
||||||
|
const MCSymbol *Symbol;
|
||||||
uint64_t r_addend;
|
uint64_t r_addend;
|
||||||
|
|
||||||
// Support lexicographic sorting.
|
// Support lexicographic sorting.
|
||||||
@ -111,6 +114,8 @@ namespace {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SmallPtrSet<const MCSymbol *, 16> UsedInReloc;
|
||||||
|
|
||||||
llvm::DenseMap<const MCSectionData*,
|
llvm::DenseMap<const MCSectionData*,
|
||||||
std::vector<ELFRelocationEntry> > Relocations;
|
std::vector<ELFRelocationEntry> > Relocations;
|
||||||
DenseMap<const MCSection*, uint64_t> SectionStringTableIndex;
|
DenseMap<const MCSection*, uint64_t> SectionStringTableIndex;
|
||||||
@ -126,6 +131,8 @@ namespace {
|
|||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
int NumRegularSections;
|
||||||
|
|
||||||
ELFObjectWriter *Writer;
|
ELFObjectWriter *Writer;
|
||||||
|
|
||||||
raw_ostream &OS;
|
raw_ostream &OS;
|
||||||
@ -262,8 +269,6 @@ namespace {
|
|||||||
void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout);
|
void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout);
|
||||||
|
|
||||||
void ExecutePostLayoutBinding(MCAssembler &Asm) {
|
void ExecutePostLayoutBinding(MCAssembler &Asm) {
|
||||||
// Compute symbol table information.
|
|
||||||
ComputeSymbolTable(Asm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
|
void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
|
||||||
@ -279,7 +284,7 @@ namespace {
|
|||||||
bool IsPCRel,
|
bool IsPCRel,
|
||||||
const MCFragment *DF) const;
|
const MCFragment *DF) const;
|
||||||
|
|
||||||
void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout);
|
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -526,12 +531,13 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
|
|||||||
MCValue Target,
|
MCValue Target,
|
||||||
uint64_t &FixedValue) {
|
uint64_t &FixedValue) {
|
||||||
int64_t Addend = 0;
|
int64_t Addend = 0;
|
||||||
unsigned Index = 0;
|
int Index = 0;
|
||||||
int64_t Value = Target.getConstant();
|
int64_t Value = Target.getConstant();
|
||||||
|
const MCSymbol *Symbol = 0;
|
||||||
|
|
||||||
bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
|
bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
|
||||||
if (!Target.isAbsolute()) {
|
if (!Target.isAbsolute()) {
|
||||||
const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
|
Symbol = &Target.getSymA()->getSymbol();
|
||||||
MCSymbolData &SD = Asm.getSymbolData(*Symbol);
|
MCSymbolData &SD = Asm.getSymbolData(*Symbol);
|
||||||
MCFragment *F = SD.getFragment();
|
MCFragment *F = SD.getFragment();
|
||||||
|
|
||||||
@ -560,13 +566,15 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
|
|||||||
|
|
||||||
bool RelocOnSymbol = ShouldRelocOnSymbol(SD, Target);
|
bool RelocOnSymbol = ShouldRelocOnSymbol(SD, Target);
|
||||||
if (!RelocOnSymbol) {
|
if (!RelocOnSymbol) {
|
||||||
Index = F->getParent()->getOrdinal() + LocalSymbolData.size() + 1;
|
Index = F->getParent()->getOrdinal();
|
||||||
|
|
||||||
MCSectionData *FSD = F->getParent();
|
MCSectionData *FSD = F->getParent();
|
||||||
// Offset of the symbol in the section
|
// Offset of the symbol in the section
|
||||||
Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
|
Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
|
||||||
} else
|
} else {
|
||||||
Index = getSymbolIndexInSymbolTable(Asm, Symbol);
|
UsedInReloc.insert(Symbol);
|
||||||
|
Index = -1;
|
||||||
|
}
|
||||||
Addend = Value;
|
Addend = Value;
|
||||||
// Compensate for the addend on i386.
|
// Compensate for the addend on i386.
|
||||||
if (Is64Bit)
|
if (Is64Bit)
|
||||||
@ -641,15 +649,9 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
|
|||||||
|
|
||||||
ELFRelocationEntry ERE;
|
ELFRelocationEntry ERE;
|
||||||
|
|
||||||
if (Is64Bit) {
|
ERE.Index = Index;
|
||||||
struct ELF::Elf64_Rela ERE64;
|
ERE.Type = Type;
|
||||||
ERE64.setSymbolAndType(Index, Type);
|
ERE.Symbol = Symbol;
|
||||||
ERE.r_info = ERE64.r_info;
|
|
||||||
} else {
|
|
||||||
struct ELF::Elf32_Rela ERE32;
|
|
||||||
ERE32.setSymbolAndType(Index, Type);
|
|
||||||
ERE.r_info = ERE32.r_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
|
ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
|
||||||
|
|
||||||
@ -671,11 +673,12 @@ ELFObjectWriterImpl::getSymbolIndexInSymbolTable(const MCAssembler &Asm,
|
|||||||
return SD.getIndex() + /* empty symbol */ 1;
|
return SD.getIndex() + /* empty symbol */ 1;
|
||||||
|
|
||||||
// External or undefined symbol.
|
// External or undefined symbol.
|
||||||
return SD.getIndex() + Asm.size() + /* empty symbol */ 1;
|
return SD.getIndex() + NumRegularSections + /* empty symbol */ 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
|
void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
|
||||||
// Build section lookup table.
|
// Build section lookup table.
|
||||||
|
NumRegularSections = Asm.size();
|
||||||
DenseMap<const MCSection*, uint8_t> SectionIndexMap;
|
DenseMap<const MCSection*, uint8_t> SectionIndexMap;
|
||||||
unsigned Index = 1;
|
unsigned Index = 1;
|
||||||
for (MCAssembler::iterator it = Asm.begin(),
|
for (MCAssembler::iterator it = Asm.begin(),
|
||||||
@ -698,6 +701,9 @@ void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
|
|||||||
if (it->isExternal() || Symbol.isUndefined())
|
if (it->isExternal() || Symbol.isUndefined())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (Symbol.isTemporary() && !UsedInReloc.count(&Symbol))
|
||||||
|
continue;
|
||||||
|
|
||||||
uint64_t &Entry = StringIndexMap[Symbol.getName()];
|
uint64_t &Entry = StringIndexMap[Symbol.getName()];
|
||||||
if (!Entry) {
|
if (!Entry) {
|
||||||
Entry = StringTable.size();
|
Entry = StringTable.size();
|
||||||
@ -734,6 +740,10 @@ void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
|
|||||||
if (Symbol.isVariable())
|
if (Symbol.isVariable())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (Symbol.isUndefined() && !UsedInReloc.count(&Symbol)
|
||||||
|
&& Symbol.isTemporary())
|
||||||
|
continue;
|
||||||
|
|
||||||
uint64_t &Entry = StringIndexMap[Symbol.getName()];
|
uint64_t &Entry = StringIndexMap[Symbol.getName()];
|
||||||
if (!Entry) {
|
if (!Entry) {
|
||||||
Entry = StringTable.size();
|
Entry = StringTable.size();
|
||||||
@ -843,13 +853,19 @@ void ELFObjectWriterImpl::WriteRelocationsFragment(const MCAssembler &Asm,
|
|||||||
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
|
||||||
ELFRelocationEntry entry = Relocs[e - i - 1];
|
ELFRelocationEntry entry = Relocs[e - i - 1];
|
||||||
|
|
||||||
|
if (entry.Index < 0)
|
||||||
|
entry.Index = getSymbolIndexInSymbolTable(Asm, entry.Symbol);
|
||||||
|
else
|
||||||
|
entry.Index += LocalSymbolData.size() + 1;
|
||||||
if (Is64Bit) {
|
if (Is64Bit) {
|
||||||
char buf[8];
|
char buf[8];
|
||||||
|
|
||||||
String64(buf, entry.r_offset);
|
String64(buf, entry.r_offset);
|
||||||
F->getContents() += StringRef(buf, 8);
|
F->getContents() += StringRef(buf, 8);
|
||||||
|
|
||||||
String64(buf, entry.r_info);
|
struct ELF::Elf64_Rela ERE64;
|
||||||
|
ERE64.setSymbolAndType(entry.Index, entry.Type);
|
||||||
|
String64(buf, ERE64.r_info);
|
||||||
F->getContents() += StringRef(buf, 8);
|
F->getContents() += StringRef(buf, 8);
|
||||||
|
|
||||||
if (HasRelocationAddend) {
|
if (HasRelocationAddend) {
|
||||||
@ -862,7 +878,9 @@ void ELFObjectWriterImpl::WriteRelocationsFragment(const MCAssembler &Asm,
|
|||||||
String32(buf, entry.r_offset);
|
String32(buf, entry.r_offset);
|
||||||
F->getContents() += StringRef(buf, 4);
|
F->getContents() += StringRef(buf, 4);
|
||||||
|
|
||||||
String32(buf, entry.r_info);
|
struct ELF::Elf32_Rela ERE32;
|
||||||
|
ERE32.setSymbolAndType(entry.Index, entry.Type);
|
||||||
|
String32(buf, ERE32.r_info);
|
||||||
F->getContents() += StringRef(buf, 4);
|
F->getContents() += StringRef(buf, 4);
|
||||||
|
|
||||||
if (HasRelocationAddend) {
|
if (HasRelocationAddend) {
|
||||||
@ -976,8 +994,11 @@ bool ELFObjectWriterImpl::IsFixupFullyResolved(const MCAssembler &Asm,
|
|||||||
return !SectionB && BaseSection == SectionA;
|
return !SectionB && BaseSection == SectionA;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ELFObjectWriterImpl::WriteObject(const MCAssembler &Asm,
|
void ELFObjectWriterImpl::WriteObject(MCAssembler &Asm,
|
||||||
const MCAsmLayout &Layout) {
|
const MCAsmLayout &Layout) {
|
||||||
|
// Compute symbol table information.
|
||||||
|
ComputeSymbolTable(Asm);
|
||||||
|
|
||||||
CreateMetadataSections(const_cast<MCAssembler&>(Asm),
|
CreateMetadataSections(const_cast<MCAssembler&>(Asm),
|
||||||
const_cast<MCAsmLayout&>(Layout));
|
const_cast<MCAsmLayout&>(Layout));
|
||||||
|
|
||||||
@ -1142,7 +1163,7 @@ bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm,
|
|||||||
IsPCRel, DF);
|
IsPCRel, DF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ELFObjectWriter::WriteObject(const MCAssembler &Asm,
|
void ELFObjectWriter::WriteObject(MCAssembler &Asm,
|
||||||
const MCAsmLayout &Layout) {
|
const MCAsmLayout &Layout) {
|
||||||
((ELFObjectWriterImpl*) Impl)->WriteObject(Asm, Layout);
|
((ELFObjectWriterImpl*) Impl)->WriteObject(Asm, Layout);
|
||||||
}
|
}
|
||||||
|
@ -156,22 +156,6 @@ 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!");
|
||||||
|
|
||||||
@ -179,11 +163,6 @@ void MCELFStreamer::EmitLabel(MCSymbol *Symbol) {
|
|||||||
|
|
||||||
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
|
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
|
||||||
@ -520,36 +499,6 @@ void MCELFStreamer::Finish() {
|
|||||||
SectData.setAlignment(ByteAlignment);
|
SectData.setAlignment(ByteAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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();
|
this->MCObjectStreamer::Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1360,7 +1360,7 @@ bool MachObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm,
|
|||||||
IsPCRel, DF);
|
IsPCRel, DF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MachObjectWriter::WriteObject(const MCAssembler &Asm,
|
void MachObjectWriter::WriteObject(MCAssembler &Asm,
|
||||||
const MCAsmLayout &Layout) {
|
const MCAsmLayout &Layout) {
|
||||||
((MachObjectWriterImpl*) Impl)->WriteObject(Asm, Layout);
|
((MachObjectWriterImpl*) Impl)->WriteObject(Asm, Layout);
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ public:
|
|||||||
bool IsPCRel,
|
bool IsPCRel,
|
||||||
const MCFragment *DF) const;
|
const MCFragment *DF) const;
|
||||||
|
|
||||||
void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout);
|
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -703,7 +703,7 @@ bool WinCOFFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm,
|
void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
|
||||||
const MCAsmLayout &Layout) {
|
const MCAsmLayout &Layout) {
|
||||||
// Assign symbol and section indexes and offsets.
|
// Assign symbol and section indexes and offsets.
|
||||||
Header.NumberOfSections = 0;
|
Header.NumberOfSections = 0;
|
||||||
|
Reference in New Issue
Block a user