X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FELFObjectWriter.cpp;h=fcf6d87e421b88407b2dd5897492eed1684197ff;hb=0bce3343cca290481199c5457bb54577f4a33a68;hp=b8b3188ce4808da643272f6d83400f7a958e97d0;hpb=b21d9aebba7e45ddcbce61dd501000049cefb335;p=oota-llvm.git diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index b8b3188ce48..fcf6d87e421 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -1,4 +1,4 @@ -//===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -------------------===// +//===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -----------------------===// // // The LLVM Compiler Infrastructure // @@ -11,17 +11,16 @@ // //===----------------------------------------------------------------------===// -#include "MCELF.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCELF.h" #include "llvm/MC/MCELFSymbolFlags.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFixupKindInfo.h" @@ -29,9 +28,8 @@ #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCValue.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ELF.h" - +#include "llvm/Support/ErrorHandling.h" #include using namespace llvm; @@ -74,17 +72,13 @@ class ELFObjectWriter : public MCObjectWriter { // Support lexicographic sorting. bool operator<(const ELFSymbolData &RHS) const { - if (MCELF::GetType(*SymbolData) == ELF::STT_FILE) - return true; - if (MCELF::GetType(*RHS.SymbolData) == ELF::STT_FILE) - return false; return SymbolData->getSymbol().getName() < RHS.SymbolData->getSymbol().getName(); } }; /// The target specific ELF writer instance. - llvm::OwningPtr TargetObjectWriter; + std::unique_ptr TargetObjectWriter; SmallPtrSet UsedInReloc; SmallPtrSet WeakrefUsedInReloc; @@ -99,6 +93,7 @@ class ELFObjectWriter : public MCObjectWriter { /// @{ SmallString<256> StringTable; + std::vector FileSymbolData; std::vector LocalSymbolData; std::vector ExternalSymbolData; std::vector UndefinedSymbolData; @@ -133,14 +128,17 @@ class ELFObjectWriter : public MCObjectWriter { bool IsPCRel) const { return TargetObjectWriter->ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel); } + const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel) const { + return TargetObjectWriter->undefinedExplicitRelSym(Target, Fixup, + IsPCRel); + } bool is64Bit() const { return TargetObjectWriter->is64Bit(); } bool hasRelocationAddend() const { return TargetObjectWriter->hasRelocationAddend(); } - unsigned getEFlags() const { - return TargetObjectWriter->getEFlags(); - } unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel, bool IsRelocWithSymbol, int64_t Addend) const { @@ -148,13 +146,12 @@ class ELFObjectWriter : public MCObjectWriter { IsRelocWithSymbol, Addend); } - public: ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_ostream &_OS, bool IsLittleEndian) : MCObjectWriter(_OS, IsLittleEndian), TargetObjectWriter(MOTW), - NeedsGOT(false), NeedsSymtabShndx(false){ + NeedsGOT(false), NeedsSymtabShndx(false) { } virtual ~ELFObjectWriter(); @@ -199,7 +196,7 @@ class ELFObjectWriter : public MCObjectWriter { void String8(MCDataFragment &F, uint8_t Value) { char buf[1]; buf[0] = Value; - F.getContents() += StringRef(buf, 1); + F.getContents().append(&buf[0], &buf[1]); } void String16(MCDataFragment &F, uint16_t Value) { @@ -208,7 +205,7 @@ class ELFObjectWriter : public MCObjectWriter { StringLE16(buf, Value); else StringBE16(buf, Value); - F.getContents() += StringRef(buf, 2); + F.getContents().append(&buf[0], &buf[2]); } void String32(MCDataFragment &F, uint32_t Value) { @@ -217,7 +214,7 @@ class ELFObjectWriter : public MCObjectWriter { StringLE32(buf, Value); else StringBE32(buf, Value); - F.getContents() += StringRef(buf, 4); + F.getContents().append(&buf[0], &buf[4]); } void String64(MCDataFragment &F, uint64_t Value) { @@ -226,10 +223,11 @@ class ELFObjectWriter : public MCObjectWriter { StringLE64(buf, Value); else StringBE64(buf, Value); - F.getContents() += StringRef(buf, 8); + F.getContents().append(&buf[0], &buf[8]); } - void WriteHeader(uint64_t SectionDataSize, + void WriteHeader(const MCAssembler &Asm, + uint64_t SectionDataSize, unsigned NumberOfSections); void WriteSymbolEntry(MCDataFragment *SymtabF, @@ -250,11 +248,9 @@ class ELFObjectWriter : public MCObjectWriter { const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap); - virtual void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue); + void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue) override; uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, const MCSymbol *S); @@ -268,13 +264,13 @@ class ELFObjectWriter : public MCObjectWriter { // Map from a section to its offset typedef DenseMap SectionOffsetMapTy; - /// ComputeSymbolTable - Compute the symbol table data + /// Compute the symbol table data /// /// \param Asm - The assembler. /// \param SectionIndexMap - Maps a section to its index. /// \param RevGroupMap - Maps a signature symbol to the group section. /// \param NumRegularSections - Number of non-relocation sections. - void ComputeSymbolTable(MCAssembler &Asm, + void computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, RevGroupMapTy RevGroupMap, unsigned NumRegularSections); @@ -301,8 +297,8 @@ class ELFObjectWriter : public MCObjectWriter { SectionIndexMapTy &SectionIndexMap, const RelMapTy &RelMap); - virtual void ExecutePostLayoutBinding(MCAssembler &Asm, - const MCAsmLayout &Layout); + void ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) override; void WriteSectionHeader(MCAssembler &Asm, const GroupMapTy &GroupMap, const MCAsmLayout &Layout, @@ -321,14 +317,14 @@ class ELFObjectWriter : public MCObjectWriter { MCDataFragment *F, const MCSectionData *SD); - virtual bool + bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCSymbolData &DataA, const MCFragment &FB, bool InSet, - bool IsPCRel) const; + bool IsPCRel) const override; - virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); + void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; void WriteSection(MCAssembler &Asm, const SectionIndexMapTy &SectionIndexMap, uint32_t GroupSymbolIndex, @@ -369,7 +365,8 @@ ELFObjectWriter::~ELFObjectWriter() {} // Emit the ELF header. -void ELFObjectWriter::WriteHeader(uint64_t SectionDataSize, +void ELFObjectWriter::WriteHeader(const MCAssembler &Asm, + uint64_t SectionDataSize, unsigned NumberOfSections) { // ELF Header // ---------- @@ -407,7 +404,7 @@ void ELFObjectWriter::WriteHeader(uint64_t SectionDataSize, sizeof(ELF::Elf32_Ehdr))); // e_shoff = sec hdr table off in bytes // e_flags = whatever the target wants - Write32(getEFlags()); + Write32(Asm.getELFHeaderEFlags()); // e_ehsize = ELF header size Write16(is64Bit() ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr)); @@ -465,33 +462,44 @@ void ELFObjectWriter::WriteSymbolEntry(MCDataFragment *SymtabF, } } -uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data, +uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &OrigData, const MCAsmLayout &Layout) { - if (Data.isCommon() && Data.isExternal()) - return Data.getCommonAlignment(); + MCSymbolData *Data = &OrigData; + if (Data->isCommon() && Data->isExternal()) + return Data->getCommonAlignment(); - const MCSymbol &Symbol = Data.getSymbol(); + const MCSymbol *Symbol = &Data->getSymbol(); + bool IsThumbFunc = OrigData.getFlags() & ELF_Other_ThumbFunc; + + uint64_t Res = 0; + if (Symbol->isVariable()) { + const MCExpr *Expr = Symbol->getVariableValue(); + MCValue Value; + if (!Expr->EvaluateAsRelocatable(Value, &Layout)) + llvm_unreachable("Invalid expression"); + + assert(!Value.getSymB()); + + Res = Value.getConstant(); - if (Symbol.isAbsolute() && Symbol.isVariable()) { - if (const MCExpr *Value = Symbol.getVariableValue()) { - int64_t IntValue; - if (Value->EvaluateAsAbsolute(IntValue, Layout)) - return (uint64_t)IntValue; + if (const MCSymbolRefExpr *A = Value.getSymA()) { + Symbol = &A->getSymbol(); + Data = &Layout.getAssembler().getSymbolData(*Symbol); + } else { + Symbol = 0; + Data = 0; } } - if (!Symbol.isInSection()) - return 0; + if (IsThumbFunc) + Res |= 1; + if (!Symbol || !Symbol->isInSection()) + return Res; - if (Data.getFragment()) { - if (Data.getFlags() & ELF_Other_ThumbFunc) - return Layout.getSymbolOffset(&Data)+1; - else - return Layout.getSymbolOffset(&Data); - } + Res += Layout.getSymbolOffset(Data); - return 0; + return Res; } void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, @@ -532,6 +540,57 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, } } +static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) { + uint8_t Type = newType; + + // Propagation rules: + // IFUNC > FUNC > OBJECT > NOTYPE + // TLS_OBJECT > OBJECT > NOTYPE + // + // dont let the new type degrade the old type + switch (origType) { + default: + break; + case ELF::STT_GNU_IFUNC: + if (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT || + Type == ELF::STT_NOTYPE || Type == ELF::STT_TLS) + Type = ELF::STT_GNU_IFUNC; + break; + case ELF::STT_FUNC: + if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE || + Type == ELF::STT_TLS) + Type = ELF::STT_FUNC; + break; + case ELF::STT_OBJECT: + if (Type == ELF::STT_NOTYPE) + Type = ELF::STT_OBJECT; + break; + case ELF::STT_TLS: + if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE || + Type == ELF::STT_GNU_IFUNC || Type == ELF::STT_FUNC) + Type = ELF::STT_TLS; + break; + } + + return Type; +} + +static const MCSymbol *getBaseSymbol(const MCAsmLayout &Layout, + const MCSymbol &Symbol) { + if (!Symbol.isVariable()) + return &Symbol; + + const MCExpr *Expr = Symbol.getVariableValue(); + MCValue Value; + if (!Expr->EvaluateAsRelocatable(Value, &Layout)) + llvm_unreachable("Invalid Expression"); + assert(!Value.getSymB()); + const MCSymbolRefExpr *A = Value.getSymA(); + if (!A) + return nullptr; + return getBaseSymbol(Layout, A->getSymbol()); +} + void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF, ELFSymbolData &MSD, @@ -543,14 +602,27 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() || Data.getSymbol().isVariable(); + // Binding and Type share the same byte as upper and lower nibbles uint8_t Binding = MCELF::GetBinding(OrigData); - uint8_t Visibility = MCELF::GetVisibility(OrigData); - uint8_t Type = MCELF::GetType(Data); - + uint8_t Type = MCELF::GetType(OrigData); + const MCSymbol *Base = getBaseSymbol(Layout, OrigData.getSymbol()); + if (Base) { + MCSymbolData BaseSD = Layout.getAssembler().getSymbolData(*Base); + Type = mergeTypeForSet(Type, MCELF::GetType(BaseSD)); + } + if (OrigData.getFlags() & ELF_Other_ThumbFunc) + Type = ELF::STT_FUNC; uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift); - uint8_t Other = Visibility; - uint64_t Value = SymbolValue(Data, Layout); + // Other and Visibility share the same byte with Visibility using the lower + // 2 bits + uint8_t Visibility = MCELF::GetVisibility(OrigData); + uint8_t Other = MCELF::getOther(OrigData) << (ELF_STO_Shift - ELF_STV_Shift); + Other |= Visibility; + + uint64_t Value = SymbolValue(OrigData, Layout); + if (OrigData.getFlags() & ELF_Other_ThumbFunc) + Value |= 1; uint64_t Size = 0; assert(!(Data.isCommon() && !Data.isExternal())); @@ -582,8 +654,15 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, // The first entry is the undefined symbol entry. WriteSymbolEntry(SymtabF, ShndxF, 0, 0, 0, 0, 0, 0, false); + for (unsigned i = 0, e = FileSymbolData.size(); i != e; ++i) { + WriteSymbolEntry(SymtabF, ShndxF, FileSymbolData[i], + ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, + ELF::STV_DEFAULT, ELF::SHN_ABS, true); + } + // Write the symbol table entries. - LastLocalSymbolIndex = LocalSymbolData.size() + 1; + LastLocalSymbolIndex = FileSymbolData.size() + LocalSymbolData.size() + 1; + for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) { ELFSymbolData &MSD = LocalSymbolData[i]; WriteSymbol(SymtabF, ShndxF, MSD, Layout); @@ -639,7 +718,7 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm, if (ASymbol.isUndefined()) { if (Renamed) return Renamed; - return &ASymbol; + return undefinedExplicitRelSym(Target, Fixup, IsPCRel); } if (SD.isExternal()) { @@ -709,6 +788,12 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, MCSymbolData &SDB = Asm.getSymbolData(SymbolB); IsPCRel = true; + if (!SDB.getFragment()) + Asm.getContext().FatalError( + Fixup.getLoc(), + Twine("symbol '") + SymbolB.getName() + + "' can not be undefined in a subtraction expression"); + // Offset of the symbol in the section int64_t a = Layout.getSymbolOffset(&SDB); @@ -721,12 +806,15 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, MCSymbolData &SD = Asm.getSymbolData(ASymbol); MCFragment *F = SD.getFragment(); - Index = F->getParent()->getOrdinal() + 1; - - // Offset of the symbol in the section - Value += Layout.getSymbolOffset(&SD); + if (F) { + Index = F->getParent()->getOrdinal() + 1; + // Offset of the symbol in the section + Value += Layout.getSymbolOffset(&SD); + } else { + Index = 0; + } } else { - if (Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref) + if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_WEAKREF) WeakrefUsedInReloc.insert(RelocSymbol); else UsedInReloc.insert(RelocSymbol); @@ -748,9 +836,6 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, uint64_t RelocOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); - // FIXME: no tests cover this. Is adjustFixupOffset dead code? - TargetObjectWriter->adjustFixupOffset(Fixup, RelocOffset); - if (!hasRelocationAddend()) Addend = 0; @@ -774,8 +859,14 @@ ELFObjectWriter::getSymbolIndexInSymbolTable(const MCAssembler &Asm, bool ELFObjectWriter::isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, bool Used, bool Renamed) { - if (Data.getFlags() & ELF_Other_Weakref) - return false; + const MCSymbol &Symbol = Data.getSymbol(); + if (Symbol.isVariable()) { + const MCExpr *Expr = Symbol.getVariableValue(); + if (const MCSymbolRefExpr *Ref = dyn_cast(Expr)) { + if (Ref->getKind() == MCSymbolRefExpr::VK_WEAKREF) + return false; + } + } if (Used) return true; @@ -783,8 +874,6 @@ bool ELFObjectWriter::isInSymtab(const MCAssembler &Asm, if (Renamed) return false; - const MCSymbol &Symbol = Data.getSymbol(); - if (Symbol.getName() == "_GLOBAL_OFFSET_TABLE_") return true; @@ -796,9 +885,6 @@ bool ELFObjectWriter::isInSymtab(const MCAssembler &Asm, if (!Symbol.isVariable() && Symbol.isUndefined() && !IsGlobal) return false; - if (!Asm.isSymbolLinkerVisible(Symbol) && !Symbol.isUndefined()) - return false; - if (Symbol.isTemporary()) return false; @@ -851,14 +937,15 @@ void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm, } } -void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, - const SectionIndexMapTy &SectionIndexMap, - RevGroupMapTy RevGroupMap, - unsigned NumRegularSections) { +void +ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap, + RevGroupMapTy RevGroupMap, + unsigned NumRegularSections) { // FIXME: Is this the correct place to do this? // FIXME: Why is an undefined reference to _GLOBAL_OFFSET_TABLE_ needed? if (NeedsGOT) { - llvm::StringRef Name = "_GLOBAL_OFFSET_TABLE_"; + StringRef Name = "_GLOBAL_OFFSET_TABLE_"; MCSymbol *Sym = Asm.getContext().GetOrCreateSymbol(Name); MCSymbolData &Data = Asm.getOrCreateSymbolData(*Sym); Data.setExternal(true); @@ -872,6 +959,20 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, // FIXME: We could optimize suffixes in strtab in the same way we // optimize them in shstrtab. + for (MCAssembler::const_file_name_iterator it = Asm.file_names_begin(), + ie = Asm.file_names_end(); + it != ie; + ++it) { + StringRef Name = *it; + uint64_t &Entry = StringIndexMap[Name]; + if (!Entry) { + Entry = StringTable.size(); + StringTable += Name; + StringTable += '\x00'; + } + FileSymbolData.push_back(Entry); + } + // Add the data for the symbols. for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), ie = Asm.symbol_end(); it != ie; ++it) { @@ -888,33 +989,33 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, ELFSymbolData MSD; MSD.SymbolData = it; - const MCSymbol &RefSymbol = Symbol.AliasedSymbol(); + const MCSymbol *BaseSymbol = getBaseSymbol(Layout, Symbol); // Undefined symbols are global, but this is the first place we // are able to set it. bool Local = isLocal(*it, isSignature, Used); if (!Local && MCELF::GetBinding(*it) == ELF::STB_LOCAL) { - MCSymbolData &SD = Asm.getSymbolData(RefSymbol); + assert(BaseSymbol); + MCSymbolData &SD = Asm.getSymbolData(*BaseSymbol); MCELF::SetBinding(*it, ELF::STB_GLOBAL); MCELF::SetBinding(SD, ELF::STB_GLOBAL); } - if (RefSymbol.isUndefined() && !Used && WeakrefUsed) - MCELF::SetBinding(*it, ELF::STB_WEAK); - - if (it->isCommon()) { + if (!BaseSymbol) { + MSD.SectionIndex = ELF::SHN_ABS; + } else if (it->isCommon()) { assert(!Local); MSD.SectionIndex = ELF::SHN_COMMON; - } else if (Symbol.isAbsolute() || RefSymbol.isVariable()) { - MSD.SectionIndex = ELF::SHN_ABS; - } else if (RefSymbol.isUndefined()) { + } else if (BaseSymbol->isUndefined()) { if (isSignature && !Used) MSD.SectionIndex = SectionIndexMap.lookup(RevGroupMap[&Symbol]); else MSD.SectionIndex = ELF::SHN_UNDEF; + if (!Used && WeakrefUsed) + MCELF::SetBinding(*it, ELF::STB_WEAK); } else { const MCSectionELF &Section = - static_cast(RefSymbol.getSection()); + static_cast(BaseSymbol->getSection()); MSD.SectionIndex = SectionIndexMap.lookup(&Section); if (MSD.SectionIndex >= ELF::SHN_LORESERVE) NeedsSymtabShndx = true; @@ -956,7 +1057,7 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, // Set the symbol indices. Local symbols must come before all other // symbols with non-local bindings. - unsigned Index = 1; + unsigned Index = FileSymbolData.size() + 1; for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) LocalSymbolData[i].SymbolData->setIndex(Index++); @@ -967,7 +1068,7 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) UndefinedSymbolData[i].SymbolData->setIndex(Index++); - if (NumRegularSections > ELF::SHN_LORESERVE) + if (Index >= ELF::SHN_LORESERVE) NeedsSymtabShndx = true; } @@ -994,11 +1095,18 @@ void ELFObjectWriter::CreateRelocationSections(MCAssembler &Asm, else EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel); + unsigned Flags = 0; + StringRef Group = ""; + if (Section.getFlags() & ELF::SHF_GROUP) { + Flags = ELF::SHF_GROUP; + Group = Section.getGroup()->getName(); + } + const MCSectionELF *RelaSection = Ctx.getELFSection(RelaSectionName, hasRelocationAddend() ? - ELF::SHT_RELA : ELF::SHT_REL, 0, + ELF::SHT_RELA : ELF::SHT_REL, Flags, SectionKind::getReadOnly(), - EntrySize, ""); + EntrySize, Group); RelMap[&Section] = RelaSection; Asm.getOrCreateSectionData(*RelaSection); } @@ -1058,7 +1166,7 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, else if (entry.Index < 0) entry.Index = getSymbolIndexInSymbolTable(Asm, entry.Symbol); else - entry.Index += LocalSymbolData.size(); + entry.Index += FileSymbolData.size() + LocalSymbolData.size(); if (is64Bit()) { String64(*F, entry.r_offset); if (TargetObjectWriter->isN64()) { @@ -1089,11 +1197,10 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, } } -static int compareBySuffix(const void *a, const void *b) { - const MCSectionELF *secA = *static_cast(a); - const MCSectionELF *secB = *static_cast(b); - const StringRef &NameA = secA->getSectionName(); - const StringRef &NameB = secB->getSectionName(); +static int compareBySuffix(const MCSectionELF *const *a, + const MCSectionELF *const *b) { + const StringRef &NameA = (*a)->getSectionName(); + const StringRef &NameB = (*b)->getSectionName(); const unsigned sizeA = NameA.size(); const unsigned sizeB = NameB.size(); const unsigned len = std::min(sizeA, sizeB); @@ -1179,7 +1286,7 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, // The first entry of a string table holds a null character so skip // section 0. uint64_t Index = 1; - F->getContents() += '\x00'; + F->getContents().push_back('\x00'); for (unsigned int I = 0, E = Sections.size(); I != E; ++I) { const MCSectionELF &Section = *Sections[I]; @@ -1197,8 +1304,8 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, SectionStringTableIndex[&Section] = Index; Index += Name.size() + 1; - F->getContents() += Name; - F->getContents() += '\x00'; + F->getContents().append(Name.begin(), Name.end()); + F->getContents().push_back('\x00'); } } @@ -1284,10 +1391,12 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, // Remove ".rel" and ".rela" prefixes. unsigned SecNameLen = (Section.getType() == ELF::SHT_REL) ? 4 : 5; StringRef SectionName = Section.getSectionName().substr(SecNameLen); + StringRef GroupName = + Section.getGroup() ? Section.getGroup()->getName() : ""; - InfoSection = Asm.getContext().getELFSection(SectionName, - ELF::SHT_PROGBITS, 0, - SectionKind::getReadOnly()); + InfoSection = Asm.getContext().getELFSection(SectionName, ELF::SHT_PROGBITS, + 0, SectionKind::getReadOnly(), + 0, GroupName); sh_info = SectionIndexMap.lookup(InfoSection); break; } @@ -1312,6 +1421,8 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, case ELF::SHT_FINI_ARRAY: case ELF::SHT_PREINIT_ARRAY: case ELF::SHT_X86_64_UNWIND: + case ELF::SHT_MIPS_REGINFO: + case ELF::SHT_MIPS_OPTIONS: // Nothing to do. break; @@ -1325,6 +1436,25 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, break; } + if (TargetObjectWriter->getEMachine() == ELF::EM_ARM && + Section.getType() == ELF::SHT_ARM_EXIDX) { + StringRef SecName(Section.getSectionName()); + if (SecName == ".ARM.exidx") { + sh_link = SectionIndexMap.lookup( + Asm.getContext().getELFSection(".text", + ELF::SHT_PROGBITS, + ELF::SHF_EXECINSTR | ELF::SHF_ALLOC, + SectionKind::getText())); + } else if (SecName.startswith(".ARM.exidx")) { + StringRef GroupName = + Section.getGroup() ? Section.getGroup()->getName() : ""; + sh_link = SectionIndexMap.lookup(Asm.getContext().getELFSection( + SecName.substr(sizeof(".ARM.exidx") - 1), ELF::SHT_PROGBITS, + ELF::SHF_EXECINSTR | ELF::SHF_ALLOC, SectionKind::getText(), 0, + GroupName)); + } + } + WriteSecHdrEntry(SectionStringTableIndex[&Section], Section.getType(), Section.getFlags(), 0, Offset, Size, sh_link, sh_info, Alignment, Section.getEntrySize()); @@ -1373,7 +1503,7 @@ void ELFObjectWriter::WriteDataSectionData(MCAssembler &Asm, ++i) { const MCFragment &F = *i; assert(F.getKind() == MCFragment::FT_Data); - WriteBytes(cast(F).getContents().str()); + WriteBytes(cast(F).getContents()); } } else { Asm.writeSectionData(&SD, Layout); @@ -1471,8 +1601,8 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, unsigned NumRegularSections = NumUserSections + NumIndexedSections; // Compute symbol table information. - ComputeSymbolTable(Asm, SectionIndexMap, RevGroupMap, NumRegularSections); - + computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, + NumRegularSections); WriteRelocations(Asm, const_cast(Layout), RelMap); @@ -1525,7 +1655,7 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, } // Write out the ELF header ... - WriteHeader(SectionHeaderOffset, NumSections + 1); + WriteHeader(Asm, SectionHeaderOffset, NumSections + 1); // ... then the regular sections ... // + because of .shstrtab @@ -1550,7 +1680,7 @@ ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCFragment &FB, bool InSet, bool IsPCRel) const { - if (DataA.getFlags() & ELF_STB_Weak) + if (DataA.getFlags() & ELF_STB_Weak || MCELF::GetType(DataA) == ELF::STT_GNU_IFUNC) return false; return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( Asm, DataA, FB,InSet, IsPCRel);