Index: llvm/trunk/test/tools/llvm-readobj/mips-got-overlapped.test =================================================================== --- llvm/trunk/test/tools/llvm-readobj/mips-got-overlapped.test +++ llvm/trunk/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: } Index: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp =================================================================== --- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp +++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp @@ -497,10 +497,10 @@ } template -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 @@ return; } - const Elf_Shdr *GOTShdr = findSectionByAddress(Obj, *DtPltGot); - if (!GOTShdr) { - W.startLine() << "There is no .got section in the file.\n"; - return; - } - - ErrorOr> 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 StrTable = Obj->getStringTableForSymtab(*DynSymSec); error(StrTable.getError()); @@ -1889,18 +1872,26 @@ 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> 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 @@ 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> 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 SymTableOrErr = Obj->getSection(PLTRelShdr->sh_link); error(SymTableOrErr.getError());