diff options
Diffstat (limited to 'llvm/lib/MC/ELFObjectWriter.cpp')
-rw-r--r-- | llvm/lib/MC/ELFObjectWriter.cpp | 185 |
1 files changed, 84 insertions, 101 deletions
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 69307b617552..e0ea44626b7f 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -116,21 +116,9 @@ struct ELFWriter { /// Helper struct for containing some precomputed information on symbols. struct ELFSymbolData { const MCSymbolELF *Symbol; - uint32_t SectionIndex; StringRef Name; - - // Support lexicographic sorting. - bool operator<(const ELFSymbolData &RHS) const { - unsigned LHSType = Symbol->getType(); - unsigned RHSType = RHS.Symbol->getType(); - if (LHSType == ELF::STT_SECTION && RHSType != ELF::STT_SECTION) - return false; - if (LHSType != ELF::STT_SECTION && RHSType == ELF::STT_SECTION) - return true; - if (LHSType == ELF::STT_SECTION && RHSType == ELF::STT_SECTION) - return SectionIndex < RHS.SectionIndex; - return Name < RHS.Name; - } + uint32_t SectionIndex; + uint32_t Order; }; /// @} @@ -154,9 +142,9 @@ struct ELFWriter { // TargetObjectWriter wrappers. bool is64Bit() const; - bool hasRelocationAddend() const; + bool usesRela(const MCSectionELF &Sec) const; - void align(unsigned Alignment); + uint64_t align(unsigned Alignment); bool maybeWriteCompression(uint64_t Size, SmallVectorImpl<char> &CompressedContents, @@ -206,8 +194,6 @@ public: MCSectionELF *createRelocationSection(MCContext &Ctx, const MCSectionELF &Sec); - const MCSectionELF *createStringTable(MCContext &Ctx); - void writeSectionHeader(const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, const SectionOffsetsTy &SectionOffsets); @@ -236,6 +222,7 @@ class ELFObjectWriter : public MCObjectWriter { DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames; + bool SeenGnuAbi = false; bool EmitAddrsigSection = false; std::vector<const MCSymbol *> AddrsigSyms; @@ -251,6 +238,7 @@ public: : TargetObjectWriter(std::move(MOTW)) {} void reset() override { + SeenGnuAbi = false; Relocations.clear(); Renames.clear(); MCObjectWriter::reset(); @@ -274,6 +262,8 @@ public: void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; + void markGnuAbi() override { SeenGnuAbi = true; } + bool seenGnuAbi() const { return SeenGnuAbi; } void emitAddrsigSection() override { EmitAddrsigSection = true; } void addAddrsigSymbol(const MCSymbol *Sym) override { AddrsigSyms.push_back(Sym); @@ -336,9 +326,10 @@ public: } // end anonymous namespace -void ELFWriter::align(unsigned Alignment) { - uint64_t Padding = offsetToAlignment(W.OS.tell(), Align(Alignment)); - W.OS.write_zeros(Padding); +uint64_t ELFWriter::align(unsigned Alignment) { + uint64_t Offset = W.OS.tell(), NewOffset = alignTo(Offset, Alignment); + W.OS.write_zeros(NewOffset - Offset); + return NewOffset; } unsigned ELFWriter::addToSectionTable(const MCSectionELF *Sec) { @@ -401,8 +392,9 @@ bool ELFWriter::is64Bit() const { return OWriter.TargetObjectWriter->is64Bit(); } -bool ELFWriter::hasRelocationAddend() const { - return OWriter.hasRelocationAddend(); +bool ELFWriter::usesRela(const MCSectionELF &Sec) const { + return OWriter.hasRelocationAddend() && + Sec.getType() != ELF::SHT_LLVM_CALL_GRAPH_PROFILE; } // Emit the ELF header. @@ -425,7 +417,10 @@ void ELFWriter::writeHeader(const MCAssembler &Asm) { W.OS << char(ELF::EV_CURRENT); // e_ident[EI_VERSION] // e_ident[EI_OSABI] - W.OS << char(OWriter.TargetObjectWriter->getOSABI()); + uint8_t OSABI = OWriter.TargetObjectWriter->getOSABI(); + W.OS << char(OSABI == ELF::ELFOSABI_NONE && OWriter.seenGnuAbi() + ? int(ELF::ELFOSABI_GNU) + : OSABI); // e_ident[EI_ABIVERSION] W.OS << char(OWriter.TargetObjectWriter->getABIVersion()); @@ -457,7 +452,7 @@ void ELFWriter::writeHeader(const MCAssembler &Asm) { // e_shnum = # of section header ents W.write<uint16_t>(0); - // e_shstrndx = Section # of '.shstrtab' + // e_shstrndx = Section # of '.strtab' assert(StringTableIndex < ELF::SHN_LORESERVE); W.write<uint16_t>(StringTableIndex); } @@ -614,23 +609,26 @@ void ELFWriter::computeSymbolTable( // Symbol table unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32; MCSectionELF *SymtabSection = - Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize, ""); + Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize); SymtabSection->setAlignment(is64Bit() ? Align(8) : Align(4)); SymbolTableIndex = addToSectionTable(SymtabSection); - align(SymtabSection->getAlignment()); - uint64_t SecStart = W.OS.tell(); + uint64_t SecStart = align(SymtabSection->getAlignment()); // The first entry is the undefined symbol entry. Writer.writeSymbol(0, 0, 0, 0, 0, 0, false); std::vector<ELFSymbolData> LocalSymbolData; std::vector<ELFSymbolData> ExternalSymbolData; + MutableArrayRef<std::pair<std::string, size_t>> FileNames = + Asm.getFileNames(); + for (const std::pair<std::string, size_t> &F : FileNames) + StrTabBuilder.add(F.first); // Add the data for the symbols. bool HasLargeSectionIndex = false; - for (const MCSymbol &S : Asm.symbols()) { - const auto &Symbol = cast<MCSymbolELF>(S); + for (auto It : llvm::enumerate(Asm.symbols())) { + const auto &Symbol = cast<MCSymbolELF>(It.value()); bool Used = Symbol.isUsedInReloc(); bool WeakrefUsed = Symbol.isWeakrefUsedInReloc(); bool isSignature = Symbol.isSignature(); @@ -646,6 +644,7 @@ void ELFWriter::computeSymbolTable( ELFSymbolData MSD; MSD.Symbol = cast<MCSymbolELF>(&Symbol); + MSD.Order = It.index(); bool Local = Symbol.getBinding() == ELF::STB_LOCAL; assert(Local || !Symbol.isTemporary()); @@ -711,39 +710,41 @@ void ELFWriter::computeSymbolTable( if (HasLargeSectionIndex) { MCSectionELF *SymtabShndxSection = - Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0, 4, ""); + Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0, 4); SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection); SymtabShndxSection->setAlignment(Align(4)); } - ArrayRef<std::string> FileNames = Asm.getFileNames(); - for (const std::string &Name : FileNames) - StrTabBuilder.add(Name); - StrTabBuilder.finalize(); - // File symbols are emitted first and handled separately from normal symbols, - // i.e. a non-STT_FILE symbol with the same name may appear. - for (const std::string &Name : FileNames) - Writer.writeSymbol(StrTabBuilder.getOffset(Name), - ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT, - ELF::SHN_ABS, true); - - // Symbols are required to be in lexicographic order. - array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end()); - array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); - - // Set the symbol indices. Local symbols must come before all other - // symbols with non-local bindings. - unsigned Index = FileNames.size() + 1; + // Make the first STT_FILE precede previous local symbols. + unsigned Index = 1; + auto FileNameIt = FileNames.begin(); + if (!FileNames.empty()) + FileNames[0].second = 0; for (ELFSymbolData &MSD : LocalSymbolData) { + // Emit STT_FILE symbols before their associated local symbols. + for (; FileNameIt != FileNames.end() && FileNameIt->second <= MSD.Order; + ++FileNameIt) { + Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first), + ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT, + ELF::SHN_ABS, true); + ++Index; + } + unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION ? 0 : StrTabBuilder.getOffset(MSD.Name); MSD.Symbol->setIndex(Index++); writeSymbol(Writer, StringIndex, MSD, Layout); } + for (; FileNameIt != FileNames.end(); ++FileNameIt) { + Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first), + ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT, + ELF::SHN_ABS, true); + ++Index; + } // Write the symbol table entries. LastLocalSymbolIndex = Index; @@ -785,11 +786,12 @@ MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx, return nullptr; const StringRef SectionName = Sec.getName(); - std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel"; + bool Rela = usesRela(Sec); + std::string RelaSectionName = Rela ? ".rela" : ".rel"; RelaSectionName += SectionName; unsigned EntrySize; - if (hasRelocationAddend()) + if (Rela) EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela); else EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel); @@ -799,8 +801,8 @@ MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx, Flags = ELF::SHF_GROUP; MCSectionELF *RelaSection = Ctx.createELFRelSection( - RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL, - Flags, EntrySize, Sec.getGroup(), &Sec); + RelaSectionName, Rela ? ELF::SHT_RELA : ELF::SHT_REL, Flags, EntrySize, + Sec.getGroup(), &Sec); RelaSection->setAlignment(is64Bit() ? Align(8) : Align(4)); return RelaSection; } @@ -925,6 +927,7 @@ void ELFWriter::writeRelocations(const MCAssembler &Asm, // Sort the relocation entries. MIPS needs this. OWriter.TargetObjectWriter->sortRelocs(Asm, Relocs); + const bool Rela = usesRela(Sec); for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { const ELFRelocationEntry &Entry = Relocs[e - i - 1]; unsigned Index = Entry.Symbol ? Entry.Symbol->getIndex() : 0; @@ -943,7 +946,7 @@ void ELFWriter::writeRelocations(const MCAssembler &Asm, ERE64.setSymbolAndType(Index, Entry.Type); write(ERE64.r_info); } - if (hasRelocationAddend()) + if (Rela) write(Entry.Addend); } else { write(uint32_t(Entry.Offset)); @@ -952,7 +955,7 @@ void ELFWriter::writeRelocations(const MCAssembler &Asm, ERE32.setSymbolAndType(Index, Entry.Type); write(ERE32.r_info); - if (hasRelocationAddend()) + if (Rela) write(uint32_t(Entry.Addend)); if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) { @@ -977,12 +980,6 @@ void ELFWriter::writeRelocations(const MCAssembler &Asm, } } -const MCSectionELF *ELFWriter::createStringTable(MCContext &Ctx) { - const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1]; - StrTabBuilder.write(W.OS); - return StrtabSection; -} - void ELFWriter::writeSection(const SectionIndexMapTy &SectionIndexMap, uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size, const MCSectionELF &Section) { @@ -1097,10 +1094,8 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { if (Mode == DwoOnly && !isDwoSection(Section)) continue; - align(Section.getAlignment()); - // Remember the offset into the file for this section. - uint64_t SecStart = W.OS.tell(); + const uint64_t SecStart = align(Section.getAlignment()); const MCSymbolELF *SignatureSymbol = Section.getGroup(); writeSectionData(Asm, Section, Layout); @@ -1111,10 +1106,10 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { MCSectionELF *RelSection = createRelocationSection(Ctx, Section); if (SignatureSymbol) { - Asm.registerSymbol(*SignatureSymbol); unsigned &GroupIdx = RevGroupMap[SignatureSymbol]; if (!GroupIdx) { - MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol); + MCSectionELF *Group = + Ctx.createELFGroupSection(SignatureSymbol, Section.isComdat()); GroupIdx = addToSectionTable(Group); Group->setAlignment(Align(4)); Groups.push_back(Group); @@ -1135,23 +1130,13 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { OWriter.TargetObjectWriter->addTargetSectionFlags(Ctx, Section); } - MCSectionELF *CGProfileSection = nullptr; - if (!Asm.CGProfile.empty()) { - CGProfileSection = Ctx.getELFSection(".llvm.call-graph-profile", - ELF::SHT_LLVM_CALL_GRAPH_PROFILE, - ELF::SHF_EXCLUDE, 16, ""); - SectionIndexMap[CGProfileSection] = addToSectionTable(CGProfileSection); - } - for (MCSectionELF *Group : Groups) { - align(Group->getAlignment()); - // Remember the offset into the file for this section. - uint64_t SecStart = W.OS.tell(); + const uint64_t SecStart = align(Group->getAlignment()); const MCSymbol *SignatureSymbol = Group->getGroup(); assert(SignatureSymbol); - write(uint32_t(ELF::GRP_COMDAT)); + write(uint32_t(Group->isComdat() ? unsigned(ELF::GRP_COMDAT) : 0)); for (const MCSectionELF *Member : GroupMembers[SignatureSymbol]) { uint32_t SecIndex = SectionIndexMap.lookup(Member); write(SecIndex); @@ -1178,10 +1163,8 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { SectionOffsets); for (MCSectionELF *RelSection : Relocations) { - align(RelSection->getAlignment()); - // Remember the offset into the file for this section. - uint64_t SecStart = W.OS.tell(); + const uint64_t SecStart = align(RelSection->getAlignment()); writeRelocations(Asm, cast<MCSectionELF>(*RelSection->getLinkedToSection())); @@ -1198,28 +1181,13 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { } } - if (CGProfileSection) { - uint64_t SecStart = W.OS.tell(); - for (const MCAssembler::CGProfileEntry &CGPE : Asm.CGProfile) { - W.write<uint32_t>(CGPE.From->getSymbol().getIndex()); - W.write<uint32_t>(CGPE.To->getSymbol().getIndex()); - W.write<uint64_t>(CGPE.Count); - } - uint64_t SecEnd = W.OS.tell(); - SectionOffsets[CGProfileSection] = std::make_pair(SecStart, SecEnd); - } - { uint64_t SecStart = W.OS.tell(); - const MCSectionELF *Sec = createStringTable(Ctx); - uint64_t SecEnd = W.OS.tell(); - SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd); + StrTabBuilder.write(W.OS); + SectionOffsets[StrtabSection] = std::make_pair(SecStart, W.OS.tell()); } - uint64_t NaturalAlignment = is64Bit() ? 8 : 4; - align(NaturalAlignment); - - const uint64_t SectionHeaderOffset = W.OS.tell(); + const uint64_t SectionHeaderOffset = align(is64Bit() ? 8 : 4); // ... then the section header table ... writeSectionHeader(Layout, SectionIndexMap, SectionOffsets); @@ -1282,7 +1250,7 @@ void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, Alias->setVisibility(Symbol.getVisibility()); Alias->setOther(Symbol.getOther()); - if (!Symbol.isUndefined() && !Rest.startswith("@@@")) + if (!Symbol.isUndefined() && S.KeepOriginalSym) continue; if (Symbol.isUndefined() && Rest.startswith("@@") && @@ -1397,6 +1365,17 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm, if (TargetObjectWriter->getEMachine() == ELF::EM_386 && Type == ELF::R_386_GOTOFF) return true; + + // ld.lld handles R_MIPS_HI16/R_MIPS_LO16 separately, not as a whole, so + // it doesn't know that an R_MIPS_HI16 with implicit addend 1 and an + // R_MIPS_LO16 with implicit addend -32768 represents 32768, which is in + // range of a MergeInputSection. We could introduce a new RelExpr member + // (like R_RISCV_PC_INDIRECT for R_RISCV_PCREL_HI20 / R_RISCV_PCREL_LO12) + // but the complexity is unnecessary given that GNU as keeps the original + // symbol for this case as well. + if (TargetObjectWriter->getEMachine() == ELF::EM_MIPS && + !hasRelocationAddend()) + return true; } // Most TLS relocations use a got, so they need the symbol. Even those that @@ -1476,7 +1455,11 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm, return; unsigned Type = TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel); - bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type); + const auto *Parent = cast<MCSectionELF>(Fragment->getParent()); + // Emiting relocation with sybmol for CG Profile to help with --cg-profile. + bool RelocateWithSymbol = + shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type) || + (Parent->getType() == ELF::SHT_LLVM_CALL_GRAPH_PROFILE); uint64_t Addend = 0; FixedValue = !RelocateWithSymbol && SymA && !SymA->isUndefined() |