//===----------------------------------------------------------------------===//
#include "llvm/MC/ELFObjectWriter.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
struct ELFRelocationEntry {
// Make these big enough for both 32-bit and 64-bit
uint64_t r_offset;
- uint64_t r_info;
+ int Index;
+ unsigned Type;
+ const MCSymbol *Symbol;
uint64_t r_addend;
// Support lexicographic sorting.
}
};
+ SmallPtrSet<const MCSymbol *, 16> UsedInReloc;
+
llvm::DenseMap<const MCSectionData*,
std::vector<ELFRelocationEntry> > Relocations;
DenseMap<const MCSection*, uint64_t> SectionStringTableIndex;
/// @}
+ int NumRegularSections;
+
ELFObjectWriter *Writer;
raw_ostream &OS;
void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout);
void ExecutePostLayoutBinding(MCAssembler &Asm) {
- // Compute symbol table information.
- ComputeSymbolTable(Asm);
}
void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
bool IsPCRel,
const MCFragment *DF) const;
- void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout);
+ void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
};
}
MCValue Target,
uint64_t &FixedValue) {
int64_t Addend = 0;
- unsigned Index = 0;
+ int Index = 0;
int64_t Value = Target.getConstant();
+ const MCSymbol *Symbol = 0;
bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
if (!Target.isAbsolute()) {
- const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
+ Symbol = &Target.getSymA()->getSymbol();
MCSymbolData &SD = Asm.getSymbolData(*Symbol);
MCFragment *F = SD.getFragment();
bool RelocOnSymbol = ShouldRelocOnSymbol(SD, Target);
if (!RelocOnSymbol) {
- Index = F->getParent()->getOrdinal() + LocalSymbolData.size() + 1;
+ Index = F->getParent()->getOrdinal();
MCSectionData *FSD = F->getParent();
// Offset of the symbol in the section
Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
- } else
- Index = getSymbolIndexInSymbolTable(Asm, Symbol);
+ } else {
+ UsedInReloc.insert(Symbol);
+ Index = -1;
+ }
Addend = Value;
// Compensate for the addend on i386.
if (Is64Bit)
ELFRelocationEntry ERE;
- if (Is64Bit) {
- struct ELF::Elf64_Rela ERE64;
- ERE64.setSymbolAndType(Index, Type);
- ERE.r_info = ERE64.r_info;
- } else {
- struct ELF::Elf32_Rela ERE32;
- ERE32.setSymbolAndType(Index, Type);
- ERE.r_info = ERE32.r_info;
- }
+ ERE.Index = Index;
+ ERE.Type = Type;
+ ERE.Symbol = Symbol;
ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
return SD.getIndex() + /* empty symbol */ 1;
// External or undefined symbol.
- return SD.getIndex() + Asm.size() + /* empty symbol */ 1;
+ return SD.getIndex() + NumRegularSections + /* empty symbol */ 1;
}
void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
// Build section lookup table.
+ NumRegularSections = Asm.size();
DenseMap<const MCSection*, uint8_t> SectionIndexMap;
unsigned Index = 1;
for (MCAssembler::iterator it = Asm.begin(),
if (it->isExternal() || Symbol.isUndefined())
continue;
+ if (Symbol.isTemporary() && !UsedInReloc.count(&Symbol))
+ continue;
+
uint64_t &Entry = StringIndexMap[Symbol.getName()];
if (!Entry) {
Entry = StringTable.size();
if (Symbol.isVariable())
continue;
+ if (Symbol.isUndefined() && !UsedInReloc.count(&Symbol)
+ && Symbol.isTemporary())
+ continue;
+
uint64_t &Entry = StringIndexMap[Symbol.getName()];
if (!Entry) {
Entry = StringTable.size();
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
ELFRelocationEntry entry = Relocs[e - i - 1];
+ if (entry.Index < 0)
+ entry.Index = getSymbolIndexInSymbolTable(Asm, entry.Symbol);
+ else
+ entry.Index += LocalSymbolData.size() + 1;
if (Is64Bit) {
char buf[8];
String64(buf, entry.r_offset);
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);
if (HasRelocationAddend) {
String32(buf, entry.r_offset);
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);
if (HasRelocationAddend) {
return !SectionB && BaseSection == SectionA;
}
-void ELFObjectWriterImpl::WriteObject(const MCAssembler &Asm,
+void ELFObjectWriterImpl::WriteObject(MCAssembler &Asm,
const MCAsmLayout &Layout) {
+ // Compute symbol table information.
+ ComputeSymbolTable(Asm);
+
CreateMetadataSections(const_cast<MCAssembler&>(Asm),
const_cast<MCAsmLayout&>(Layout));
IsPCRel, DF);
}
-void ELFObjectWriter::WriteObject(const MCAssembler &Asm,
+void ELFObjectWriter::WriteObject(MCAssembler &Asm,
const MCAsmLayout &Layout) {
((ELFObjectWriterImpl*) Impl)->WriteObject(Asm, Layout);
}
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!");
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
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();
}