diff options
-rwxr-xr-x | llvm/test/tools/llvm-readobj/Inputs/got-over.exe.elf-mips | bin | 0 -> 1648 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-readobj/mips-got-overlapped.test | 45 | ||||
-rw-r--r-- | llvm/tools/llvm-readobj/ELFDumper.cpp | 65 |
3 files changed, 70 insertions, 40 deletions
diff --git a/llvm/test/tools/llvm-readobj/Inputs/got-over.exe.elf-mips b/llvm/test/tools/llvm-readobj/Inputs/got-over.exe.elf-mips Binary files differnew file mode 100755 index 00000000000..27644bff330 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/Inputs/got-over.exe.elf-mips diff --git a/llvm/test/tools/llvm-readobj/mips-got-overlapped.test b/llvm/test/tools/llvm-readobj/mips-got-overlapped.test new file mode 100644 index 00000000000..ae4ae953295 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/mips-got-overlapped.test @@ -0,0 +1,45 @@ +# Check that llvm-readobj -mips-plt-got correctly shows .got section +# content if there are some other zero-sized sections with the same +# address as the .got. got-over.exe.elf-mips has zero-sized .data +# section at the same offset .got section. + +RUN: llvm-readobj -mips-plt-got %p/Inputs/got-over.exe.elf-mips | FileCheck %s + +GOT-OBJ: Cannot find PLTGOT dynamic table tag. + +CHECK: Primary GOT { +CHECK-NEXT: Canonical gp value: 0x418270 +CHECK-NEXT: Reserved entries [ +CHECK-NEXT: Entry { +CHECK-NEXT: Address: 0x410280 +CHECK-NEXT: Access: -32752 +CHECK-NEXT: Initial: 0x0 +CHECK-NEXT: Purpose: Lazy resolver +CHECK-NEXT: } +CHECK-NEXT: Entry { +CHECK-NEXT: Address: 0x410284 +CHECK-NEXT: Access: -32748 +CHECK-NEXT: Initial: 0x80000000 +CHECK-NEXT: Purpose: Module pointer (GNU extension) +CHECK-NEXT: } +CHECK-NEXT: ] +CHECK-NEXT: Local entries [ +CHECK-NEXT: Entry { +CHECK-NEXT: Address: 0x410288 +CHECK-NEXT: Access: -32744 +CHECK-NEXT: Initial: 0x4001B8 +CHECK-NEXT: } +CHECK-NEXT: ] +CHECK-NEXT: Global entries [ +CHECK-NEXT: Entry { +CHECK-NEXT: Address: 0x41028C +CHECK-NEXT: Access: -32740 +CHECK-NEXT: Initial: 0x0 +CHECK-NEXT: Value: 0x0 +CHECK-NEXT: Type: None +CHECK-NEXT: Section: Undefined +CHECK-NEXT: Name: _foo +CHECK-NEXT: } +CHECK-NEXT: ] +CHECK-NEXT: Number of TLS and multi-GOT entries: 0 +CHECK-NEXT: } diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 386d5422cbc..14ab4b1a8bc 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -497,10 +497,10 @@ getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol, } template <class ELFO> -static const typename ELFO::Elf_Shdr *findSectionByAddress(const ELFO *Obj, - uint64_t Addr) { +static const typename ELFO::Elf_Shdr * +findNotEmptySectionByAddress(const ELFO *Obj, uint64_t Addr) { for (const auto &Shdr : Obj->sections()) - if (Shdr.sh_addr == Addr) + if (Shdr.sh_addr == Addr && Shdr.sh_size > 0) return &Shdr; return nullptr; } @@ -1865,23 +1865,6 @@ template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() { return; } - const Elf_Shdr *GOTShdr = findSectionByAddress(Obj, *DtPltGot); - if (!GOTShdr) { - W.startLine() << "There is no .got section in the file.\n"; - return; - } - - ErrorOr<ArrayRef<uint8_t>> GOT = Obj->getSectionContents(GOTShdr); - if (!GOT) { - W.startLine() << "The .got section is empty.\n"; - return; - } - - if (*DtLocalGotNum > getGOTTotal(*GOT)) { - W.startLine() << "MIPS_LOCAL_GOTNO exceeds a number of GOT entries.\n"; - return; - } - const Elf_Shdr *DynSymSec = Dumper->getDotDynSymSec(); ErrorOr<StringRef> StrTable = Obj->getStringTableForSymtab(*DynSymSec); error(StrTable.getError()); @@ -1889,18 +1872,26 @@ template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() { const Elf_Sym *DynSymEnd = Obj->symbol_end(DynSymSec); std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd)); - if (*DtGotSym > DynSymTotal) { - W.startLine() << "MIPS_GOTSYM exceeds a number of dynamic symbols.\n"; - return; - } + if (*DtGotSym > DynSymTotal) + report_fatal_error("MIPS_GOTSYM exceeds a number of dynamic symbols"); std::size_t GlobalGotNum = DynSymTotal - *DtGotSym; - if (*DtLocalGotNum + GlobalGotNum > getGOTTotal(*GOT)) { - W.startLine() << "Number of global GOT entries exceeds the size of GOT.\n"; + if (*DtLocalGotNum + GlobalGotNum == 0) { + W.startLine() << "GOT is empty.\n"; return; } + const Elf_Shdr *GOTShdr = findNotEmptySectionByAddress(Obj, *DtPltGot); + if (!GOTShdr) + report_fatal_error("There is no not empty GOT section at 0x" + + Twine::utohexstr(*DtPltGot)); + + ErrorOr<ArrayRef<uint8_t>> GOT = Obj->getSectionContents(GOTShdr); + + if (*DtLocalGotNum + GlobalGotNum > getGOTTotal(*GOT)) + report_fatal_error("Number of GOT entries exceeds the size of GOT section"); + const GOTEntry *GotBegin = makeGOTIter(*GOT, 0); const GOTEntry *GotLocalEnd = makeGOTIter(*GOT, *DtLocalGotNum); const GOTEntry *It = GotBegin; @@ -1957,22 +1948,16 @@ template <class ELFT> void MipsGOTParser<ELFT>::parsePLT() { return; } - const Elf_Shdr *PLTShdr = findSectionByAddress(Obj, *DtMipsPltGot); - if (!PLTShdr) { - W.startLine() << "There is no .got.plt section in the file.\n"; - return; - } + const Elf_Shdr *PLTShdr = findNotEmptySectionByAddress(Obj, *DtMipsPltGot); + if (!PLTShdr) + report_fatal_error("There is no not empty PLTGOT section at 0x " + + Twine::utohexstr(*DtMipsPltGot)); ErrorOr<ArrayRef<uint8_t>> PLT = Obj->getSectionContents(PLTShdr); - if (!PLT) { - W.startLine() << "The .got.plt section is empty.\n"; - return; - } - const Elf_Shdr *PLTRelShdr = findSectionByAddress(Obj, *DtJmpRel); - if (!PLTShdr) { - W.startLine() << "There is no .rel.plt section in the file.\n"; - return; - } + const Elf_Shdr *PLTRelShdr = findNotEmptySectionByAddress(Obj, *DtJmpRel); + if (!PLTRelShdr) + report_fatal_error("There is no not empty RELPLT section at 0x" + + Twine::utohexstr(*DtJmpRel)); ErrorOr<const Elf_Shdr *> SymTableOrErr = Obj->getSection(PLTRelShdr->sh_link); error(SymTableOrErr.getError()); |