diff --git a/llvm/test/tools/llvm-readobj/ELF/mips-abiflags.test b/llvm/test/tools/llvm-readobj/ELF/mips-abiflags.test --- a/llvm/test/tools/llvm-readobj/ELF/mips-abiflags.test +++ b/llvm/test/tools/llvm-readobj/ELF/mips-abiflags.test @@ -338,7 +338,7 @@ # RUN: llvm-readelf -A %t.err1 2>&1 | FileCheck %s -DFILE=%t.err1 --check-prefix=CONTENT-ERR # RUN: llvm-readobj -A %t.err1 2>&1 | FileCheck %s -DFILE=%t.err1 --check-prefix=CONTENT-ERR -# CONTENT-ERR: warning: '[[FILE]]': unable to read the .MIPS.abiflags section: section [index 1] has a sh_offset (0xffffffff) + sh_size (0x18) that is greater than the file size (0x240) +# CONTENT-ERR: warning: '[[FILE]]': unable to read the .MIPS.abiflags section: section [index 2] has a sh_offset (0xffffffff) + sh_size (0x18) that is greater than the file size (0x2c0) # CONTENT-ERR-NEXT: There is no .MIPS.options section in the file. # CONTENT-ERR-NEXT: There is no .reginfo section in the file. @@ -349,12 +349,17 @@ Type: ET_REL Machine: EM_MIPS Sections: + - Type: SHT_PROGBITS + ShName: [[NAME=]] - Name: .MIPS.abiflags Type: SHT_MIPS_ABIFLAGS ISA: MIPS32 Offset: 0x100 ShOffset: [[SHOFFSET=0x100]] ShSize: [[SHSIZE=24]] + ShName: [[ABIFLAGSNAME=]] + - Type: SHT_PROGBITS + ShName: [[NAME=]] ## Check we report a warning when the .MIPS.abiflags section has an unexpected size. # RUN: yaml2obj --docnum=3 -DSHSIZE=23 %s -o %t.err2 @@ -364,3 +369,24 @@ # SIZE-ERR: warning: '[[FILE]]': unable to read the .MIPS.abiflags section: it has a wrong size (23) # SIZE-ERR-NEXT: There is no .MIPS.options section in the file. # SIZE-ERR-NEXT: There is no .reginfo section in the file. + +## Check that we try to dump the .MIPS.abiflags section when we are able to locate it by name. +# RUN: yaml2obj --docnum=3 -DNAME=0xffff %s -o %t.err3 +# RUN: llvm-readelf -A %t.err3 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err3 --check-prefixes=NAME-ERR-FOUND,NAME-ERR-FOUND-GNU --implicit-check-not=warning: +# RUN: llvm-readobj -A %t.err3 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err3 --check-prefixes=NAME-ERR-FOUND,NAME-ERR-FOUND-LLVM --implicit-check-not=warning: + +# NAME-ERR-FOUND: warning: '[[FILE]]': unable to read the name of SHT_PROGBITS section with index 1: a section [index 1] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table +# NAME-ERR-FOUND-GNU-NEXT: MIPS ABI Flags Version: 0 +# NAME-ERR-FOUND-LLVM-NEXT: MIPS ABI Flags { +# NAME-ERR-FOUND: warning: '[[FILE]]': unable to read the name of SHT_PROGBITS section with index 3: a section [index 3] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table + +## Check we report a warning when we are unable to find the .MIPS.abiflags section due to an error. +# RUN: yaml2obj --docnum=3 -DABIFLAGSNAME=0xffff %s -o %t.err4 +# RUN: llvm-readelf -A %t.err4 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err4 --check-prefix=NAME-ERR-NOTFOUND --implicit-check-not=warning: --implicit-check-not="MIPS ABI Flags" +# RUN: llvm-readobj -A %t.err4 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err4 --check-prefix=NAME-ERR-NOTFOUND --implicit-check-not=warning: --implicit-check-not="MIPS ABI Flags" + +# NAME-ERR-NOTFOUND: warning: '[[FILE]]': unable to read the name of SHT_MIPS_ABIFLAGS section with index 2: a section [index 2] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table diff --git a/llvm/test/tools/llvm-readobj/ELF/mips-got.test b/llvm/test/tools/llvm-readobj/ELF/mips-got.test --- a/llvm/test/tools/llvm-readobj/ELF/mips-got.test +++ b/llvm/test/tools/llvm-readobj/ELF/mips-got.test @@ -547,3 +547,35 @@ - Tag: DT_PLTGOT Value: [[VAL2=0]] DynamicSymbols: [] + +## Check that we do not report a warning about the .got section when we are able to locate it by name. +# RUN: yaml2obj --docnum=3 -DNAME=0xffff %s -o %t.err6.o +# RUN: llvm-readobj -A %t.err6.o 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err6.o -check-prefix=NAME-ERR-FOUND --implicit-check-not=warning: +# RUN: llvm-readelf -A %t.err6.o 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err6.o -check-prefix=NAME-ERR-FOUND --implicit-check-not=warning: + +# NAME-ERR-FOUND: warning: '[[FILE]]': unable to read the name of SHT_PROGBITS section with index 1: a section [index 1] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table +# NAME-ERR-FOUND-NEXT: warning: '[[FILE]]': unable to read the name of SHT_PROGBITS section with index 3: a section [index 3] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS +Sections: + - Type: SHT_PROGBITS + ShName: [[NAME=]] + - Name: .got + Type: SHT_PROGBITS + ShName: [[GOTNAME=]] + - Type: SHT_PROGBITS + ShName: [[NAME=]] + +## Check we report a warning when we are unable to find the .got section due to an error. +# RUN: yaml2obj --docnum=3 -DGOTNAME=0xffff %s -o %t.err7.o +# RUN: llvm-readelf -A %t.err7.o 2>&1 | FileCheck %s -DFILE=%t.err7.o --check-prefix=NAME-ERR-NOTFOUND --implicit-check-not=warning: +# RUN: llvm-readobj -A %t.err7.o 2>&1 | FileCheck %s -DFILE=%t.err7.o --check-prefix=NAME-ERR-NOTFOUND --implicit-check-not=warning: + +# NAME-ERR-NOTFOUND: warning: '[[FILE]]': unable to read the name of SHT_PROGBITS section with index 2: a section [index 2] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table diff --git a/llvm/test/tools/llvm-readobj/ELF/mips-options-sec.test b/llvm/test/tools/llvm-readobj/ELF/mips-options-sec.test --- a/llvm/test/tools/llvm-readobj/ELF/mips-options-sec.test +++ b/llvm/test/tools/llvm-readobj/ELF/mips-options-sec.test @@ -12,3 +12,39 @@ # CHECK-NEXT: Co-Proc Mask3: 0x0 # CHECK-NEXT: } # CHECK-NEXT: } + +## Check that we try to dump the .MIPS.options section when we are able to locate it by name. +# RUN: yaml2obj --docnum=1 -DNAME=0xffff %s -o %t.err1 +# RUN: llvm-readelf -A %t.err1 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err1 --check-prefix=NAME-ERR-FOUND --implicit-check-not=warning: +# RUN: llvm-readobj -A %t.err1 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err1 --check-prefix=NAME-ERR-FOUND --implicit-check-not=warning: + +# NAME-ERR-FOUND: warning: '[[FILE]]': unable to read the name of SHT_PROGBITS section with index 1: a section [index 1] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table +# NAME-ERR-FOUND-NEXT: warning: '[[FILE]]': unable to read the name of SHT_PROGBITS section with index 3: a section [index 3] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table +# NAME-ERR-FOUND: MIPS Options { +# NAME-ERR-FOUND-NEXT: } + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS +Sections: + - Type: SHT_PROGBITS + ShName: [[NAME=]] + - Name: .MIPS.options + Type: SHT_MIPS_OPTIONS + ShName: [[OPTNAME=]] + - Type: SHT_PROGBITS + ShName: [[NAME=]] + +## Check we report a warning when we are unable to find the .MIPS.options section due to an error. +# RUN: yaml2obj --docnum=1 -DOPTNAME=0xffff %s -o %t.err2 +# RUN: llvm-readelf -A %t.err2 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err2 --check-prefix=NAME-ERR-NOTFOUND --implicit-check-not=warning: --implicit-check-not="MIPS Options" +# RUN: llvm-readobj -A %t.err2 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err2 --check-prefix=NAME-ERR-NOTFOUND --implicit-check-not=warning: --implicit-check-not="MIPS Options" + +# NAME-ERR-NOTFOUND: warning: '[[FILE]]': unable to read the name of SHT_MIPS_OPTIONS section with index 2: a section [index 2] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table diff --git a/llvm/test/tools/llvm-readobj/ELF/mips-reginfo.test b/llvm/test/tools/llvm-readobj/ELF/mips-reginfo.test --- a/llvm/test/tools/llvm-readobj/ELF/mips-reginfo.test +++ b/llvm/test/tools/llvm-readobj/ELF/mips-reginfo.test @@ -10,3 +10,38 @@ # CHECK-NEXT: Co-Proc Mask2: 0x0 # CHECK-NEXT: Co-Proc Mask3: 0x0 # CHECK-NEXT: } + +## Check that we try to dump the .reginfo section when we are able to locate it by name. +# RUN: yaml2obj --docnum=1 -DNAME=0xffff %s -o %t.err1 +# RUN: llvm-readelf -A %t.err1 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err1 --check-prefix=NAME-ERR-FOUND --implicit-check-not=warning: +# RUN: llvm-readobj -A %t.err1 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err1 --check-prefix=NAME-ERR-FOUND --implicit-check-not=warning: + +# NAME-ERR-FOUND: warning: '[[FILE]]': unable to read the name of SHT_PROGBITS section with index 1: a section [index 1] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table +# NAME-ERR-FOUND-NEXT: warning: '[[FILE]]': unable to read the name of SHT_PROGBITS section with index 3: a section [index 3] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table +# NAME-ERR-FOUND: The .reginfo section has a wrong size. + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS +Sections: + - Type: SHT_PROGBITS + ShName: [[NAME=]] + - Name: .reginfo + Type: SHT_MIPS_REGINFO + ShName: [[REGINFONAME=]] + - Type: SHT_PROGBITS + ShName: [[NAME=]] + +## Check we report a warning when we are unable to find the .reginfo section due to an error. +# RUN: yaml2obj --docnum=1 -DREGINFONAME=0xffff %s -o %t.err2 +# RUN: llvm-readelf -A %t.err2 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err2 --check-prefix=NAME-ERR-NOTFOUND --implicit-check-not=warning: +# RUN: llvm-readobj -A %t.err2 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.err2 --check-prefix=NAME-ERR-NOTFOUND --implicit-check-not=warning: + +# NAME-ERR-NOTFOUND: warning: '[[FILE]]': unable to read the name of SHT_MIPS_REGINFO section with index 2: a section [index 2] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -353,6 +353,8 @@ void printSymbolsHelper(bool IsDynamic) const; std::string getDynamicEntry(uint64_t Type, uint64_t Value) const; + Expected findSectionByName(StringRef Name) const; + const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; } const Elf_Shdr *getDotCGProfileSec() const { return DotCGProfileSec; } const Elf_Shdr *getDotAddrsigSec() const { return DotAddrsigSec; } @@ -1286,15 +1288,6 @@ return nullptr; } -template -static const typename ELFO::Elf_Shdr * -findSectionByName(const ELFO &Obj, StringRef FileName, StringRef Name) { - for (const typename ELFO::Elf_Shdr &Shdr : cantFail(Obj.sections())) - if (Name == unwrapOrError(FileName, Obj.getSectionName(&Shdr))) - return &Shdr; - return nullptr; -} - static const EnumEntry ElfClass[] = { {"None", "none", ELF::ELFCLASSNONE}, {"32-bit", "ELF32", ELF::ELFCLASS32}, @@ -2457,6 +2450,23 @@ } } +template +Expected +ELFDumper::findSectionByName(StringRef Name) const { + const ELFFile *Obj = ObjF->getELFFile(); + for (const Elf_Shdr &Shdr : cantFail(Obj->sections())) { + if (Expected NameOrErr = Obj->getSectionName(&Shdr)) { + if (*NameOrErr == Name) + return &Shdr; + } else { + reportUniqueWarning(createError("unable to read the name of " + + describe(Shdr) + ": " + + toString(NameOrErr.takeError()))); + } + } + return nullptr; +} + template std::string ELFDumper::getDynamicEntry(uint64_t Type, uint64_t Value) const { @@ -2864,9 +2874,7 @@ ELFDumperStyle->printMipsABIFlags(ObjF); printMipsOptions(); printMipsReginfo(); - - MipsGOTParser Parser(Obj, ObjF->getFileName(), dynamic_table(), - dynamic_symbols()); + MipsGOTParser Parser(*this); if (Error E = Parser.findGOT(dynamic_table(), dynamic_symbols())) reportError(std::move(E), ObjF->getFileName()); else if (!Parser.isGotEmpty()) @@ -2933,9 +2941,9 @@ const bool IsStatic; const ELFO * const Obj; + const ELFDumper &Dumper; - MipsGOTParser(const ELFO *Obj, StringRef FileName, Elf_Dyn_Range DynTable, - Elf_Sym_Range DynSyms); + MipsGOTParser(const ELFDumper &D); Error findGOT(Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms); Error findPLT(Elf_Dyn_Range DynTable); @@ -2983,12 +2991,11 @@ } // end anonymous namespace template -MipsGOTParser::MipsGOTParser(const ELFO *Obj, StringRef FileName, - Elf_Dyn_Range DynTable, - Elf_Sym_Range DynSyms) - : IsStatic(DynTable.empty()), Obj(Obj), GotSec(nullptr), LocalNum(0), - GlobalNum(0), PltSec(nullptr), PltRelSec(nullptr), PltSymTable(nullptr), - FileName(FileName) {} +MipsGOTParser::MipsGOTParser(const ELFDumper &D) + : IsStatic(D.dynamic_table().empty()), Obj(D.getElfObject()->getELFFile()), + Dumper(D), GotSec(nullptr), LocalNum(0), GlobalNum(0), PltSec(nullptr), + PltRelSec(nullptr), PltSymTable(nullptr), + FileName(D.getElfObject()->getFileName()) {} template Error MipsGOTParser::findGOT(Elf_Dyn_Range DynTable, @@ -2999,7 +3006,12 @@ // Find static GOT secton. if (IsStatic) { - GotSec = findSectionByName(*Obj, FileName, ".got"); + Expected GotOrErr = Dumper.findSectionByName(".got"); + if (!GotOrErr) + return GotOrErr.takeError(); + else + GotSec = *GotOrErr; + if (!GotSec) return Error::success(); @@ -3318,13 +3330,19 @@ template void ELFDumper::printMipsReginfo() { const ELFFile *Obj = ObjF->getELFFile(); - const Elf_Shdr *Shdr = findSectionByName(*Obj, ObjF->getFileName(), ".reginfo"); - if (!Shdr) { + Expected RegInfoOrErr = findSectionByName(".reginfo"); + if (!RegInfoOrErr) { + reportUniqueWarning(RegInfoOrErr.takeError()); + return; + } + + if ((*RegInfoOrErr) == nullptr) { W.startLine() << "There is no .reginfo section in the file.\n"; return; } - ArrayRef Sec = - unwrapOrError(ObjF->getFileName(), Obj->getSectionContents(Shdr)); + + ArrayRef Sec = unwrapOrError(ObjF->getFileName(), + Obj->getSectionContents(*RegInfoOrErr)); if (Sec.size() != sizeof(Elf_Mips_RegInfo)) { W.startLine() << "The .reginfo section has a wrong size.\n"; return; @@ -3337,17 +3355,21 @@ template void ELFDumper::printMipsOptions() { const ELFFile *Obj = ObjF->getELFFile(); - const Elf_Shdr *Shdr = - findSectionByName(*Obj, ObjF->getFileName(), ".MIPS.options"); - if (!Shdr) { + Expected MipsOptOrErr = findSectionByName(".MIPS.options"); + if (!MipsOptOrErr) { + reportUniqueWarning(MipsOptOrErr.takeError()); + return; + } + + if ((*MipsOptOrErr) == nullptr) { W.startLine() << "There is no .MIPS.options section in the file.\n"; return; } DictScope GS(W, "MIPS Options"); - ArrayRef Sec = - unwrapOrError(ObjF->getFileName(), Obj->getSectionContents(Shdr)); + ArrayRef Sec = unwrapOrError(ObjF->getFileName(), + Obj->getSectionContents(*MipsOptOrErr)); while (!Sec.empty()) { if (Sec.size() < sizeof(Elf_Mips_Options)) { W.startLine() << "The .MIPS.options section has a wrong size.\n"; @@ -5959,15 +5981,18 @@ template Expected *> -getMipsAbiFlagsSection(const ELFObjectFile *ObjF) { - const ELFFile *Obj = ObjF->getELFFile(); - const typename ELFT::Shdr *Shdr = - findSectionByName(*Obj, ObjF->getFileName(), ".MIPS.abiflags"); - if (!Shdr) +getMipsAbiFlagsSection(const ELFObjectFile *ObjF, + const ELFDumper &Dumper) { + Expected SecOrErr = + Dumper.findSectionByName(".MIPS.abiflags"); + if (!SecOrErr) + return SecOrErr.takeError(); + if (*SecOrErr == nullptr) return nullptr; + const ELFFile *Obj = ObjF->getELFFile(); constexpr StringRef ErrPrefix = "unable to read the .MIPS.abiflags section: "; - Expected> DataOrErr = Obj->getSectionContents(Shdr); + Expected> DataOrErr = Obj->getSectionContents(*SecOrErr); if (!DataOrErr) return createError(ErrPrefix + toString(DataOrErr.takeError())); @@ -5981,7 +6006,7 @@ void GNUStyle::printMipsABIFlags(const ELFObjectFile *ObjF) { const Elf_Mips_ABIFlags *Flags = nullptr; if (Expected *> SecOrErr = - getMipsAbiFlagsSection(ObjF)) + getMipsAbiFlagsSection(ObjF, *this->dumper())) Flags = *SecOrErr; else this->reportUniqueWarning(SecOrErr.takeError()); @@ -6926,7 +6951,7 @@ void LLVMStyle::printMipsABIFlags(const ELFObjectFile *ObjF) { const Elf_Mips_ABIFlags *Flags; if (Expected *> SecOrErr = - getMipsAbiFlagsSection(ObjF)) { + getMipsAbiFlagsSection(ObjF, *this->dumper())) { Flags = *SecOrErr; if (!Flags) { W.startLine() << "There is no .MIPS.abiflags section in the file.\n";