[PATCH] D111181: llvm-objcopy][ELF] Don't assume RELA sections are dynamic if they carry the SHF_ALLOC flag

Ard Biesheuvel via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 5 13:38:32 PDT 2021


ardb created this revision.
ardb added reviewers: jakehehrlich, nickdesaulniers.
Herald added subscribers: abrachet, emaste.
Herald added a reviewer: alexander-shaposhnikov.
Herald added a reviewer: rupprecht.
Herald added a reviewer: jhenderson.
ardb requested review of this revision.
Herald added subscribers: llvm-commits, MaskRay.
Herald added a project: LLVM.

Currently, llvm-objcopy assumes that any SHT_RELA type section with the SHF_ALLOC attribute is a dynamic relocation section, and therefore refers to symbol and string tables of the dynamic variety, which deviates from the ordinary static ones.

However, the ELF spec permits the use of SHF_ALLOC for ordinary SHT_RELA type sections as well, and so this heuristic is not entirely accurate, and may produce incorrect results, resulting in cryptic error messages such as

llvm-strip: error: Link field value 48 in section .rela.text is not a symbol table

where the file in question does in fact have a SYMTAB section at #48.

So let's replace this with a check against the ELF file type, which is more appropriate: partially linked binaries of type ET_REL cannot have dynamic relocation sections, and ET_EXEC/ET_DYN fully linked cannot have the static ones. Note that this requires that reading the section headers is deferred until after we figure out the file type, which also means that finding the executable header offset


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D111181

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


Index: llvm/tools/llvm-objcopy/ELF/Object.cpp
===================================================================
--- llvm/tools/llvm-objcopy/ELF/Object.cpp
+++ llvm/tools/llvm-objcopy/ELF/Object.cpp
@@ -1415,12 +1415,26 @@
 }
 
 template <class ELFT> Error ELFBuilder<ELFT>::findEhdrOffset() {
+  uint32_t Index = 0;
   if (!ExtractPartition)
     return Error::success();
 
-  for (const SectionBase &Sec : Obj.sections()) {
-    if (Sec.Type == SHT_LLVM_PART_EHDR && Sec.Name == *ExtractPartition) {
-      EhdrOffset = Sec.Offset;
+  Expected<typename ELFFile<ELFT>::Elf_Shdr_Range> Sections =
+      ElfFile.sections();
+  if (!Sections)
+    return Sections.takeError();
+
+  for (const typename ELFFile<ELFT>::Elf_Shdr &Shdr : *Sections) {
+    if (Index == 0) {
+      ++Index;
+      continue;
+    }
+    Expected<StringRef> SecName = ElfFile.getSectionName(Shdr);
+    if (!SecName)
+      return SecName.takeError();
+    if (Shdr.sh_type == SHT_LLVM_PART_EHDR &&
+        SecName->str() == *ExtractPartition) {
+      EhdrOffset = Shdr.sh_offset;
       return Error::success();
     }
   }
@@ -1692,7 +1706,7 @@
   switch (Shdr.sh_type) {
   case SHT_REL:
   case SHT_RELA:
-    if (Shdr.sh_flags & SHF_ALLOC) {
+    if (Obj.Type != ELF::ET_REL) {
       if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
         return Obj.addSection<DynamicRelocationSection>(*Data);
       else
@@ -1900,8 +1914,6 @@
 }
 
 template <class ELFT> Error ELFBuilder<ELFT>::build(bool EnsureSymtab) {
-  if (Error E = readSectionHeaders())
-    return E;
   if (Error E = findEhdrOffset())
     return E;
 
@@ -1922,6 +1934,8 @@
   Obj.Entry = Ehdr.e_entry;
   Obj.Flags = Ehdr.e_flags;
 
+  if (Error E = readSectionHeaders())
+    return E;
   if (Error E = readSections(EnsureSymtab))
     return E;
   return readProgramHeaders(*HeadersFile);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D111181.377339.patch
Type: text/x-patch
Size: 1866 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20211005/244501da/attachment.bin>


More information about the llvm-commits mailing list