Skip to content

Commit f20c3f4

Browse files
committed
[llvm-objcopy] Add support for .dynamic, .dynsym, and .dynstr
This change adds support for sections involved in dynamic loading such as SHT_DYNAMIC, SHT_DYNSYM, and allocated string tables. The two added binaries used for tests can be downloaded [[ https://drive.google.com/file/d/0B3gtIAmiMwZXOXE3T0RobFg4ZTg/view?usp=sharing | here ]] and [[ https://drive.google.com/file/d/0B3gtIAmiMwZXTFJSQUJZMGxNSXc/view?usp=sharing | here ]] Differential Revision: https://reviews.llvm.org/D36560 llvm-svn: 313663
1 parent 610e03a commit f20c3f4

File tree

7 files changed

+237
-31
lines changed

7 files changed

+237
-31
lines changed
8.9 KB
Binary file not shown.
13.1 KB
Binary file not shown.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# RUN: llvm-objcopy %p/Inputs/dynamic.so %t
2+
# RUN: llvm-readobj -dynamic-table %t | FileCheck %s
3+
# RUN: llvm-readobj -sections %t | FileCheck -check-prefix=LINK %s
4+
5+
#CHECK: DynamicSection [
6+
#CHECK-NEXT: Tag Type Name/Value
7+
#CHECK-NEXT: 0x0000000000000006 SYMTAB 0x1C8
8+
#CHECK-NEXT: 0x000000000000000B SYMENT 24
9+
#CHECK-NEXT: 0x0000000000000005 STRTAB 0x210
10+
#CHECK-NEXT: 0x000000000000000A STRSZ 5
11+
#CHECK-NEXT: 0x0000000000000004 HASH 0x1F8
12+
#CHECK-NEXT: 0x0000000000000000 NULL 0x0
13+
#CHECK-NEXT:]
14+
15+
#LINK: Index: 3
16+
#LINK-NEXT: Name: .dynstr
17+
18+
#LINK: Name: .dynamic
19+
#LINK-NEXT: Type: SHT_DYNAMIC
20+
#LINK-NEXT: Flags [
21+
#LINK-NEXT: SHF_ALLOC
22+
#LINK-NEXT: SHF_WRITE
23+
#LINK-NEXT: ]
24+
#LINK-NEXT: Address:
25+
#LINK-NEXT: Offset:
26+
#LINK-NEXT: Size:
27+
#LINK-NEXT: Link: 3
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# RUN: yaml2obj %s > %t
2+
# RUN: llvm-objcopy %t %t2
3+
# RUN: llvm-readobj -sections -section-data %t2 | FileCheck %s
4+
5+
!ELF
6+
FileHeader:
7+
Class: ELFCLASS64
8+
Data: ELFDATA2LSB
9+
Type: ET_EXEC
10+
Machine: EM_X86_64
11+
Sections:
12+
- Name: .dynstr
13+
Type: SHT_STRTAB
14+
Flags: [ SHF_ALLOC ]
15+
Address: 0x1000
16+
Content: "002EDEADBEEF002EBAADF00D00"
17+
18+
#CHECK: Name: .dynstr
19+
#CHECK-NEXT: Type: SHT_STRTAB
20+
#CHECK-NEXT: Flags [
21+
#CHECK-NEXT: SHF_ALLOC
22+
#CHECK-NEXT: ]
23+
#CHECK-NEXT: Address: 0x1000
24+
#CHECK-NEXT: Offset:
25+
#CHECK-NEXT: Size: 13
26+
#CHECK-NEXT: Link:
27+
#CHECK-NEXT: Info:
28+
#CHECK-NEXT: AddressAlignment:
29+
#CHECK-NEXT: EntrySize:
30+
#CHECK-NEXT: SectionData (
31+
#CHECK-NEXT: 0000: 002EDEAD BEEF002E BAADF00D 00
32+
#CHECK-NEXT: )
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# RUN: llvm-objcopy %p/Inputs/dynsym.so %t
2+
# RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
3+
# RUN: llvm-readobj -sections %t | FileCheck -check-prefix=LINK %s
4+
5+
#LINK: Name: .dynsym
6+
#LINK-NEXT: Type: SHT_DYNSYM
7+
#LINK-NEXT: Flags [
8+
#LINK-NEXT: SHF_ALLOC
9+
#LINK-NEXT: ]
10+
#LINK-NEXT: Address:
11+
#LINK-NEXT: Offset:
12+
#LINK-NEXT: Size:
13+
#LINK-NEXT: Link: 3
14+
15+
#LINK: Index: 3
16+
#LINK-NEXT: Name: .dynstr
17+
18+
#CHECK: DynamicSymbols [
19+
#CHECK-NEXT: Symbol {
20+
#CHECK-NEXT: Name: @ (0)
21+
#CHECK-NEXT: Value: 0x0
22+
#CHECK-NEXT: Size: 0
23+
#CHECK-NEXT: Binding: Local
24+
#CHECK-NEXT: Type: None (0x0)
25+
#CHECK-NEXT: Other: 0
26+
#CHECK-NEXT: Section: Undefined (0x0)
27+
#CHECK-NEXT: }
28+
#CHECK-NEXT: Symbol {
29+
#CHECK-NEXT: Name: bang@ (1)
30+
#CHECK-NEXT: Value: 0x4000
31+
#CHECK-NEXT: Size: 8
32+
#CHECK-NEXT: Binding: Global (0x1)
33+
#CHECK-NEXT: Type: Object (0x1)
34+
#CHECK-NEXT: Other: 0
35+
#CHECK-NEXT: Section: .bss (0x7)
36+
#CHECK-NEXT: }
37+
#CHECK-NEXT: Symbol {
38+
#CHECK-NEXT: Name: bar@ (6)
39+
#CHECK-NEXT: Value: 0x1001
40+
#CHECK-NEXT: Size: 0
41+
#CHECK-NEXT: Binding: Global (0x1)
42+
#CHECK-NEXT: Type: Function (0x2)
43+
#CHECK-NEXT: Other: 0
44+
#CHECK-NEXT: Section: .text (0x4)
45+
#CHECK-NEXT: }
46+
#CHECK-NEXT: Symbol {
47+
#CHECK-NEXT: Name: baz@ (10)
48+
#CHECK-NEXT: Value: 0x2000
49+
#CHECK-NEXT: Size: 0
50+
#CHECK-NEXT: Binding: Global (0x1)
51+
#CHECK-NEXT: Type: Object (0x1)
52+
#CHECK-NEXT: Other: 0
53+
#CHECK-NEXT: Section: .data (0x5)
54+
#CHECK-NEXT: }
55+
#CHECK-NEXT: Symbol {
56+
#CHECK-NEXT: Name: foo@ (14)
57+
#CHECK-NEXT: Value: 0x1000
58+
#CHECK-NEXT: Size: 0
59+
#CHECK-NEXT: Binding: Global (0x1)
60+
#CHECK-NEXT: Type: Function (0x2)
61+
#CHECK-NEXT: Other: 0
62+
#CHECK-NEXT: Section: .text (0x4)
63+
#CHECK-NEXT: }
64+
#CHECK-NEXT:]

llvm/tools/llvm-objcopy/Object.cpp

Lines changed: 80 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,12 @@ void RelocationSection<ELFT>::writeSection(llvm::FileOutputBuffer &Out) const {
228228
writeRel(reinterpret_cast<Elf_Rela *>(Buf));
229229
}
230230

231+
bool SectionWithStrTab::classof(const SectionBase *S) {
232+
return isa<DynamicSymbolTableSection>(S) || isa<DynamicSection>(S);
233+
}
234+
235+
void SectionWithStrTab::finalize() { this->Link = StrTab->Index; }
236+
231237
// Returns true IFF a section is wholly inside the range of a segment
232238
static bool sectionWithinSegment(const SectionBase &Section,
233239
const Segment &Segment) {
@@ -308,23 +314,20 @@ void Object<ELFT>::initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile,
308314
SymbolTableSection *SymTab) {
309315

310316
SymTab->Size = 0;
311-
if (SymbolTable->Link - 1 >= Sections.size())
312-
error("Symbol table has link index of " + Twine(SymbolTable->Link) +
313-
" which is not a valid index");
314-
315-
if (auto StrTab =
316-
dyn_cast<StringTableSection>(Sections[SymbolTable->Link - 1].get()))
317-
SymTab->setStrTab(StrTab);
318-
else
319-
error("Symbol table has link index of " + Twine(SymbolTable->Link) +
320-
"which is not a string table");
317+
SymTab->setStrTab(getSectionOfType<StringTableSection>(
318+
SymbolTable->Link,
319+
"Symbol table has link index of " + Twine(SymTab->Link) +
320+
" which is not a valid index",
321+
"Symbol table has link index of " + Twine(SymTab->Link) +
322+
" which is not a string table"));
321323

322324
const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index));
323325
StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr));
324326

325327
for (const auto &Sym : unwrapOrError(ElfFile.symbols(&Shdr))) {
326328
SectionBase *DefSection = nullptr;
327329
StringRef Name = unwrapOrError(Sym.getName(StrTabData));
330+
328331
if (Sym.st_shndx >= SHN_LORESERVE) {
329332
if (!isValidReservedSectionIndex(Sym.st_shndx, Machine)) {
330333
error(
@@ -333,12 +336,12 @@ void Object<ELFT>::initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile,
333336
Twine(Sym.st_shndx));
334337
}
335338
} else if (Sym.st_shndx != SHN_UNDEF) {
336-
if (Sym.st_shndx >= Sections.size())
337-
error("Symbol '" + Name +
338-
"' is defined in invalid section with index " +
339+
DefSection = getSection(
340+
Sym.st_shndx,
341+
"Symbol '" + Name + "' is defined in invalid section with index " +
339342
Twine(Sym.st_shndx));
340-
DefSection = Sections[Sym.st_shndx - 1].get();
341343
}
344+
342345
SymTab->addSymbol(Name, Sym.getBinding(), Sym.getType(), DefSection,
343346
Sym.getValue(), Sym.st_shndx, Sym.st_size);
344347
}
@@ -365,6 +368,22 @@ void initRelocations(RelocationSection<ELFT> *Relocs,
365368
}
366369
}
367370

371+
template <class ELFT>
372+
SectionBase *Object<ELFT>::getSection(uint16_t Index, Twine ErrMsg) {
373+
if (Index == SHN_UNDEF || Index > Sections.size())
374+
error(ErrMsg);
375+
return Sections[Index - 1].get();
376+
}
377+
378+
template <class ELFT>
379+
template <class T>
380+
T *Object<ELFT>::getSectionOfType(uint16_t Index, Twine IndexErrMsg,
381+
Twine TypeErrMsg) {
382+
if (T *TSec = llvm::dyn_cast<T>(getSection(Index, IndexErrMsg)))
383+
return TSec;
384+
error(TypeErrMsg);
385+
}
386+
368387
template <class ELFT>
369388
std::unique_ptr<SectionBase>
370389
Object<ELFT>::makeSection(const llvm::object::ELFFile<ELFT> &ElfFile,
@@ -375,7 +394,26 @@ Object<ELFT>::makeSection(const llvm::object::ELFFile<ELFT> &ElfFile,
375394
case SHT_RELA:
376395
return llvm::make_unique<RelocationSection<ELFT>>();
377396
case SHT_STRTAB:
397+
// If a string table is allocated we don't want to mess with it. That would
398+
// mean altering the memory image. There are no special link types or
399+
// anything so we can just use a Section.
400+
if (Shdr.sh_flags & SHF_ALLOC) {
401+
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
402+
return llvm::make_unique<Section>(Data);
403+
}
378404
return llvm::make_unique<StringTableSection>();
405+
case SHT_HASH:
406+
case SHT_GNU_HASH:
407+
// Hash tables should refer to SHT_DYNSYM which we're not going to change.
408+
// Because of this we don't need to mess with the hash tables either.
409+
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
410+
return llvm::make_unique<Section>(Data);
411+
case SHT_DYNSYM:
412+
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
413+
return llvm::make_unique<DynamicSymbolTableSection>(Data);
414+
case SHT_DYNAMIC:
415+
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
416+
return llvm::make_unique<DynamicSection>(Data);
379417
case SHT_SYMTAB: {
380418
auto SymTab = llvm::make_unique<SymbolTableSectionImpl<ELFT>>();
381419
SymbolTable = SymTab.get();
@@ -423,28 +461,35 @@ void Object<ELFT>::readSectionHeaders(const ELFFile<ELFT> &ElfFile) {
423461
// relocation sections.
424462
for (auto &Section : Sections) {
425463
if (auto RelSec = dyn_cast<RelocationSection<ELFT>>(Section.get())) {
426-
if (RelSec->Link - 1 >= Sections.size() || RelSec->Link == 0) {
427-
error("Link field value " + Twine(RelSec->Link) + " in section " +
428-
RelSec->Name + " is invalid");
429-
}
430-
if (RelSec->Info - 1 >= Sections.size() || RelSec->Info == 0) {
431-
error("Info field value " + Twine(RelSec->Link) + " in section " +
432-
RelSec->Name + " is invalid");
433-
}
434-
auto SymTab =
435-
dyn_cast<SymbolTableSection>(Sections[RelSec->Link - 1].get());
436-
if (SymTab == nullptr) {
437-
error("Link field of relocation section " + RelSec->Name +
438-
" is not a symbol table");
439-
}
464+
465+
auto SymTab = getSectionOfType<SymbolTableSection>(
466+
RelSec->Link,
467+
"Link field value " + Twine(RelSec->Link) + " in section " +
468+
RelSec->Name + " is invalid",
469+
"Link field value " + Twine(RelSec->Link) + " in section " +
470+
RelSec->Name + " is not a symbol table");
440471
RelSec->setSymTab(SymTab);
441-
RelSec->setSection(Sections[RelSec->Info - 1].get());
472+
473+
RelSec->setSection(getSection(RelSec->Info,
474+
"Info field value " + Twine(RelSec->Link) +
475+
" in section " + RelSec->Name +
476+
" is invalid"));
477+
442478
auto Shdr = unwrapOrError(ElfFile.sections()).begin() + RelSec->Index;
443479
if (RelSec->Type == SHT_REL)
444480
initRelocations(RelSec, SymTab, unwrapOrError(ElfFile.rels(Shdr)));
445481
else
446482
initRelocations(RelSec, SymTab, unwrapOrError(ElfFile.relas(Shdr)));
447483
}
484+
485+
if (auto Sec = dyn_cast<SectionWithStrTab>(Section.get())) {
486+
Sec->setStrTab(getSectionOfType<StringTableSection>(
487+
Sec->Link,
488+
"Link field value " + Twine(Sec->Link) + " in section " + Sec->Name +
489+
" is invalid",
490+
"Link field value " + Twine(Sec->Link) + " in section " + Sec->Name +
491+
" is not a string table"));
492+
}
448493
}
449494
}
450495

@@ -462,8 +507,12 @@ template <class ELFT> Object<ELFT>::Object(const ELFObjectFile<ELFT> &Obj) {
462507
readSectionHeaders(ElfFile);
463508
readProgramHeaders(ElfFile);
464509

465-
SectionNames =
466-
dyn_cast<StringTableSection>(Sections[Ehdr.e_shstrndx - 1].get());
510+
SectionNames = getSectionOfType<StringTableSection>(
511+
Ehdr.e_shstrndx,
512+
"e_shstrndx field value " + Twine(Ehdr.e_shstrndx) + " in elf header " +
513+
" is invalid",
514+
"e_shstrndx field value " + Twine(Ehdr.e_shstrndx) + " in elf header " +
515+
" is not a string table");
467516
}
468517

469518
template <class ELFT>

llvm/tools/llvm-objcopy/Object.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,34 @@ template <class ELFT> class RelocationSection : public SectionBase {
194194
}
195195
};
196196

197+
class SectionWithStrTab : public Section {
198+
private:
199+
StringTableSection *StrTab;
200+
201+
public:
202+
SectionWithStrTab(llvm::ArrayRef<uint8_t> Data) : Section(Data) {}
203+
void setStrTab(StringTableSection *StringTable) { StrTab = StringTable; }
204+
void finalize() override;
205+
static bool classof(const SectionBase *S);
206+
};
207+
208+
class DynamicSymbolTableSection : public SectionWithStrTab {
209+
public:
210+
DynamicSymbolTableSection(llvm::ArrayRef<uint8_t> Data)
211+
: SectionWithStrTab(Data) {}
212+
static bool classof(const SectionBase *S) {
213+
return S->Type == llvm::ELF::SHT_DYNSYM;
214+
}
215+
};
216+
217+
class DynamicSection : public SectionWithStrTab {
218+
public:
219+
DynamicSection(llvm::ArrayRef<uint8_t> Data) : SectionWithStrTab(Data) {}
220+
static bool classof(const SectionBase *S) {
221+
return S->Type == llvm::ELF::SHT_DYNAMIC;
222+
}
223+
};
224+
197225
template <class ELFT> class Object {
198226
private:
199227
typedef std::unique_ptr<SectionBase> SecPtr;
@@ -210,6 +238,12 @@ template <class ELFT> class Object {
210238
void readProgramHeaders(const llvm::object::ELFFile<ELFT> &ElfFile);
211239
void readSectionHeaders(const llvm::object::ELFFile<ELFT> &ElfFile);
212240

241+
SectionBase *getSection(uint16_t Index, llvm::Twine ErrMsg);
242+
243+
template <class T>
244+
T *getSectionOfType(uint16_t Index, llvm::Twine IndexErrMsg,
245+
llvm::Twine TypeErrMsg);
246+
213247
protected:
214248
StringTableSection *SectionNames;
215249
SymbolTableSection *SymbolTable;

0 commit comments

Comments
 (0)