[llvm-objcopy] Route section copies through writeSectionContents - #217974
[llvm-objcopy] Route section copies through writeSectionContents#217974fzakaria wants to merge 1 commit into
Conversation
Centralize section byte copies behind a virtual helper so ELF output can later target either a memory buffer or a seekable stream. Materialize SHT_SYMTAB_SHNDX entries using the target ELF word type to preserve output endianness. Co-authored-by: Jeremy Braun <jtbraun@meta.com> Assisted-by: OpenAI Codex
|
@llvm/pr-subscribers-llvm-binary-utilities Author: Farid Zakaria (fzakaria) ChangesMotivationThe ELF section writers currently copy section contents directly into a ChangeThis change adds a virtual While routing This change was developed with assistance from OpenAI Codex and includes a trailer following the AI policy. Full diff: https://github.com/llvm/llvm-project/pull/217974.diff 3 Files Affected:
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index ac818343f3f8f..dace67fdca44d 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -183,9 +183,14 @@ Error BinarySectionWriter::visit(const GroupSection &Sec) {
"cannot write '" + Sec.Name + "' out to binary");
}
+void SectionWriter::writeSectionContents(ArrayRef<uint8_t> Data,
+ uint64_t Offset) {
+ llvm::copy(Data, Out.getBufferStart() + Offset);
+}
+
Error SectionWriter::visit(const Section &Sec) {
if (Sec.Type != SHT_NOBITS)
- llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);
+ writeSectionContents(Sec.Contents, Sec.Offset);
return Error::success();
}
@@ -453,7 +458,7 @@ void Section::restoreSymTabLink(SymbolTableSection &SymTab) {
}
Error SectionWriter::visit(const OwnedDataSection &Sec) {
- llvm::copy(Sec.Data, Out.getBufferStart() + Sec.Offset);
+ writeSectionContents(Sec.Data, Sec.Offset);
return Error::success();
}
@@ -487,9 +492,7 @@ Error ELFSectionWriter<ELFT>::visit(const DecompressedSection &Sec) {
"failed to decompress section '" + Sec.Name +
"': " + toString(std::move(E)));
- uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
- llvm::copy(Decompressed, Buf);
-
+ writeSectionContents(Decompressed, Sec.Offset);
return Error::success();
}
@@ -532,11 +535,10 @@ Error BinarySectionWriter::visit(const CompressedSection &Sec) {
template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const CompressedSection &Sec) {
- uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
Elf_Chdr_Impl<ELFT> Chdr = {};
switch (Sec.CompressionType) {
case DebugCompressionType::None:
- llvm::copy(Sec.OriginalData, Buf);
+ writeSectionContents(Sec.OriginalData, Sec.Offset);
return Error::success();
case DebugCompressionType::Zlib:
Chdr.ch_type = ELF::ELFCOMPRESS_ZLIB;
@@ -547,10 +549,10 @@ Error ELFSectionWriter<ELFT>::visit(const CompressedSection &Sec) {
}
Chdr.ch_size = Sec.DecompressedSize;
Chdr.ch_addralign = Sec.DecompressedAlign;
- memcpy(Buf, &Chdr, sizeof(Chdr));
- Buf += sizeof(Chdr);
-
- llvm::copy(Sec.CompressedData, Buf);
+ writeSectionContents(
+ ArrayRef(reinterpret_cast<const uint8_t *>(&Chdr), sizeof(Chdr)),
+ Sec.Offset);
+ writeSectionContents(Sec.CompressedData, Sec.Offset + sizeof(Chdr));
return Error::success();
}
@@ -613,8 +615,14 @@ Error StringTableSection::accept(MutableSectionVisitor &Visitor) {
template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const SectionIndexSection &Sec) {
- uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
- llvm::copy(Sec.Indexes, reinterpret_cast<Elf_Word *>(Buf));
+ SmallVector<Elf_Word, 0> Indexes;
+ Indexes.reserve(Sec.Indexes.size());
+ for (uint32_t Index : Sec.Indexes)
+ Indexes.emplace_back(Index);
+ writeSectionContents(
+ ArrayRef(reinterpret_cast<const uint8_t *>(Indexes.data()),
+ Indexes.size() * sizeof(Elf_Word)),
+ Sec.Offset);
return Error::success();
}
@@ -1029,7 +1037,7 @@ void RelocationSection::replaceSectionReferences(
}
Error SectionWriter::visit(const DynamicRelocationSection &Sec) {
- llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);
+ writeSectionContents(Sec.Contents, Sec.Offset);
return Error::success();
}
@@ -1182,7 +1190,10 @@ Error ELFSectionWriter<ELFT>::visit(const GnuDebugLinkSection &Sec) {
Elf_Word *CRC =
reinterpret_cast<Elf_Word *>(Buf + Sec.Size - sizeof(Elf_Word));
*CRC = Sec.CRC32;
- llvm::copy(Sec.FileName, Buf);
+ writeSectionContents(
+ ArrayRef(reinterpret_cast<const uint8_t *>(Sec.FileName.data()),
+ Sec.FileName.size()),
+ Sec.Offset);
return Error::success();
}
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h
index 2783ef27ac9de..9df62d8642917 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.h
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.h
@@ -107,6 +107,7 @@ class MutableSectionVisitor {
class SectionWriter : public SectionVisitor {
protected:
WritableMemoryBuffer &Out;
+ virtual void writeSectionContents(ArrayRef<uint8_t> Data, uint64_t Offset);
public:
~SectionWriter() override = default;
diff --git a/llvm/test/tools/llvm-objcopy/ELF/many-sections.test b/llvm/test/tools/llvm-objcopy/ELF/many-sections.test
index 6622db237026f..64ee1e4b4b48b 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/many-sections.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/many-sections.test
@@ -5,6 +5,10 @@ RUN: llvm-objcopy %t %t2
RUN: llvm-readobj --file-headers --sections --symbols %t2 | FileCheck %s
RUN: llvm-readelf --symbols %t2 | FileCheck --check-prefix=SYMS %s
+## Check that SHT_SYMTAB_SHNDX entries use the output endianness.
+RUN: llvm-objcopy --output-target=elf64-s390 %t %t.be
+RUN: llvm-readobj --file-headers --sections --symbols %t.be | FileCheck %s
+
## The ELF header should have e_shnum == 0 and e_shstrndx == SHN_XINDEX.
# CHECK: SectionHeaderCount: 0
# CHECK-NEXT: StringTableSectionIndex: 65535
|
Motivation
The ELF section writers currently copy section contents directly into a
WritableMemoryBuffer. Before introducing an alternative output implementation, these writes need to go through a common function.Change
This change adds a virtual
writeSectionContentshelper and routes the section byte-copy paths through it. The default implementation continues to write into the existing memory buffer, so this does not change the output strategy by itself.While routing
SHT_SYMTAB_SHNDXthrough the helper, the indexes are materialized using the targetElf_Wordtype. This ensures that the entries use the output ELF endianness when converting between formats. The big-endian test case exercises this behavior.This change was developed with assistance from OpenAI Codex and includes a trailer following the AI policy.