mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-04 17:56:53 +00:00
[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
This commit is contained in:
parent
5c7951c24c
commit
8e38021f91
BIN
test/tools/llvm-objcopy/Inputs/dynamic.so
Executable file
BIN
test/tools/llvm-objcopy/Inputs/dynamic.so
Executable file
Binary file not shown.
BIN
test/tools/llvm-objcopy/Inputs/dynsym.so
Executable file
BIN
test/tools/llvm-objcopy/Inputs/dynsym.so
Executable file
Binary file not shown.
27
test/tools/llvm-objcopy/dynamic.test
Normal file
27
test/tools/llvm-objcopy/dynamic.test
Normal file
@ -0,0 +1,27 @@
|
||||
# RUN: llvm-objcopy %p/Inputs/dynamic.so %t
|
||||
# RUN: llvm-readobj -dynamic-table %t | FileCheck %s
|
||||
# RUN: llvm-readobj -sections %t | FileCheck -check-prefix=LINK %s
|
||||
|
||||
#CHECK: DynamicSection [
|
||||
#CHECK-NEXT: Tag Type Name/Value
|
||||
#CHECK-NEXT: 0x0000000000000006 SYMTAB 0x1C8
|
||||
#CHECK-NEXT: 0x000000000000000B SYMENT 24
|
||||
#CHECK-NEXT: 0x0000000000000005 STRTAB 0x210
|
||||
#CHECK-NEXT: 0x000000000000000A STRSZ 5
|
||||
#CHECK-NEXT: 0x0000000000000004 HASH 0x1F8
|
||||
#CHECK-NEXT: 0x0000000000000000 NULL 0x0
|
||||
#CHECK-NEXT:]
|
||||
|
||||
#LINK: Index: 3
|
||||
#LINK-NEXT: Name: .dynstr
|
||||
|
||||
#LINK: Name: .dynamic
|
||||
#LINK-NEXT: Type: SHT_DYNAMIC
|
||||
#LINK-NEXT: Flags [
|
||||
#LINK-NEXT: SHF_ALLOC
|
||||
#LINK-NEXT: SHF_WRITE
|
||||
#LINK-NEXT: ]
|
||||
#LINK-NEXT: Address:
|
||||
#LINK-NEXT: Offset:
|
||||
#LINK-NEXT: Size:
|
||||
#LINK-NEXT: Link: 3
|
32
test/tools/llvm-objcopy/dynstr.test
Normal file
32
test/tools/llvm-objcopy/dynstr.test
Normal file
@ -0,0 +1,32 @@
|
||||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy %t %t2
|
||||
# RUN: llvm-readobj -sections -section-data %t2 | FileCheck %s
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .dynstr
|
||||
Type: SHT_STRTAB
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x1000
|
||||
Content: "002EDEADBEEF002EBAADF00D00"
|
||||
|
||||
#CHECK: Name: .dynstr
|
||||
#CHECK-NEXT: Type: SHT_STRTAB
|
||||
#CHECK-NEXT: Flags [
|
||||
#CHECK-NEXT: SHF_ALLOC
|
||||
#CHECK-NEXT: ]
|
||||
#CHECK-NEXT: Address: 0x1000
|
||||
#CHECK-NEXT: Offset:
|
||||
#CHECK-NEXT: Size: 13
|
||||
#CHECK-NEXT: Link:
|
||||
#CHECK-NEXT: Info:
|
||||
#CHECK-NEXT: AddressAlignment:
|
||||
#CHECK-NEXT: EntrySize:
|
||||
#CHECK-NEXT: SectionData (
|
||||
#CHECK-NEXT: 0000: 002EDEAD BEEF002E BAADF00D 00
|
||||
#CHECK-NEXT: )
|
64
test/tools/llvm-objcopy/dynsym.test
Normal file
64
test/tools/llvm-objcopy/dynsym.test
Normal file
@ -0,0 +1,64 @@
|
||||
# RUN: llvm-objcopy %p/Inputs/dynsym.so %t
|
||||
# RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
|
||||
# RUN: llvm-readobj -sections %t | FileCheck -check-prefix=LINK %s
|
||||
|
||||
#LINK: Name: .dynsym
|
||||
#LINK-NEXT: Type: SHT_DYNSYM
|
||||
#LINK-NEXT: Flags [
|
||||
#LINK-NEXT: SHF_ALLOC
|
||||
#LINK-NEXT: ]
|
||||
#LINK-NEXT: Address:
|
||||
#LINK-NEXT: Offset:
|
||||
#LINK-NEXT: Size:
|
||||
#LINK-NEXT: Link: 3
|
||||
|
||||
#LINK: Index: 3
|
||||
#LINK-NEXT: Name: .dynstr
|
||||
|
||||
#CHECK: DynamicSymbols [
|
||||
#CHECK-NEXT: Symbol {
|
||||
#CHECK-NEXT: Name: @ (0)
|
||||
#CHECK-NEXT: Value: 0x0
|
||||
#CHECK-NEXT: Size: 0
|
||||
#CHECK-NEXT: Binding: Local
|
||||
#CHECK-NEXT: Type: None (0x0)
|
||||
#CHECK-NEXT: Other: 0
|
||||
#CHECK-NEXT: Section: Undefined (0x0)
|
||||
#CHECK-NEXT: }
|
||||
#CHECK-NEXT: Symbol {
|
||||
#CHECK-NEXT: Name: bang@ (1)
|
||||
#CHECK-NEXT: Value: 0x4000
|
||||
#CHECK-NEXT: Size: 8
|
||||
#CHECK-NEXT: Binding: Global (0x1)
|
||||
#CHECK-NEXT: Type: Object (0x1)
|
||||
#CHECK-NEXT: Other: 0
|
||||
#CHECK-NEXT: Section: .bss (0x7)
|
||||
#CHECK-NEXT: }
|
||||
#CHECK-NEXT: Symbol {
|
||||
#CHECK-NEXT: Name: bar@ (6)
|
||||
#CHECK-NEXT: Value: 0x1001
|
||||
#CHECK-NEXT: Size: 0
|
||||
#CHECK-NEXT: Binding: Global (0x1)
|
||||
#CHECK-NEXT: Type: Function (0x2)
|
||||
#CHECK-NEXT: Other: 0
|
||||
#CHECK-NEXT: Section: .text (0x4)
|
||||
#CHECK-NEXT: }
|
||||
#CHECK-NEXT: Symbol {
|
||||
#CHECK-NEXT: Name: baz@ (10)
|
||||
#CHECK-NEXT: Value: 0x2000
|
||||
#CHECK-NEXT: Size: 0
|
||||
#CHECK-NEXT: Binding: Global (0x1)
|
||||
#CHECK-NEXT: Type: Object (0x1)
|
||||
#CHECK-NEXT: Other: 0
|
||||
#CHECK-NEXT: Section: .data (0x5)
|
||||
#CHECK-NEXT: }
|
||||
#CHECK-NEXT: Symbol {
|
||||
#CHECK-NEXT: Name: foo@ (14)
|
||||
#CHECK-NEXT: Value: 0x1000
|
||||
#CHECK-NEXT: Size: 0
|
||||
#CHECK-NEXT: Binding: Global (0x1)
|
||||
#CHECK-NEXT: Type: Function (0x2)
|
||||
#CHECK-NEXT: Other: 0
|
||||
#CHECK-NEXT: Section: .text (0x4)
|
||||
#CHECK-NEXT: }
|
||||
#CHECK-NEXT:]
|
@ -228,6 +228,12 @@ void RelocationSection<ELFT>::writeSection(llvm::FileOutputBuffer &Out) const {
|
||||
writeRel(reinterpret_cast<Elf_Rela *>(Buf));
|
||||
}
|
||||
|
||||
bool SectionWithStrTab::classof(const SectionBase *S) {
|
||||
return isa<DynamicSymbolTableSection>(S) || isa<DynamicSection>(S);
|
||||
}
|
||||
|
||||
void SectionWithStrTab::finalize() { this->Link = StrTab->Index; }
|
||||
|
||||
// Returns true IFF a section is wholly inside the range of a segment
|
||||
static bool sectionWithinSegment(const SectionBase &Section,
|
||||
const Segment &Segment) {
|
||||
@ -308,16 +314,12 @@ void Object<ELFT>::initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile,
|
||||
SymbolTableSection *SymTab) {
|
||||
|
||||
SymTab->Size = 0;
|
||||
if (SymbolTable->Link - 1 >= Sections.size())
|
||||
error("Symbol table has link index of " + Twine(SymbolTable->Link) +
|
||||
" which is not a valid index");
|
||||
|
||||
if (auto StrTab =
|
||||
dyn_cast<StringTableSection>(Sections[SymbolTable->Link - 1].get()))
|
||||
SymTab->setStrTab(StrTab);
|
||||
else
|
||||
error("Symbol table has link index of " + Twine(SymbolTable->Link) +
|
||||
"which is not a string table");
|
||||
SymTab->setStrTab(getSectionOfType<StringTableSection>(
|
||||
SymbolTable->Link,
|
||||
"Symbol table has link index of " + Twine(SymTab->Link) +
|
||||
" which is not a valid index",
|
||||
"Symbol table has link index of " + Twine(SymTab->Link) +
|
||||
" which is not a string table"));
|
||||
|
||||
const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index));
|
||||
StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr));
|
||||
@ -325,6 +327,7 @@ void Object<ELFT>::initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile,
|
||||
for (const auto &Sym : unwrapOrError(ElfFile.symbols(&Shdr))) {
|
||||
SectionBase *DefSection = nullptr;
|
||||
StringRef Name = unwrapOrError(Sym.getName(StrTabData));
|
||||
|
||||
if (Sym.st_shndx >= SHN_LORESERVE) {
|
||||
if (!isValidReservedSectionIndex(Sym.st_shndx, Machine)) {
|
||||
error(
|
||||
@ -333,12 +336,12 @@ void Object<ELFT>::initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile,
|
||||
Twine(Sym.st_shndx));
|
||||
}
|
||||
} else if (Sym.st_shndx != SHN_UNDEF) {
|
||||
if (Sym.st_shndx >= Sections.size())
|
||||
error("Symbol '" + Name +
|
||||
"' is defined in invalid section with index " +
|
||||
DefSection = getSection(
|
||||
Sym.st_shndx,
|
||||
"Symbol '" + Name + "' is defined in invalid section with index " +
|
||||
Twine(Sym.st_shndx));
|
||||
DefSection = Sections[Sym.st_shndx - 1].get();
|
||||
}
|
||||
|
||||
SymTab->addSymbol(Name, Sym.getBinding(), Sym.getType(), DefSection,
|
||||
Sym.getValue(), Sym.st_shndx, Sym.st_size);
|
||||
}
|
||||
@ -365,6 +368,22 @@ void initRelocations(RelocationSection<ELFT> *Relocs,
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
SectionBase *Object<ELFT>::getSection(uint16_t Index, Twine ErrMsg) {
|
||||
if (Index == SHN_UNDEF || Index > Sections.size())
|
||||
error(ErrMsg);
|
||||
return Sections[Index - 1].get();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
template <class T>
|
||||
T *Object<ELFT>::getSectionOfType(uint16_t Index, Twine IndexErrMsg,
|
||||
Twine TypeErrMsg) {
|
||||
if (T *TSec = llvm::dyn_cast<T>(getSection(Index, IndexErrMsg)))
|
||||
return TSec;
|
||||
error(TypeErrMsg);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
std::unique_ptr<SectionBase>
|
||||
Object<ELFT>::makeSection(const llvm::object::ELFFile<ELFT> &ElfFile,
|
||||
@ -375,7 +394,26 @@ Object<ELFT>::makeSection(const llvm::object::ELFFile<ELFT> &ElfFile,
|
||||
case SHT_RELA:
|
||||
return llvm::make_unique<RelocationSection<ELFT>>();
|
||||
case SHT_STRTAB:
|
||||
// If a string table is allocated we don't want to mess with it. That would
|
||||
// mean altering the memory image. There are no special link types or
|
||||
// anything so we can just use a Section.
|
||||
if (Shdr.sh_flags & SHF_ALLOC) {
|
||||
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
|
||||
return llvm::make_unique<Section>(Data);
|
||||
}
|
||||
return llvm::make_unique<StringTableSection>();
|
||||
case SHT_HASH:
|
||||
case SHT_GNU_HASH:
|
||||
// Hash tables should refer to SHT_DYNSYM which we're not going to change.
|
||||
// Because of this we don't need to mess with the hash tables either.
|
||||
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
|
||||
return llvm::make_unique<Section>(Data);
|
||||
case SHT_DYNSYM:
|
||||
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
|
||||
return llvm::make_unique<DynamicSymbolTableSection>(Data);
|
||||
case SHT_DYNAMIC:
|
||||
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
|
||||
return llvm::make_unique<DynamicSection>(Data);
|
||||
case SHT_SYMTAB: {
|
||||
auto SymTab = llvm::make_unique<SymbolTableSectionImpl<ELFT>>();
|
||||
SymbolTable = SymTab.get();
|
||||
@ -423,28 +461,35 @@ void Object<ELFT>::readSectionHeaders(const ELFFile<ELFT> &ElfFile) {
|
||||
// relocation sections.
|
||||
for (auto &Section : Sections) {
|
||||
if (auto RelSec = dyn_cast<RelocationSection<ELFT>>(Section.get())) {
|
||||
if (RelSec->Link - 1 >= Sections.size() || RelSec->Link == 0) {
|
||||
error("Link field value " + Twine(RelSec->Link) + " in section " +
|
||||
RelSec->Name + " is invalid");
|
||||
}
|
||||
if (RelSec->Info - 1 >= Sections.size() || RelSec->Info == 0) {
|
||||
error("Info field value " + Twine(RelSec->Link) + " in section " +
|
||||
RelSec->Name + " is invalid");
|
||||
}
|
||||
auto SymTab =
|
||||
dyn_cast<SymbolTableSection>(Sections[RelSec->Link - 1].get());
|
||||
if (SymTab == nullptr) {
|
||||
error("Link field of relocation section " + RelSec->Name +
|
||||
" is not a symbol table");
|
||||
}
|
||||
|
||||
auto SymTab = getSectionOfType<SymbolTableSection>(
|
||||
RelSec->Link,
|
||||
"Link field value " + Twine(RelSec->Link) + " in section " +
|
||||
RelSec->Name + " is invalid",
|
||||
"Link field value " + Twine(RelSec->Link) + " in section " +
|
||||
RelSec->Name + " is not a symbol table");
|
||||
RelSec->setSymTab(SymTab);
|
||||
RelSec->setSection(Sections[RelSec->Info - 1].get());
|
||||
|
||||
RelSec->setSection(getSection(RelSec->Info,
|
||||
"Info field value " + Twine(RelSec->Link) +
|
||||
" in section " + RelSec->Name +
|
||||
" is invalid"));
|
||||
|
||||
auto Shdr = unwrapOrError(ElfFile.sections()).begin() + RelSec->Index;
|
||||
if (RelSec->Type == SHT_REL)
|
||||
initRelocations(RelSec, SymTab, unwrapOrError(ElfFile.rels(Shdr)));
|
||||
else
|
||||
initRelocations(RelSec, SymTab, unwrapOrError(ElfFile.relas(Shdr)));
|
||||
}
|
||||
|
||||
if (auto Sec = dyn_cast<SectionWithStrTab>(Section.get())) {
|
||||
Sec->setStrTab(getSectionOfType<StringTableSection>(
|
||||
Sec->Link,
|
||||
"Link field value " + Twine(Sec->Link) + " in section " + Sec->Name +
|
||||
" is invalid",
|
||||
"Link field value " + Twine(Sec->Link) + " in section " + Sec->Name +
|
||||
" is not a string table"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -462,8 +507,12 @@ template <class ELFT> Object<ELFT>::Object(const ELFObjectFile<ELFT> &Obj) {
|
||||
readSectionHeaders(ElfFile);
|
||||
readProgramHeaders(ElfFile);
|
||||
|
||||
SectionNames =
|
||||
dyn_cast<StringTableSection>(Sections[Ehdr.e_shstrndx - 1].get());
|
||||
SectionNames = getSectionOfType<StringTableSection>(
|
||||
Ehdr.e_shstrndx,
|
||||
"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");
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -194,6 +194,34 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class SectionWithStrTab : public Section {
|
||||
private:
|
||||
StringTableSection *StrTab;
|
||||
|
||||
public:
|
||||
SectionWithStrTab(llvm::ArrayRef<uint8_t> Data) : Section(Data) {}
|
||||
void setStrTab(StringTableSection *StringTable) { StrTab = StringTable; }
|
||||
void finalize() override;
|
||||
static bool classof(const SectionBase *S);
|
||||
};
|
||||
|
||||
class DynamicSymbolTableSection : public SectionWithStrTab {
|
||||
public:
|
||||
DynamicSymbolTableSection(llvm::ArrayRef<uint8_t> Data)
|
||||
: SectionWithStrTab(Data) {}
|
||||
static bool classof(const SectionBase *S) {
|
||||
return S->Type == llvm::ELF::SHT_DYNSYM;
|
||||
}
|
||||
};
|
||||
|
||||
class DynamicSection : public SectionWithStrTab {
|
||||
public:
|
||||
DynamicSection(llvm::ArrayRef<uint8_t> Data) : SectionWithStrTab(Data) {}
|
||||
static bool classof(const SectionBase *S) {
|
||||
return S->Type == llvm::ELF::SHT_DYNAMIC;
|
||||
}
|
||||
};
|
||||
|
||||
template <class ELFT> class Object {
|
||||
private:
|
||||
typedef std::unique_ptr<SectionBase> SecPtr;
|
||||
@ -210,6 +238,12 @@ private:
|
||||
void readProgramHeaders(const llvm::object::ELFFile<ELFT> &ElfFile);
|
||||
void readSectionHeaders(const llvm::object::ELFFile<ELFT> &ElfFile);
|
||||
|
||||
SectionBase *getSection(uint16_t Index, llvm::Twine ErrMsg);
|
||||
|
||||
template <class T>
|
||||
T *getSectionOfType(uint16_t Index, llvm::Twine IndexErrMsg,
|
||||
llvm::Twine TypeErrMsg);
|
||||
|
||||
protected:
|
||||
StringTableSection *SectionNames;
|
||||
SymbolTableSection *SymbolTable;
|
||||
|
Loading…
Reference in New Issue
Block a user