Index: test/tools/llvm-objcopy/dynamic-relocations.test =================================================================== --- /dev/null +++ test/tools/llvm-objcopy/dynamic-relocations.test @@ -0,0 +1,19 @@ +# RUN: llvm-objcopy %p/Inputs/dynrel.elf %t +# RUN: llvm-readobj -sections -section-data %t | FileCheck %s + +#CHECK: Name: .rela.plt +#CHECK-NEXT: Type: SHT_RELA +#CHECK-NEXT: Flags [ +#CHECK-NEXT: SHF_ALLOC +#CHECK-NEXT: ] +#CHECK-NEXT: Address: +#CHECK-NEXT: Offset: +#CHECK-NEXT: Size: 24 +#CHECK-NEXT: Link: +#CHECK-NEXT: Info: +#CHECK-NEXT: AddressAlignment: 8 +#CHECK-NEXT: EntrySize: 24 +#CHECK-NEXT: SectionData ( +#CHECK-NEXT: 0000: 18202000 00000000 07000000 01000000 |. .............| +#CHECK-NEXT: 0010: 00000000 00000000 |........| +#CHECK-NEXT: ) Index: tools/llvm-objcopy/Object.h =================================================================== --- tools/llvm-objcopy/Object.h +++ tools/llvm-objcopy/Object.h @@ -190,6 +190,8 @@ void finalize() override; void writeSection(llvm::FileOutputBuffer &Out) const override; static bool classof(const SectionBase *S) { + if (S->Flags & llvm::ELF::SHF_ALLOC) + return false; return S->Type == llvm::ELF::SHT_REL || S->Type == llvm::ELF::SHT_RELA; } }; @@ -221,6 +223,24 @@ } }; +class DynamicRelocationSection : public Section { +private: + llvm::ArrayRef Contents; + DynamicSymbolTableSection *Symbols; + SectionBase *SecToApplyRel; + +public: + DynamicRelocationSection(llvm::ArrayRef Data) : Section(Data) {} + void setSymTab(DynamicSymbolTableSection *SymTab) { Symbols = SymTab; } + void setSection(SectionBase *Sec) { SecToApplyRel = Sec; } + void finalize() override; + static bool classof(const SectionBase *S) { + if (!(S->Flags & llvm::ELF::SHF_ALLOC)) + return false; + return S->Type == llvm::ELF::SHT_REL || S->Type == llvm::ELF::SHT_RELA; + } +}; + template class Object { private: typedef std::unique_ptr SecPtr; Index: tools/llvm-objcopy/Object.cpp =================================================================== --- tools/llvm-objcopy/Object.cpp +++ tools/llvm-objcopy/Object.cpp @@ -195,11 +195,6 @@ } } -template void RelocationSection::finalize() { - this->Link = Symbols->Index; - this->Info = SecToApplyRel->Index; -} - template void setAddend(Elf_Rel_Impl &Rel, uint64_t Addend) {} @@ -228,6 +223,18 @@ writeRel(reinterpret_cast(Buf)); } +template void RelocationSection::finalize() { + this->Link = Symbols->Index; + if (SecToApplyRel != nullptr) + this->Info = SecToApplyRel->Index; +} + +void DynamicRelocationSection::finalize() { + this->Link = Symbols->Index; + if (SecToApplyRel != nullptr) + this->Info = SecToApplyRel->Index; +} + bool SectionWithStrTab::classof(const SectionBase *S) { return isa(S) || isa(S); } @@ -395,6 +402,10 @@ switch (Shdr.sh_type) { case SHT_REL: case SHT_RELA: + if (Shdr.sh_flags & SHF_ALLOC) { + Data = unwrapOrError(ElfFile.getSectionContents(&Shdr)); + return llvm::make_unique(Data); + } return llvm::make_unique>(); case SHT_STRTAB: // If a string table is allocated we don't want to mess with it. That would @@ -463,6 +474,23 @@ // relocations that reference symbols and set the link and info fields for // relocation sections. for (auto &Section : Sections) { + // TODO: I don't like how this is growing. I think a kind of visitor pattern + // like solution could be setup to make this better. + if (auto DynRelSec = dyn_cast(Section.get())) { + auto SymTab = getSectionCast( + DynRelSec->Link, + "Link field value " + Twine(DynRelSec->Link) + " in section " + + DynRelSec->Name + " is invalid", + "Link field value " + Twine(DynRelSec->Link) + " in section " + + DynRelSec->Name + " is not a dynamic symbol table"); + DynRelSec->setSymTab(SymTab); + + if (DynRelSec->Info != SHN_UNDEF) + DynRelSec->setSection( + getSection(DynRelSec->Info, + "Info field value " + Twine(DynRelSec->Info) + + " in section " + DynRelSec->Name + " is invalid")); + } if (auto RelSec = dyn_cast>(Section.get())) { auto SymTab = getSectionCast( @@ -473,10 +501,11 @@ RelSec->Name + " is not a symbol table"); RelSec->setSymTab(SymTab); - RelSec->setSection(getSection(RelSec->Info, - "Info field value " + Twine(RelSec->Link) + - " in section " + RelSec->Name + - " is invalid")); + if (RelSec->Info != SHN_UNDEF) + RelSec->setSection(getSection(RelSec->Info, + "Info field value " + + Twine(RelSec->Info) + " in section " + + RelSec->Name + " is invalid")); auto Shdr = unwrapOrError(ElfFile.sections()).begin() + RelSec->Index; if (RelSec->Type == SHT_REL)