diff options
Diffstat (limited to 'llvm/lib/MC/ELFObjectWriter.cpp')
-rw-r--r-- | llvm/lib/MC/ELFObjectWriter.cpp | 103 |
1 files changed, 71 insertions, 32 deletions
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index f6360c4e2f21..07ed3409707b 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -142,11 +142,11 @@ struct ELFWriter { bool is64Bit() const; bool usesRela(const MCSectionELF &Sec) const; - uint64_t align(unsigned Alignment); + uint64_t align(Align Alignment); bool maybeWriteCompression(uint32_t ChType, uint64_t Size, SmallVectorImpl<uint8_t> &CompressedContents, - unsigned Alignment); + Align Alignment); public: ELFWriter(ELFObjectWriter &OWriter, raw_pwrite_stream &OS, @@ -192,6 +192,8 @@ public: MCSectionELF *createRelocationSection(MCContext &Ctx, const MCSectionELF &Sec); + void createMemtagRelocs(MCAssembler &Asm); + void writeSectionHeader(const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, const SectionOffsetsTy &SectionOffsets); @@ -201,7 +203,7 @@ public: 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, + uint32_t Link, uint32_t Info, MaybeAlign Alignment, uint64_t EntrySize); void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec); @@ -317,8 +319,9 @@ public: } // end anonymous namespace -uint64_t ELFWriter::align(unsigned Alignment) { - uint64_t Offset = W.OS.tell(), NewOffset = alignTo(Offset, Alignment); +uint64_t ELFWriter::align(Align Alignment) { + uint64_t Offset = W.OS.tell(); + uint64_t NewOffset = alignTo(Offset, Alignment); W.OS.write_zeros(NewOffset - Offset); return NewOffset; } @@ -451,7 +454,7 @@ void ELFWriter::writeHeader(const MCAssembler &Asm) { uint64_t ELFWriter::SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout) { if (Sym.isCommon()) - return Sym.getCommonAlignment(); + return Sym.getCommonAlignment()->value(); uint64_t Res; if (!Layout.getSymbolOffset(Sym, Res)) @@ -608,6 +611,23 @@ bool ELFWriter::isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol, return true; } +void ELFWriter::createMemtagRelocs(MCAssembler &Asm) { + MCSectionELF *MemtagRelocs = nullptr; + for (const MCSymbol &Sym : Asm.symbols()) { + const auto &SymE = cast<MCSymbolELF>(Sym); + if (!SymE.isMemtag()) + continue; + if (MemtagRelocs == nullptr) { + MemtagRelocs = OWriter.TargetObjectWriter->getMemtagRelocsSection(Asm.getContext()); + if (MemtagRelocs == nullptr) + report_fatal_error("Tagged globals are not available on this architecture."); + Asm.registerSection(*MemtagRelocs); + } + ELFRelocationEntry Rec(0, &SymE, ELF::R_AARCH64_NONE, 0, nullptr, 0); + OWriter.Relocations[MemtagRelocs].push_back(Rec); + } +} + void ELFWriter::computeSymbolTable( MCAssembler &Asm, const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap, @@ -622,7 +642,7 @@ void ELFWriter::computeSymbolTable( SymtabSection->setAlignment(is64Bit() ? Align(8) : Align(4)); SymbolTableIndex = addToSectionTable(SymtabSection); - uint64_t SecStart = align(SymtabSection->getAlignment()); + uint64_t SecStart = align(SymtabSection->getAlign()); // The first entry is the undefined symbol entry. Writer.writeSymbol(0, 0, 0, 0, 0, 0, false); @@ -786,7 +806,8 @@ void ELFWriter::computeSymbolTable( void ELFWriter::writeAddrsigSection() { for (const MCSymbol *Sym : OWriter.AddrsigSyms) - encodeULEB128(Sym->getIndex(), W.OS); + if (Sym->getIndex() != 0) + encodeULEB128(Sym->getIndex(), W.OS); } MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx, @@ -819,7 +840,7 @@ MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx, // Include the debug info compression header. bool ELFWriter::maybeWriteCompression( uint32_t ChType, uint64_t Size, - SmallVectorImpl<uint8_t> &CompressedContents, unsigned Alignment) { + SmallVectorImpl<uint8_t> &CompressedContents, Align Alignment) { uint64_t HdrSize = is64Bit() ? sizeof(ELF::Elf32_Chdr) : sizeof(ELF::Elf64_Chdr); if (Size <= HdrSize + CompressedContents.size()) @@ -830,12 +851,12 @@ bool ELFWriter::maybeWriteCompression( write(static_cast<ELF::Elf64_Word>(ChType)); write(static_cast<ELF::Elf64_Word>(0)); // ch_reserved field. write(static_cast<ELF::Elf64_Xword>(Size)); - write(static_cast<ELF::Elf64_Xword>(Alignment)); + write(static_cast<ELF::Elf64_Xword>(Alignment.value())); } else { // Write Elf32_Chdr header otherwise. write(static_cast<ELF::Elf32_Word>(ChType)); write(static_cast<ELF::Elf32_Word>(Size)); - write(static_cast<ELF::Elf32_Word>(Alignment)); + write(static_cast<ELF::Elf32_Word>(Alignment.value())); } return true; } @@ -848,29 +869,36 @@ void ELFWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, auto &MC = Asm.getContext(); const auto &MAI = MC.getAsmInfo(); - bool CompressionEnabled = - MAI->compressDebugSections() != DebugCompressionType::None; - if (!CompressionEnabled || !SectionName.startswith(".debug_")) { + const DebugCompressionType CompressionType = MAI->compressDebugSections(); + if (CompressionType == DebugCompressionType::None || + !SectionName.startswith(".debug_")) { Asm.writeSectionData(W.OS, &Section, Layout); return; } - assert(MAI->compressDebugSections() == DebugCompressionType::Z && - "expected zlib style compression"); - SmallVector<char, 128> UncompressedData; raw_svector_ostream VecOS(UncompressedData); Asm.writeSectionData(VecOS, &Section, Layout); + ArrayRef<uint8_t> Uncompressed = + ArrayRef(reinterpret_cast<uint8_t *>(UncompressedData.data()), + UncompressedData.size()); SmallVector<uint8_t, 128> Compressed; - const uint32_t ChType = ELF::ELFCOMPRESS_ZLIB; - compression::zlib::compress( - makeArrayRef(reinterpret_cast<uint8_t *>(UncompressedData.data()), - UncompressedData.size()), - Compressed); - + uint32_t ChType; + switch (CompressionType) { + case DebugCompressionType::None: + llvm_unreachable("has been handled"); + case DebugCompressionType::Zlib: + ChType = ELF::ELFCOMPRESS_ZLIB; + break; + case DebugCompressionType::Zstd: + ChType = ELF::ELFCOMPRESS_ZSTD; + break; + } + compression::compress(compression::Params(CompressionType), Uncompressed, + Compressed); if (!maybeWriteCompression(ChType, UncompressedData.size(), Compressed, - Sec.getAlignment())) { + Sec.getAlign())) { W.OS << UncompressedData; return; } @@ -885,7 +913,7 @@ void ELFWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, void ELFWriter::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) { + MaybeAlign Alignment, uint64_t EntrySize) { W.write<uint32_t>(Name); // sh_name: index into string table W.write<uint32_t>(Type); // sh_type WriteWord(Flags); // sh_flags @@ -894,7 +922,7 @@ void ELFWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, WriteWord(Size); // sh_size W.write<uint32_t>(Link); // sh_link W.write<uint32_t>(Info); // sh_info - WriteWord(Alignment); // sh_addralign + WriteWord(Alignment ? Alignment->value() : 0); // sh_addralign WriteWord(EntrySize); // sh_entsize } @@ -1016,7 +1044,7 @@ void ELFWriter::writeSection(const SectionIndexMapTy &SectionIndexMap, WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getName()), Section.getType(), Section.getFlags(), 0, Offset, Size, - sh_link, sh_info, Section.getAlignment(), + sh_link, sh_info, Section.getAlign(), Section.getEntrySize()); } @@ -1028,7 +1056,7 @@ void ELFWriter::writeSectionHeader( // Null section first. uint64_t FirstSectionSize = (NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 1 : 0; - WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, 0, 0); + WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, std::nullopt, 0); for (const MCSectionELF *Section : SectionTable) { uint32_t GroupSymbolIndex; @@ -1059,6 +1087,8 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0); StringTableIndex = addToSectionTable(StrtabSection); + createMemtagRelocs(Asm); + RevGroupMapTy RevGroupMap; SectionIndexMapTy SectionIndexMap; @@ -1079,7 +1109,7 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { continue; // Remember the offset into the file for this section. - const uint64_t SecStart = align(Section.getAlignment()); + const uint64_t SecStart = align(Section.getAlign()); const MCSymbolELF *SignatureSymbol = Section.getGroup(); writeSectionData(Asm, Section, Layout); @@ -1116,7 +1146,7 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { for (MCSectionELF *Group : Groups) { // Remember the offset into the file for this section. - const uint64_t SecStart = align(Group->getAlignment()); + const uint64_t SecStart = align(Group->getAlign()); const MCSymbol *SignatureSymbol = Group->getGroup(); assert(SignatureSymbol); @@ -1148,7 +1178,7 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { for (MCSectionELF *RelSection : Relocations) { // Remember the offset into the file for this section. - const uint64_t SecStart = align(RelSection->getAlignment()); + const uint64_t SecStart = align(RelSection->getAlign()); writeRelocations(Asm, cast<MCSectionELF>(*RelSection->getLinkedToSection())); @@ -1171,7 +1201,7 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { SectionOffsets[StrtabSection] = std::make_pair(SecStart, W.OS.tell()); } - const uint64_t SectionHeaderOffset = align(is64Bit() ? 8 : 4); + const uint64_t SectionHeaderOffset = align(is64Bit() ? Align(8) : Align(4)); // ... then the section header table ... writeSectionHeader(Layout, SectionIndexMap, SectionOffsets); @@ -1308,6 +1338,15 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm, if (Sym->isUndefined()) return true; + // For memory-tagged symbols, ensure that the relocation uses the symbol. For + // tagged symbols, we emit an empty relocation (R_AARCH64_NONE) in a special + // section (SHT_AARCH64_MEMTAG_GLOBALS_STATIC) to indicate to the linker that + // this global needs to be tagged. In addition, the linker needs to know + // whether to emit a special addend when relocating `end` symbols, and this + // can only be determined by the attributes of the symbol itself. + if (Sym->isMemtag()) + return true; + unsigned Binding = Sym->getBinding(); switch(Binding) { default: |