summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-readobj/ELFDumper.cpp
diff options
context:
space:
mode:
authorGeorge Rimar <grimar@accesssoftek.com>2019-09-17 13:58:46 +0000
committerGeorge Rimar <grimar@accesssoftek.com>2019-09-17 13:58:46 +0000
commita3569aced05dd0238e286283da46bb55cd1f4c83 (patch)
treef894b5bfa84d477462d10f0fd57efa70f18e8b2f /llvm/tools/llvm-readobj/ELFDumper.cpp
parentf1d069e54df350a807e9b90462485483139327ea (diff)
downloadbcm5719-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.cpp130
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>
OpenPOWER on IntegriCloud