Index: lib/MC/ELFObjectWriter.cpp |
=================================================================== |
--- lib/MC/ELFObjectWriter.cpp (revision 118813) |
+++ lib/MC/ELFObjectWriter.cpp (working copy) |
@@ -98,266 +98,46 @@ |
} |
} |
-namespace { |
+//===- ELFObjectWriter -------------------===// |
+ELFObjectWriter::~ELFObjectWriter() |
+{} |
- class ELFObjectWriterImpl { |
- /*static bool isFixupKindX86RIPRel(unsigned Kind) { |
- return Kind == X86::reloc_riprel_4byte || |
- Kind == X86::reloc_riprel_4byte_movq_load; |
- }*/ |
+void ELFObjectWriter::String8(MCDataFragment &F, uint8_t Value) { |
+ char buf[1]; |
+ buf[0] = Value; |
+ F.getContents() += StringRef(buf, 1); |
+} |
+void ELFObjectWriter::String16(MCDataFragment &F, uint16_t Value) { |
+ char buf[2]; |
+ if (isLittleEndian()) |
+ StringLE16(buf, Value); |
+ else |
+ StringBE16(buf, Value); |
+ F.getContents() += StringRef(buf, 2); |
+} |
- /// ELFSymbolData - Helper struct for containing some precomputed information |
- /// on symbols. |
- struct ELFSymbolData { |
- MCSymbolData *SymbolData; |
- uint64_t StringIndex; |
- uint32_t SectionIndex; |
+void ELFObjectWriter::String32(MCDataFragment &F, uint32_t Value) { |
+ char buf[4]; |
+ if (isLittleEndian()) |
+ StringLE32(buf, Value); |
+ else |
+ StringBE32(buf, Value); |
+ F.getContents() += StringRef(buf, 4); |
+} |
- // Support lexicographic sorting. |
- bool operator<(const ELFSymbolData &RHS) const { |
- if (GetType(*SymbolData) == ELF::STT_FILE) |
- return true; |
- if (GetType(*RHS.SymbolData) == ELF::STT_FILE) |
- return false; |
- return SymbolData->getSymbol().getName() < |
- RHS.SymbolData->getSymbol().getName(); |
- } |
- }; |
- |
- /// @name Relocation Data |
- /// @{ |
- |
- struct ELFRelocationEntry { |
- // Make these big enough for both 32-bit and 64-bit |
- uint64_t r_offset; |
- int Index; |
- unsigned Type; |
- const MCSymbol *Symbol; |
- uint64_t r_addend; |
- |
- // Support lexicographic sorting. |
- bool operator<(const ELFRelocationEntry &RE) const { |
- return RE.r_offset < r_offset; |
- } |
- }; |
- |
- SmallPtrSet<const MCSymbol *, 16> UsedInReloc; |
- SmallPtrSet<const MCSymbol *, 16> WeakrefUsedInReloc; |
- DenseMap<const MCSymbol *, const MCSymbol *> Renames; |
- |
- llvm::DenseMap<const MCSectionData*, |
- std::vector<ELFRelocationEntry> > Relocations; |
- DenseMap<const MCSection*, uint64_t> SectionStringTableIndex; |
- |
- /// @} |
- /// @name Symbol Table Data |
- /// @{ |
- |
- SmallString<256> StringTable; |
- std::vector<ELFSymbolData> LocalSymbolData; |
- std::vector<ELFSymbolData> ExternalSymbolData; |
- std::vector<ELFSymbolData> UndefinedSymbolData; |
- |
- /// @} |
- |
- int NumRegularSections; |
- |
- bool NeedsGOT; |
- |
- bool NeedsSymtabShndx; |
- |
- ELFObjectWriter *Writer; |
- |
- raw_ostream &OS; |
- |
- unsigned Is64Bit : 1; |
- |
- bool HasRelocationAddend; |
- |
- Triple::OSType OSType; |
- |
- uint16_t EMachine; |
- |
- // This holds the symbol table index of the last local symbol. |
- unsigned LastLocalSymbolIndex; |
- // This holds the .strtab section index. |
- unsigned StringTableIndex; |
- // This holds the .symtab section index. |
- unsigned SymbolTableIndex; |
- |
- unsigned ShstrtabIndex; |
- |
- public: |
- ELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _Is64Bit, |
- uint16_t _EMachine, bool _HasRelAddend, |
- Triple::OSType _OSType) |
- : NeedsGOT(false), NeedsSymtabShndx(false), Writer(_Writer), |
- OS(Writer->getStream()), |
- Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelAddend), |
- OSType(_OSType), EMachine(_EMachine) { |
- } |
- |
- void Write8(uint8_t Value) { Writer->Write8(Value); } |
- void Write16(uint16_t Value) { Writer->Write16(Value); } |
- void Write32(uint32_t Value) { Writer->Write32(Value); } |
- //void Write64(uint64_t Value) { Writer->Write64(Value); } |
- void WriteZeros(unsigned N) { Writer->WriteZeros(N); } |
- //void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) { |
- // Writer->WriteBytes(Str, ZeroFillSize); |
- //} |
- |
- void WriteWord(uint64_t W) { |
- if (Is64Bit) |
- Writer->Write64(W); |
- else |
- Writer->Write32(W); |
- } |
- |
- void StringLE16(char *buf, uint16_t Value) { |
- buf[0] = char(Value >> 0); |
- buf[1] = char(Value >> 8); |
- } |
- |
- void StringLE32(char *buf, uint32_t Value) { |
- StringLE16(buf, uint16_t(Value >> 0)); |
- StringLE16(buf + 2, uint16_t(Value >> 16)); |
- } |
- |
- void StringLE64(char *buf, uint64_t Value) { |
- StringLE32(buf, uint32_t(Value >> 0)); |
- StringLE32(buf + 4, uint32_t(Value >> 32)); |
- } |
- |
- void StringBE16(char *buf ,uint16_t Value) { |
- buf[0] = char(Value >> 8); |
- buf[1] = char(Value >> 0); |
- } |
- |
- void StringBE32(char *buf, uint32_t Value) { |
- StringBE16(buf, uint16_t(Value >> 16)); |
- StringBE16(buf + 2, uint16_t(Value >> 0)); |
- } |
- |
- void StringBE64(char *buf, uint64_t Value) { |
- StringBE32(buf, uint32_t(Value >> 32)); |
- StringBE32(buf + 4, uint32_t(Value >> 0)); |
- } |
- |
- void String8(MCDataFragment &F, uint8_t Value) { |
- char buf[1]; |
- buf[0] = Value; |
- F.getContents() += StringRef(buf, 1); |
- } |
- |
- void String16(MCDataFragment &F, uint16_t Value) { |
- char buf[2]; |
- if (Writer->isLittleEndian()) |
- StringLE16(buf, Value); |
- else |
- StringBE16(buf, Value); |
- F.getContents() += StringRef(buf, 2); |
- } |
- |
- void String32(MCDataFragment &F, uint32_t Value) { |
- char buf[4]; |
- if (Writer->isLittleEndian()) |
- StringLE32(buf, Value); |
- else |
- StringBE32(buf, Value); |
- F.getContents() += StringRef(buf, 4); |
- } |
- |
- void String64(MCDataFragment &F, uint64_t Value) { |
- char buf[8]; |
- if (Writer->isLittleEndian()) |
- StringLE64(buf, Value); |
- else |
- StringBE64(buf, Value); |
- F.getContents() += StringRef(buf, 8); |
- } |
- |
- void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections); |
- |
- void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *ShndxF, |
- uint64_t name, uint8_t info, |
- uint64_t value, uint64_t size, |
- uint8_t other, uint32_t shndx, |
- bool Reserved); |
- |
- void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF, |
- ELFSymbolData &MSD, |
- const MCAsmLayout &Layout); |
- |
- typedef DenseMap<const MCSectionELF*, uint32_t> SectionIndexMapTy; |
- void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *ShndxF, |
- const MCAssembler &Asm, |
- const MCAsmLayout &Layout, |
- const SectionIndexMapTy &SectionIndexMap); |
- |
- void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, |
- const MCFragment *Fragment, const MCFixup &Fixup, |
- MCValue Target, uint64_t &FixedValue); |
- |
- uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, |
- const MCSymbol *S); |
- |
- /// ComputeSymbolTable - Compute the symbol table data |
- /// |
- /// \param StringTable [out] - The string table data. |
- /// \param StringIndexMap [out] - Map from symbol names to offsets in the |
- /// string table. |
- void ComputeSymbolTable(MCAssembler &Asm, |
- const SectionIndexMapTy &SectionIndexMap); |
- |
- void ComputeIndexMap(MCAssembler &Asm, |
- SectionIndexMapTy &SectionIndexMap); |
- |
- void WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, |
- const MCSectionData &SD); |
- |
- void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout) { |
- for (MCAssembler::const_iterator it = Asm.begin(), |
- ie = Asm.end(); it != ie; ++it) { |
- WriteRelocation(Asm, Layout, *it); |
- } |
- } |
- |
- void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, |
- const SectionIndexMapTy &SectionIndexMap); |
- |
- // Map from a group section to the signature symbol |
- typedef DenseMap<const MCSectionELF*, const MCSymbol*> GroupMapTy; |
- void CreateGroupSections(MCAssembler &Asm, MCAsmLayout &Layout, |
- GroupMapTy &GroupMap); |
- |
- void ExecutePostLayoutBinding(MCAssembler &Asm); |
- |
- void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, |
- uint64_t Address, uint64_t Offset, |
- uint64_t Size, uint32_t Link, uint32_t Info, |
- uint64_t Alignment, uint64_t EntrySize); |
- |
- void WriteRelocationsFragment(const MCAssembler &Asm, MCDataFragment *F, |
- const MCSectionData *SD); |
- |
- bool IsFixupFullyResolved(const MCAssembler &Asm, |
- const MCValue Target, |
- bool IsPCRel, |
- const MCFragment *DF) const; |
- |
- void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); |
- void WriteSection(MCAssembler &Asm, |
- const SectionIndexMapTy &SectionIndexMap, |
- uint32_t GroupSymbolIndex, |
- uint64_t Offset, uint64_t Size, uint64_t Alignment, |
- const MCSectionELF &Section); |
- }; |
- |
+void ELFObjectWriter::String64(MCDataFragment &F, uint64_t Value) { |
+ char buf[8]; |
+ if (isLittleEndian()) |
+ StringLE64(buf, Value); |
+ else |
+ StringBE64(buf, Value); |
+ F.getContents() += StringRef(buf, 8); |
} |
+ |
// Emit the ELF header. |
-void ELFObjectWriterImpl::WriteHeader(uint64_t SectionDataSize, |
+void ELFObjectWriter::WriteHeader(uint64_t SectionDataSize, |
unsigned NumberOfSections) { |
// ELF Header |
// ---------- |
@@ -375,7 +155,7 @@ |
Write8(Is64Bit ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS] |
// e_ident[EI_DATA] |
- Write8(Writer->isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB); |
+ Write8(isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB); |
Write8(ELF::EV_CURRENT); // e_ident[EI_VERSION] |
// e_ident[EI_OSABI] |
@@ -423,7 +203,7 @@ |
Write16(ShstrtabIndex); |
} |
-void ELFObjectWriterImpl::WriteSymbolEntry(MCDataFragment *SymtabF, |
+void ELFObjectWriter::WriteSymbolEntry(MCDataFragment *SymtabF, |
MCDataFragment *ShndxF, |
uint64_t name, |
uint8_t info, uint64_t value, |
@@ -497,7 +277,25 @@ |
return *S; |
} |
-void ELFObjectWriterImpl::ExecutePostLayoutBinding(MCAssembler &Asm) { |
+ |
+// Helper routines |
+ |
+bool ELFObjectWriter::ELFSymbolData::operator<(const ELFSymbolData &RHS) const { |
+ if (GetType(*SymbolData) == ELF::STT_FILE) |
+ return true; |
+ if (GetType(*RHS.SymbolData) == ELF::STT_FILE) |
+ return false; |
+ return SymbolData->getSymbol().getName() < |
+ RHS.SymbolData->getSymbol().getName(); |
+} |
+ |
+ |
+bool ELFObjectWriter::ELFRelocationEntry::operator<(const ELFRelocationEntry &RE) const { |
+ return RE.r_offset < r_offset; |
+} |
+ |
+ |
+void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) { |
// The presence of symbol versions causes undefined symbols and |
// versions declared with @@@ to be renamed. |
@@ -543,7 +341,7 @@ |
} |
} |
-void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *SymtabF, |
+void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, |
MCDataFragment *ShndxF, |
ELFSymbolData &MSD, |
const MCAsmLayout &Layout) { |
@@ -590,7 +388,7 @@ |
Size, Other, MSD.SectionIndex, IsReserved); |
} |
-void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *SymtabF, |
+void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, |
MCDataFragment *ShndxF, |
const MCAssembler &Asm, |
const MCAsmLayout &Layout, |
@@ -678,215 +476,9 @@ |
return false; |
} |
-// FIXME: this is currently X86/X86_64 only |
-void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm, |
- const MCAsmLayout &Layout, |
- const MCFragment *Fragment, |
- const MCFixup &Fixup, |
- MCValue Target, |
- uint64_t &FixedValue) { |
- int64_t Addend = 0; |
- int Index = 0; |
- int64_t Value = Target.getConstant(); |
- const MCSymbol &Symbol = Target.getSymA()->getSymbol(); |
- const MCSymbol &ASymbol = AliasedSymbol(Symbol); |
- const MCSymbol *RenamedP = Renames.lookup(&Symbol); |
- if (!RenamedP) |
- RenamedP = &ASymbol; |
- const MCSymbol &Renamed = *RenamedP; |
- bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind()); |
- if (!Target.isAbsolute()) { |
- MCSymbolData &SD = Asm.getSymbolData(Symbol); |
- MCFragment *F = SD.getFragment(); |
- |
- if (const MCSymbolRefExpr *RefB = Target.getSymB()) { |
- const MCSymbol &SymbolB = RefB->getSymbol(); |
- MCSymbolData &SDB = Asm.getSymbolData(SymbolB); |
- IsPCRel = true; |
- MCSectionData *Sec = Fragment->getParent(); |
- |
- // Offset of the symbol in the section |
- int64_t a = Layout.getSymbolAddress(&SDB) - Layout.getSectionAddress(Sec); |
- |
- // Ofeset of the relocation in the section |
- int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); |
- Value += b - a; |
- } |
- |
- bool RelocOnSymbol = ShouldRelocOnSymbol(SD, Target, *Fragment); |
- if (!RelocOnSymbol) { |
- Index = F->getParent()->getOrdinal(); |
- |
- MCSectionData *FSD = F->getParent(); |
- // Offset of the symbol in the section |
- Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD); |
- } else { |
- if (Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref) |
- WeakrefUsedInReloc.insert(&Renamed); |
- else |
- UsedInReloc.insert(&Renamed); |
- Index = -1; |
- } |
- Addend = Value; |
- // Compensate for the addend on i386. |
- if (Is64Bit) |
- Value = 0; |
- } |
- |
- FixedValue = Value; |
- |
- // determine the type of the relocation |
- |
- MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind(); |
- unsigned Type; |
- if (Is64Bit) { |
- if (IsPCRel) { |
- switch (Modifier) { |
- default: |
- llvm_unreachable("Unimplemented"); |
- case MCSymbolRefExpr::VK_None: |
- Type = ELF::R_X86_64_PC32; |
- break; |
- case MCSymbolRefExpr::VK_PLT: |
- Type = ELF::R_X86_64_PLT32; |
- break; |
- case MCSymbolRefExpr::VK_GOTPCREL: |
- Type = ELF::R_X86_64_GOTPCREL; |
- break; |
- case MCSymbolRefExpr::VK_GOTTPOFF: |
- Type = ELF::R_X86_64_GOTTPOFF; |
- break; |
- case MCSymbolRefExpr::VK_TLSGD: |
- Type = ELF::R_X86_64_TLSGD; |
- break; |
- case MCSymbolRefExpr::VK_TLSLD: |
- Type = ELF::R_X86_64_TLSLD; |
- break; |
- } |
- } else { |
- switch ((unsigned)Fixup.getKind()) { |
- default: llvm_unreachable("invalid fixup kind!"); |
- case FK_Data_8: Type = ELF::R_X86_64_64; break; |
- case X86::reloc_signed_4byte: |
- case X86::reloc_pcrel_4byte: |
- assert(isInt<32>(Target.getConstant())); |
- switch (Modifier) { |
- default: |
- llvm_unreachable("Unimplemented"); |
- case MCSymbolRefExpr::VK_None: |
- Type = ELF::R_X86_64_32S; |
- break; |
- case MCSymbolRefExpr::VK_GOT: |
- Type = ELF::R_X86_64_GOT32; |
- break; |
- case MCSymbolRefExpr::VK_GOTPCREL: |
- Type = ELF::R_X86_64_GOTPCREL; |
- break; |
- case MCSymbolRefExpr::VK_TPOFF: |
- Type = ELF::R_X86_64_TPOFF32; |
- break; |
- case MCSymbolRefExpr::VK_DTPOFF: |
- Type = ELF::R_X86_64_DTPOFF32; |
- break; |
- } |
- break; |
- case FK_Data_4: |
- Type = ELF::R_X86_64_32; |
- break; |
- case FK_Data_2: Type = ELF::R_X86_64_16; break; |
- case X86::reloc_pcrel_1byte: |
- case FK_Data_1: Type = ELF::R_X86_64_8; break; |
- } |
- } |
- } else { |
- if (IsPCRel) { |
- switch (Modifier) { |
- default: |
- llvm_unreachable("Unimplemented"); |
- case MCSymbolRefExpr::VK_None: |
- Type = ELF::R_386_PC32; |
- break; |
- case MCSymbolRefExpr::VK_PLT: |
- Type = ELF::R_386_PLT32; |
- break; |
- } |
- } else { |
- switch ((unsigned)Fixup.getKind()) { |
- default: llvm_unreachable("invalid fixup kind!"); |
- |
- case X86::reloc_global_offset_table: |
- Type = ELF::R_386_GOTPC; |
- break; |
- |
- // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode |
- // instead? |
- case X86::reloc_signed_4byte: |
- case X86::reloc_pcrel_4byte: |
- case FK_Data_4: |
- switch (Modifier) { |
- default: |
- llvm_unreachable("Unimplemented"); |
- case MCSymbolRefExpr::VK_None: |
- Type = ELF::R_386_32; |
- break; |
- case MCSymbolRefExpr::VK_GOT: |
- Type = ELF::R_386_GOT32; |
- break; |
- case MCSymbolRefExpr::VK_GOTOFF: |
- Type = ELF::R_386_GOTOFF; |
- break; |
- case MCSymbolRefExpr::VK_TLSGD: |
- Type = ELF::R_386_TLS_GD; |
- break; |
- case MCSymbolRefExpr::VK_TPOFF: |
- Type = ELF::R_386_TLS_LE_32; |
- break; |
- case MCSymbolRefExpr::VK_INDNTPOFF: |
- Type = ELF::R_386_TLS_IE; |
- break; |
- case MCSymbolRefExpr::VK_NTPOFF: |
- Type = ELF::R_386_TLS_LE; |
- break; |
- case MCSymbolRefExpr::VK_GOTNTPOFF: |
- Type = ELF::R_386_TLS_GOTIE; |
- break; |
- case MCSymbolRefExpr::VK_TLSLDM: |
- Type = ELF::R_386_TLS_LDM; |
- break; |
- case MCSymbolRefExpr::VK_DTPOFF: |
- Type = ELF::R_386_TLS_LDO_32; |
- break; |
- } |
- break; |
- case FK_Data_2: Type = ELF::R_386_16; break; |
- case X86::reloc_pcrel_1byte: |
- case FK_Data_1: Type = ELF::R_386_8; break; |
- } |
- } |
- } |
- |
- if (RelocNeedsGOT(Modifier)) |
- NeedsGOT = true; |
- |
- ELFRelocationEntry ERE; |
- |
- ERE.Index = Index; |
- ERE.Type = Type; |
- ERE.Symbol = &Renamed; |
- |
- ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); |
- |
- if (HasRelocationAddend) |
- ERE.r_addend = Addend; |
- else |
- ERE.r_addend = 0; // Silence compiler warning. |
- |
- Relocations[Fragment->getParent()].push_back(ERE); |
-} |
- |
uint64_t |
-ELFObjectWriterImpl::getSymbolIndexInSymbolTable(const MCAssembler &Asm, |
+ELFObjectWriter::getSymbolIndexInSymbolTable(const MCAssembler &Asm, |
const MCSymbol *S) { |
MCSymbolData &SD = Asm.getSymbolData(*S); |
@@ -938,7 +530,7 @@ |
return true; |
} |
-void ELFObjectWriterImpl::ComputeIndexMap(MCAssembler &Asm, |
+void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm, |
SectionIndexMapTy &SectionIndexMap) { |
unsigned Index = 1; |
for (MCAssembler::iterator it = Asm.begin(), |
@@ -960,7 +552,7 @@ |
} |
} |
-void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm, |
+void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, |
const SectionIndexMapTy &SectionIndexMap) { |
// FIXME: Is this the correct place to do this? |
if (NeedsGOT) { |
@@ -1058,7 +650,7 @@ |
UndefinedSymbolData[i].SymbolData->setIndex(Index++); |
} |
-void ELFObjectWriterImpl::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, |
+void ELFObjectWriter::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, |
const MCSectionData &SD) { |
if (!Relocations[&SD].empty()) { |
MCContext &Ctx = Asm.getContext(); |
@@ -1088,11 +680,20 @@ |
WriteRelocationsFragment(Asm, F, &SD); |
- Asm.AddSectionToTheEnd(*Writer, RelaSD, Layout); |
+ Asm.AddSectionToTheEnd(*this, RelaSD, Layout); |
} |
} |
-void ELFObjectWriterImpl::WriteSecHdrEntry(uint32_t Name, uint32_t Type, |
+ |
+void ELFObjectWriter::WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout) { |
+ for (MCAssembler::const_iterator it = Asm.begin(), |
+ ie = Asm.end(); it != ie; ++it) { |
+ WriteRelocation(Asm, Layout, *it); |
+ } |
+} |
+ |
+ |
+void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, |
uint64_t Flags, uint64_t Address, |
uint64_t Offset, uint64_t Size, |
uint32_t Link, uint32_t Info, |
@@ -1110,7 +711,7 @@ |
WriteWord(EntrySize); // sh_entsize |
} |
-void ELFObjectWriterImpl::WriteRelocationsFragment(const MCAssembler &Asm, |
+void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, |
MCDataFragment *F, |
const MCSectionData *SD) { |
std::vector<ELFRelocationEntry> &Relocs = Relocations[SD]; |
@@ -1146,7 +747,7 @@ |
} |
} |
-void ELFObjectWriterImpl::CreateMetadataSections(MCAssembler &Asm, |
+void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, |
MCAsmLayout &Layout, |
const SectionIndexMapTy &SectionIndexMap) { |
MCContext &Ctx = Asm.getContext(); |
@@ -1194,14 +795,14 @@ |
MCDataFragment *ShndxF = NULL; |
if (NeedsSymtabShndx) { |
ShndxF = new MCDataFragment(SymtabShndxSD); |
- Asm.AddSectionToTheEnd(*Writer, *SymtabShndxSD, Layout); |
+ Asm.AddSectionToTheEnd(*this, *SymtabShndxSD, Layout); |
} |
WriteSymbolTable(F, ShndxF, Asm, Layout, SectionIndexMap); |
- Asm.AddSectionToTheEnd(*Writer, SymtabSD, Layout); |
+ Asm.AddSectionToTheEnd(*this, SymtabSD, Layout); |
F = new MCDataFragment(&StrtabSD); |
F->getContents().append(StringTable.begin(), StringTable.end()); |
- Asm.AddSectionToTheEnd(*Writer, StrtabSD, Layout); |
+ Asm.AddSectionToTheEnd(*this, StrtabSD, Layout); |
F = new MCDataFragment(&ShstrtabSD); |
@@ -1234,10 +835,10 @@ |
F->getContents() += '\x00'; |
} |
- Asm.AddSectionToTheEnd(*Writer, ShstrtabSD, Layout); |
+ Asm.AddSectionToTheEnd(*this, ShstrtabSD, Layout); |
} |
-bool ELFObjectWriterImpl::IsFixupFullyResolved(const MCAssembler &Asm, |
+bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, |
const MCValue Target, |
bool IsPCRel, |
const MCFragment *DF) const { |
@@ -1271,7 +872,7 @@ |
return !SectionB && BaseSection == SectionA; |
} |
-void ELFObjectWriterImpl::CreateGroupSections(MCAssembler &Asm, |
+void ELFObjectWriter::CreateGroupSections(MCAssembler &Asm, |
MCAsmLayout &Layout, |
GroupMapTy &GroupMap) { |
typedef DenseMap<const MCSymbol*, const MCSectionELF*> RevGroupMapTy; |
@@ -1317,11 +918,11 @@ |
i != e; ++i) { |
const MCSectionELF *Group = i->second; |
MCSectionData &Data = Asm.getOrCreateSectionData(*Group); |
- Asm.AddSectionToTheEnd(*Writer, Data, Layout); |
+ Asm.AddSectionToTheEnd(*this, Data, Layout); |
} |
} |
-void ELFObjectWriterImpl::WriteSection(MCAssembler &Asm, |
+void ELFObjectWriter::WriteSection(MCAssembler &Asm, |
const SectionIndexMapTy &SectionIndexMap, |
uint32_t GroupSymbolIndex, |
uint64_t Offset, uint64_t Size, |
@@ -1391,7 +992,7 @@ |
Alignment, Section.getEntrySize()); |
} |
-void ELFObjectWriterImpl::WriteObject(MCAssembler &Asm, |
+void ELFObjectWriter::WriteObject(MCAssembler &Asm, |
const MCAsmLayout &Layout) { |
GroupMapTy GroupMap; |
@@ -1461,7 +1062,7 @@ |
FileOff += Layout.getSectionFileSize(&SD); |
- Asm.WriteSectionData(&SD, Layout, Writer); |
+ Asm.WriteSectionData(&SD, Layout, this); |
} |
uint64_t Padding = OffsetToAlignment(FileOff, NaturalAlignment); |
@@ -1493,44 +1094,261 @@ |
} |
} |
-ELFObjectWriter::ELFObjectWriter(raw_ostream &OS, |
- bool Is64Bit, |
- Triple::OSType OSType, |
- uint16_t EMachine, |
- bool IsLittleEndian, |
- bool HasRelocationAddend) |
- : MCObjectWriter(OS, IsLittleEndian) |
+ELFObjectWriter::ELFObjectWriter(raw_ostream &_OS, |
+ bool _Is64Bit, |
+ Triple::OSType _OSType, |
+ uint16_t _EMachine, |
+ bool _IsLittleEndian, |
+ bool _HasRelocationAddend) |
+ : MCObjectWriter(_OS, _IsLittleEndian), |
+ NeedsGOT(false), NeedsSymtabShndx(false), |
+ Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelocationAddend), |
+ OSType(_OSType), EMachine(_EMachine) |
{ |
- Impl = new ELFObjectWriterImpl(this, Is64Bit, EMachine, |
- HasRelocationAddend, OSType); |
+// Impl = new ELFObjectWriterImpl(this, Is64Bit, EMachine, |
+// HasRelocationAddend, OSType); |
} |
-ELFObjectWriter::~ELFObjectWriter() { |
- delete (ELFObjectWriterImpl*) Impl; |
-} |
+//===- ARMELFObjectWriter -------------------------------------------===// |
-void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) { |
- ((ELFObjectWriterImpl*) Impl)->ExecutePostLayoutBinding(Asm); |
-} |
+ARMELFObjectWriter::ARMELFObjectWriter(raw_ostream &OS, bool Is64Bit, |
+ Triple::OSType OSType, |
+ uint16_t EMachine, bool IsLittleEndian, |
+ bool HasRelocationAddend) |
+ : ELFObjectWriter(OS, Is64Bit, OSType, EMachine, IsLittleEndian, |
+ HasRelocationAddend) |
+{} |
-void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, |
- const MCAsmLayout &Layout, |
- const MCFragment *Fragment, |
- const MCFixup &Fixup, MCValue Target, |
- uint64_t &FixedValue) { |
- ((ELFObjectWriterImpl*) Impl)->RecordRelocation(Asm, Layout, Fragment, Fixup, |
- Target, FixedValue); |
-} |
+ARMELFObjectWriter::~ARMELFObjectWriter() |
+{} |
-bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, |
- const MCValue Target, |
- bool IsPCRel, |
- const MCFragment *DF) const { |
- return ((ELFObjectWriterImpl*) Impl)->IsFixupFullyResolved(Asm, Target, |
- IsPCRel, DF); |
+void ARMELFObjectWriter::RecordRelocation(const MCAssembler &Asm, |
+ const MCAsmLayout &Layout, |
+ const MCFragment *Fragment, |
+ const MCFixup &Fixup, |
+ MCValue Target, |
+ uint64_t &FixedValue) { |
+ assert(0 && "ARMELFObjectWriter::RecordRelocation() unimplemented"); |
} |
-void ELFObjectWriter::WriteObject(MCAssembler &Asm, |
- const MCAsmLayout &Layout) { |
- ((ELFObjectWriterImpl*) Impl)->WriteObject(Asm, Layout); |
+ |
+ |
+//===- X86ELFObjectWriter -------------------------------------------===// |
+ |
+ |
+X86ELFObjectWriter::X86ELFObjectWriter(raw_ostream &OS, bool Is64Bit, |
+ Triple::OSType OSType, |
+ uint16_t EMachine, bool IsLittleEndian, |
+ bool HasRelocationAddend) |
+ : ELFObjectWriter(OS, Is64Bit, OSType, EMachine, IsLittleEndian, |
+ HasRelocationAddend) |
+{} |
+ |
+X86ELFObjectWriter::~X86ELFObjectWriter() |
+{} |
+ |
+void X86ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, |
+ const MCAsmLayout &Layout, |
+ const MCFragment *Fragment, |
+ const MCFixup &Fixup, |
+ MCValue Target, |
+ uint64_t &FixedValue) { |
+ int64_t Addend = 0; |
+ int Index = 0; |
+ int64_t Value = Target.getConstant(); |
+ const MCSymbol &Symbol = Target.getSymA()->getSymbol(); |
+ const MCSymbol &ASymbol = AliasedSymbol(Symbol); |
+ const MCSymbol *RenamedP = Renames.lookup(&Symbol); |
+ if (!RenamedP) |
+ RenamedP = &ASymbol; |
+ const MCSymbol &Renamed = *RenamedP; |
+ |
+ bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind()); |
+ if (!Target.isAbsolute()) { |
+ MCSymbolData &SD = Asm.getSymbolData(Symbol); |
+ MCFragment *F = SD.getFragment(); |
+ |
+ if (const MCSymbolRefExpr *RefB = Target.getSymB()) { |
+ const MCSymbol &SymbolB = RefB->getSymbol(); |
+ MCSymbolData &SDB = Asm.getSymbolData(SymbolB); |
+ IsPCRel = true; |
+ MCSectionData *Sec = Fragment->getParent(); |
+ |
+ // Offset of the symbol in the section |
+ int64_t a = Layout.getSymbolAddress(&SDB) - Layout.getSectionAddress(Sec); |
+ |
+ // Ofeset of the relocation in the section |
+ int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); |
+ Value += b - a; |
+ } |
+ |
+ bool RelocOnSymbol = ShouldRelocOnSymbol(SD, Target, *Fragment); |
+ if (!RelocOnSymbol) { |
+ Index = F->getParent()->getOrdinal(); |
+ |
+ MCSectionData *FSD = F->getParent(); |
+ // Offset of the symbol in the section |
+ Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD); |
+ } else { |
+ if (Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref) |
+ WeakrefUsedInReloc.insert(&Renamed); |
+ else |
+ UsedInReloc.insert(&Renamed); |
+ Index = -1; |
+ } |
+ Addend = Value; |
+ // Compensate for the addend on i386. |
+ if (Is64Bit) |
+ Value = 0; |
+ } |
+ |
+ FixedValue = Value; |
+ |
+ // determine the type of the relocation |
+ |
+ MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind(); |
+ unsigned Type; |
+ if (Is64Bit) { |
+ if (IsPCRel) { |
+ switch (Modifier) { |
+ default: |
+ llvm_unreachable("Unimplemented"); |
+ case MCSymbolRefExpr::VK_None: |
+ Type = ELF::R_X86_64_PC32; |
+ break; |
+ case MCSymbolRefExpr::VK_PLT: |
+ Type = ELF::R_X86_64_PLT32; |
+ break; |
+ case MCSymbolRefExpr::VK_GOTPCREL: |
+ Type = ELF::R_X86_64_GOTPCREL; |
+ break; |
+ case MCSymbolRefExpr::VK_GOTTPOFF: |
+ Type = ELF::R_X86_64_GOTTPOFF; |
+ break; |
+ case MCSymbolRefExpr::VK_TLSGD: |
+ Type = ELF::R_X86_64_TLSGD; |
+ break; |
+ case MCSymbolRefExpr::VK_TLSLD: |
+ Type = ELF::R_X86_64_TLSLD; |
+ break; |
+ } |
+ } else { |
+ switch ((unsigned)Fixup.getKind()) { |
+ default: llvm_unreachable("invalid fixup kind!"); |
+ case FK_Data_8: Type = ELF::R_X86_64_64; break; |
+ case X86::reloc_signed_4byte: |
+ case X86::reloc_pcrel_4byte: |
+ assert(isInt<32>(Target.getConstant())); |
+ switch (Modifier) { |
+ default: |
+ llvm_unreachable("Unimplemented"); |
+ case MCSymbolRefExpr::VK_None: |
+ Type = ELF::R_X86_64_32S; |
+ break; |
+ case MCSymbolRefExpr::VK_GOT: |
+ Type = ELF::R_X86_64_GOT32; |
+ break; |
+ case MCSymbolRefExpr::VK_GOTPCREL: |
+ Type = ELF::R_X86_64_GOTPCREL; |
+ break; |
+ case MCSymbolRefExpr::VK_TPOFF: |
+ Type = ELF::R_X86_64_TPOFF32; |
+ break; |
+ case MCSymbolRefExpr::VK_DTPOFF: |
+ Type = ELF::R_X86_64_DTPOFF32; |
+ break; |
+ } |
+ break; |
+ case FK_Data_4: |
+ Type = ELF::R_X86_64_32; |
+ break; |
+ case FK_Data_2: Type = ELF::R_X86_64_16; break; |
+ case X86::reloc_pcrel_1byte: |
+ case FK_Data_1: Type = ELF::R_X86_64_8; break; |
+ } |
+ } |
+ } else { |
+ if (IsPCRel) { |
+ switch (Modifier) { |
+ default: |
+ llvm_unreachable("Unimplemented"); |
+ case MCSymbolRefExpr::VK_None: |
+ Type = ELF::R_386_PC32; |
+ break; |
+ case MCSymbolRefExpr::VK_PLT: |
+ Type = ELF::R_386_PLT32; |
+ break; |
+ } |
+ } else { |
+ switch ((unsigned)Fixup.getKind()) { |
+ default: llvm_unreachable("invalid fixup kind!"); |
+ |
+ case X86::reloc_global_offset_table: |
+ Type = ELF::R_386_GOTPC; |
+ break; |
+ |
+ // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode |
+ // instead? |
+ case X86::reloc_signed_4byte: |
+ case X86::reloc_pcrel_4byte: |
+ case FK_Data_4: |
+ switch (Modifier) { |
+ default: |
+ llvm_unreachable("Unimplemented"); |
+ case MCSymbolRefExpr::VK_None: |
+ Type = ELF::R_386_32; |
+ break; |
+ case MCSymbolRefExpr::VK_GOT: |
+ Type = ELF::R_386_GOT32; |
+ break; |
+ case MCSymbolRefExpr::VK_GOTOFF: |
+ Type = ELF::R_386_GOTOFF; |
+ break; |
+ case MCSymbolRefExpr::VK_TLSGD: |
+ Type = ELF::R_386_TLS_GD; |
+ break; |
+ case MCSymbolRefExpr::VK_TPOFF: |
+ Type = ELF::R_386_TLS_LE_32; |
+ break; |
+ case MCSymbolRefExpr::VK_INDNTPOFF: |
+ Type = ELF::R_386_TLS_IE; |
+ break; |
+ case MCSymbolRefExpr::VK_NTPOFF: |
+ Type = ELF::R_386_TLS_LE; |
+ break; |
+ case MCSymbolRefExpr::VK_GOTNTPOFF: |
+ Type = ELF::R_386_TLS_GOTIE; |
+ break; |
+ case MCSymbolRefExpr::VK_TLSLDM: |
+ Type = ELF::R_386_TLS_LDM; |
+ break; |
+ case MCSymbolRefExpr::VK_DTPOFF: |
+ Type = ELF::R_386_TLS_LDO_32; |
+ break; |
+ } |
+ break; |
+ case FK_Data_2: Type = ELF::R_386_16; break; |
+ case X86::reloc_pcrel_1byte: |
+ case FK_Data_1: Type = ELF::R_386_8; break; |
+ } |
+ } |
+ } |
+ |
+ if (RelocNeedsGOT(Modifier)) |
+ NeedsGOT = true; |
+ |
+ ELFRelocationEntry ERE; |
+ |
+ ERE.Index = Index; |
+ ERE.Type = Type; |
+ ERE.Symbol = &Renamed; |
+ |
+ ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); |
+ |
+ if (HasRelocationAddend) |
+ ERE.r_addend = Addend; |
+ else |
+ ERE.r_addend = 0; // Silence compiler warning. |
+ |
+ Relocations[Fragment->getParent()].push_back(ERE); |
} |