[llvm-objcopy]Allow llvm-objcopy to be used on an ELF file with no section headers

This patch fixes https://bugs.llvm.org/show_bug.cgi?id=41293 and
https://bugs.llvm.org/show_bug.cgi?id=41045. llvm-objcopy assumed that
it could always read a section header string table. This isn't the case
when the sections were previously all stripped, and the e_shstrndx field
was set to 0. This patch fixes this. It also fixes a double space in an
error message relating to this issue, and prevents llvm-objcopy from
adding extra space for non-existent section headers, meaning that
--strip-sections on the output of a previous --strip-sections run
produces identical output, simplifying the test.

Reviewed by: rupprecht, grimar

Differential Revision: https://reviews.llvm.org/D59989

llvm-svn: 357475
This commit is contained in:
James Henderson 2019-04-02 14:11:13 +00:00
parent 68ad5c34e0
commit 38cb238f75
3 changed files with 47 additions and 13 deletions

View File

@ -0,0 +1,26 @@
# llvm-objcopy's --strip-sections removes the section headers. It should be
# possible to run the tool on the output after this operation. Performing any
# subsequent stripping operation, or copying the object, should produce
# identical output.
# RUN: yaml2obj %s -o %t.in
# RUN: llvm-objcopy %t.in %t.stripped --strip-sections
# RUN: llvm-objcopy %t.stripped %t.stripped2 --strip-sections
# RUN: llvm-objcopy %t.stripped2 %t.out
# RUN: cmp %t.stripped %t.stripped2
# RUN: cmp %t.stripped %t.out
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Content: 'facefeed'
ProgramHeaders:
- Type: PT_LOAD
Sections:
- Section: .text

View File

@ -1212,13 +1212,16 @@ template <class ELFT> void ELFBuilder<ELFT>::build() {
if (ShstrIndex == SHN_XINDEX) if (ShstrIndex == SHN_XINDEX)
ShstrIndex = unwrapOrError(ElfFile.getSection(0))->sh_link; ShstrIndex = unwrapOrError(ElfFile.getSection(0))->sh_link;
Obj.SectionNames = if (ShstrIndex == SHN_UNDEF)
Obj.sections().template getSectionOfType<StringTableSection>( Obj.HadShdrs = false;
ShstrIndex, else
"e_shstrndx field value " + Twine(Ehdr.e_shstrndx) + Obj.SectionNames =
" in elf header " + " is invalid", Obj.sections().template getSectionOfType<StringTableSection>(
"e_shstrndx field value " + Twine(Ehdr.e_shstrndx) + ShstrIndex,
" in elf header " + " is not a string table"); "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
" in elf header is invalid",
"e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
" in elf header is not a string table");
} }
Writer::~Writer() {} Writer::~Writer() {}
@ -1372,6 +1375,10 @@ template <class ELFT> void ELFWriter<ELFT>::writeSegmentData() {
} }
} }
template <class ELFT>
ELFWriter<ELFT>::ELFWriter(Object &Obj, Buffer &Buf, bool WSH)
: Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs) {}
Error Object::removeSections( Error Object::removeSections(
std::function<bool(const SectionBase &)> ToRemove) { std::function<bool(const SectionBase &)> ToRemove) {
@ -1558,9 +1565,10 @@ template <class ELFT> void ELFWriter<ELFT>::assignOffsets() {
template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const { template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const {
// We already have the section header offset so we can calculate the total // We already have the section header offset so we can calculate the total
// size by just adding up the size of each section header. // size by just adding up the size of each section header.
auto NullSectionSize = WriteSectionHeaders ? sizeof(Elf_Shdr) : 0; if (!WriteSectionHeaders)
return Obj.SHOffset + Obj.sections().size() * sizeof(Elf_Shdr) + return Obj.SHOffset;
NullSectionSize; size_t ShdrCount = Obj.sections().size() + 1; // Includes null shdr.
return Obj.SHOffset + ShdrCount * sizeof(Elf_Shdr);
} }
template <class ELFT> Error ELFWriter<ELFT>::write() { template <class ELFT> Error ELFWriter<ELFT>::write() {

View File

@ -226,12 +226,11 @@ private:
public: public:
virtual ~ELFWriter() {} virtual ~ELFWriter() {}
bool WriteSectionHeaders = true; bool WriteSectionHeaders;
Error finalize() override; Error finalize() override;
Error write() override; Error write() override;
ELFWriter(Object &Obj, Buffer &Buf, bool WSH) ELFWriter(Object &Obj, Buffer &Buf, bool WSH);
: Writer(Obj, Buf), WriteSectionHeaders(WSH) {}
}; };
class BinaryWriter : public Writer { class BinaryWriter : public Writer {
@ -810,6 +809,7 @@ public:
uint32_t Version; uint32_t Version;
uint32_t Flags; uint32_t Flags;
bool HadShdrs = true;
StringTableSection *SectionNames = nullptr; StringTableSection *SectionNames = nullptr;
SymbolTableSection *SymbolTable = nullptr; SymbolTableSection *SymbolTable = nullptr;
SectionIndexSection *SectionIndexTable = nullptr; SectionIndexSection *SectionIndexTable = nullptr;