diff options
| author | George Rimar <grimar@accesssoftek.com> | 2019-09-17 13:58:46 +0000 |
|---|---|---|
| committer | George Rimar <grimar@accesssoftek.com> | 2019-09-17 13:58:46 +0000 |
| commit | a3569aced05dd0238e286283da46bb55cd1f4c83 (patch) | |
| tree | f894b5bfa84d477462d10f0fd57efa70f18e8b2f /llvm/tools/llvm-readobj/ELFDumper.cpp | |
| parent | f1d069e54df350a807e9b90462485483139327ea (diff) | |
| download | bcm5719-llvm-a3569aced05dd0238e286283da46bb55cd1f4c83.tar.gz bcm5719-llvm-a3569aced05dd0238e286283da46bb55cd1f4c83.zip | |
[llvm-readobj/llvm-objdump] - Improve how tool locate the dynamic table and report warnings about that.
Before this patch we gave a priority to a dynamic table found
from the section header.
It was discussed (here: https://reviews.llvm.org/D67078?id=218356#inline-602082)
that probably preferring the table from PT_DYNAMIC is better,
because it is what runtime loader sees.
This patch makes the table from PT_DYNAMIC be chosen at first place if it is available.
But also it adds logic to fall back to SHT_DYNAMIC if the table from the dynamic segment is
broken or fall back to use no table if both are broken.
It adds a few more diagnostic warnings for the logic above.
Differential revision: https://reviews.llvm.org/D67547
llvm-svn: 372122
Diffstat (limited to 'llvm/tools/llvm-readobj/ELFDumper.cpp')
| -rw-r--r-- | llvm/tools/llvm-readobj/ELFDumper.cpp | 130 |
1 files changed, 96 insertions, 34 deletions
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 7876f415c93..51e242f7db9 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -218,6 +218,8 @@ private: S->sh_entsize, ObjF->getFileName()}); } + std::pair<const Elf_Phdr *, const Elf_Shdr *> + findDynamic(const ELFFile<ELFT> *Obj); void loadDynamicTable(const ELFFile<ELFT> *Obj); void parseDynamicTable(); @@ -1417,7 +1419,8 @@ static const char *getElfMipsOptionsOdkType(unsigned Odk) { } template <typename ELFT> -void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) { +std::pair<const typename ELFT::Phdr *, const typename ELFT::Shdr *> +ELFDumper<ELFT>::findDynamic(const ELFFile<ELFT> *Obj) { // Try to locate the PT_DYNAMIC header. const Elf_Phdr *DynamicPhdr = nullptr; for (const Elf_Phdr &Phdr : @@ -1438,53 +1441,112 @@ void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) { break; } - // Information in the section header has priority over the information - // in a PT_DYNAMIC header. + if (DynamicPhdr && DynamicPhdr->p_offset + DynamicPhdr->p_filesz > + ObjF->getMemoryBufferRef().getBufferSize()) { + reportWarning( + createError( + "PT_DYNAMIC segment offset + size exceeds the size of the file"), + ObjF->getFileName()); + // Don't use the broken dynamic header. + DynamicPhdr = nullptr; + } + + if (DynamicPhdr && DynamicSec) { + StringRef Name = + unwrapOrError(ObjF->getFileName(), Obj->getSectionName(DynamicSec)); + if (DynamicSec->sh_addr + DynamicSec->sh_size > + DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz || + DynamicSec->sh_addr < DynamicPhdr->p_vaddr) + reportWarning(createError("The SHT_DYNAMIC section '" + Name + + "' is not contained within the " + "PT_DYNAMIC segment"), + ObjF->getFileName()); + + if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr) + reportWarning(createError("The SHT_DYNAMIC section '" + Name + + "' is not at the start of " + "PT_DYNAMIC segment"), + ObjF->getFileName()); + } + + return std::make_pair(DynamicPhdr, DynamicSec); +} + +template <typename ELFT> +void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) { + const Elf_Phdr *DynamicPhdr; + const Elf_Shdr *DynamicSec; + std::tie(DynamicPhdr, DynamicSec) = findDynamic(Obj); + if (!DynamicPhdr && !DynamicSec) + return; + + DynRegionInfo FromPhdr(ObjF->getFileName()); + bool IsPhdrTableValid = false; + if (DynamicPhdr) { + FromPhdr = createDRIFrom(DynamicPhdr, sizeof(Elf_Dyn)); + IsPhdrTableValid = !FromPhdr.getAsArrayRef<Elf_Dyn>().empty(); + } + + // Locate the dynamic table described in a section header. // Ignore sh_entsize and use the expected value for entry size explicitly. - // This allows us to dump the dynamic sections with a broken sh_entsize + // This allows us to dump dynamic sections with a broken sh_entsize // field. + DynRegionInfo FromSec(ObjF->getFileName()); + bool IsSecTableValid = false; if (DynamicSec) { - DynamicTable = + FromSec = checkDRI({ObjF->getELFFile()->base() + DynamicSec->sh_offset, DynamicSec->sh_size, sizeof(Elf_Dyn), ObjF->getFileName()}); - parseDynamicTable(); + IsSecTableValid = !FromSec.getAsArrayRef<Elf_Dyn>().empty(); } - // If we have a PT_DYNAMIC header, we will either check the found dynamic - // section or take the dynamic table data directly from the header. - if (!DynamicPhdr) - return; - - if (DynamicPhdr->p_offset + DynamicPhdr->p_filesz > - ObjF->getMemoryBufferRef().getBufferSize()) { - reportWarning( - createError( - "PT_DYNAMIC segment offset + size exceeds the size of the file"), - ObjF->getFileName()); + // When we only have information from one of the SHT_DYNAMIC section header or + // PT_DYNAMIC program header, just use that. + if (!DynamicPhdr || !DynamicSec) { + if ((DynamicPhdr && IsPhdrTableValid) || (DynamicSec && IsSecTableValid)) { + DynamicTable = DynamicPhdr ? FromPhdr : FromSec; + parseDynamicTable(); + } else { + reportWarning(createError("no valid dynamic table was found"), + ObjF->getFileName()); + } return; } - if (!DynamicSec) { - DynamicTable = createDRIFrom(DynamicPhdr, sizeof(Elf_Dyn)); - parseDynamicTable(); - return; - } + // At this point we have tables found from the section header and from the + // dynamic segment. Usually they match, but we have to do sanity checks to + // verify that. - StringRef Name = - unwrapOrError(ObjF->getFileName(), Obj->getSectionName(DynamicSec)); - if (DynamicSec->sh_addr + DynamicSec->sh_size > - DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz || - DynamicSec->sh_addr < DynamicPhdr->p_vaddr) - reportWarning(createError("The SHT_DYNAMIC section '" + Name + - "' is not contained within the " - "PT_DYNAMIC segment"), + if (FromPhdr.Addr != FromSec.Addr) + reportWarning(createError("SHT_DYNAMIC section header and PT_DYNAMIC " + "program header disagree about " + "the location of the dynamic table"), ObjF->getFileName()); - if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr) - reportWarning(createError("The SHT_DYNAMIC section '" + Name + - "' is not at the start of " - "PT_DYNAMIC segment"), + if (!IsPhdrTableValid && !IsSecTableValid) { + reportWarning(createError("no valid dynamic table was found"), ObjF->getFileName()); + return; + } + + // Information in the PT_DYNAMIC program header has priority over the information + // in a section header. + if (IsPhdrTableValid) { + if (!IsSecTableValid) + reportWarning( + createError( + "SHT_DYNAMIC dynamic table is invalid: PT_DYNAMIC will be used"), + ObjF->getFileName()); + DynamicTable = FromPhdr; + } else { + reportWarning( + createError( + "PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used"), + ObjF->getFileName()); + DynamicTable = FromSec; + } + + parseDynamicTable(); } template <typename ELFT> |

