Skip to content

Commit 38cb238

Browse files
committed
[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
1 parent 68ad5c3 commit 38cb238

File tree

3 files changed

+47
-13
lines changed

3 files changed

+47
-13
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# llvm-objcopy's --strip-sections removes the section headers. It should be
2+
# possible to run the tool on the output after this operation. Performing any
3+
# subsequent stripping operation, or copying the object, should produce
4+
# identical output.
5+
6+
# RUN: yaml2obj %s -o %t.in
7+
# RUN: llvm-objcopy %t.in %t.stripped --strip-sections
8+
# RUN: llvm-objcopy %t.stripped %t.stripped2 --strip-sections
9+
# RUN: llvm-objcopy %t.stripped2 %t.out
10+
# RUN: cmp %t.stripped %t.stripped2
11+
# RUN: cmp %t.stripped %t.out
12+
13+
--- !ELF
14+
FileHeader:
15+
Class: ELFCLASS64
16+
Data: ELFDATA2LSB
17+
Type: ET_EXEC
18+
Machine: EM_X86_64
19+
Sections:
20+
- Name: .text
21+
Type: SHT_PROGBITS
22+
Content: 'facefeed'
23+
ProgramHeaders:
24+
- Type: PT_LOAD
25+
Sections:
26+
- Section: .text

llvm/tools/llvm-objcopy/ELF/Object.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,13 +1212,16 @@ template <class ELFT> void ELFBuilder<ELFT>::build() {
12121212
if (ShstrIndex == SHN_XINDEX)
12131213
ShstrIndex = unwrapOrError(ElfFile.getSection(0))->sh_link;
12141214

1215-
Obj.SectionNames =
1216-
Obj.sections().template getSectionOfType<StringTableSection>(
1217-
ShstrIndex,
1218-
"e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
1219-
" in elf header " + " is invalid",
1220-
"e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
1221-
" in elf header " + " is not a string table");
1215+
if (ShstrIndex == SHN_UNDEF)
1216+
Obj.HadShdrs = false;
1217+
else
1218+
Obj.SectionNames =
1219+
Obj.sections().template getSectionOfType<StringTableSection>(
1220+
ShstrIndex,
1221+
"e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
1222+
" in elf header is invalid",
1223+
"e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
1224+
" in elf header is not a string table");
12221225
}
12231226

12241227
Writer::~Writer() {}
@@ -1372,6 +1375,10 @@ template <class ELFT> void ELFWriter<ELFT>::writeSegmentData() {
13721375
}
13731376
}
13741377

1378+
template <class ELFT>
1379+
ELFWriter<ELFT>::ELFWriter(Object &Obj, Buffer &Buf, bool WSH)
1380+
: Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs) {}
1381+
13751382
Error Object::removeSections(
13761383
std::function<bool(const SectionBase &)> ToRemove) {
13771384

@@ -1558,9 +1565,10 @@ template <class ELFT> void ELFWriter<ELFT>::assignOffsets() {
15581565
template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const {
15591566
// We already have the section header offset so we can calculate the total
15601567
// size by just adding up the size of each section header.
1561-
auto NullSectionSize = WriteSectionHeaders ? sizeof(Elf_Shdr) : 0;
1562-
return Obj.SHOffset + Obj.sections().size() * sizeof(Elf_Shdr) +
1563-
NullSectionSize;
1568+
if (!WriteSectionHeaders)
1569+
return Obj.SHOffset;
1570+
size_t ShdrCount = Obj.sections().size() + 1; // Includes null shdr.
1571+
return Obj.SHOffset + ShdrCount * sizeof(Elf_Shdr);
15641572
}
15651573

15661574
template <class ELFT> Error ELFWriter<ELFT>::write() {

llvm/tools/llvm-objcopy/ELF/Object.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,11 @@ template <class ELFT> class ELFWriter : public Writer {
226226

227227
public:
228228
virtual ~ELFWriter() {}
229-
bool WriteSectionHeaders = true;
229+
bool WriteSectionHeaders;
230230

231231
Error finalize() override;
232232
Error write() override;
233-
ELFWriter(Object &Obj, Buffer &Buf, bool WSH)
234-
: Writer(Obj, Buf), WriteSectionHeaders(WSH) {}
233+
ELFWriter(Object &Obj, Buffer &Buf, bool WSH);
235234
};
236235

237236
class BinaryWriter : public Writer {
@@ -810,6 +809,7 @@ class Object {
810809
uint32_t Version;
811810
uint32_t Flags;
812811

812+
bool HadShdrs = true;
813813
StringTableSection *SectionNames = nullptr;
814814
SymbolTableSection *SymbolTable = nullptr;
815815
SectionIndexSection *SectionIndexTable = nullptr;

0 commit comments

Comments
 (0)