[llvm-readobj] - Don't call `unwrapOrErr` in `findSectionByName`.

We have a `findSectionByName` helper that tries to find a section
by it name. It is used in a few places, but never tested.

I'd like to reuse this helper for a different place.
For this, I've changed it to return Expected<> and now it
doesn't use `unwrapOrErr` anymore. It also now a member of
Dumper class and might report warnings.

Differential revision: https://reviews.llvm.org/D84651
This commit is contained in:
Georgii Rymar 2020-07-27 16:03:03 +03:00
parent d76057c1fe
commit 7e32797552
5 changed files with 193 additions and 39 deletions

View File

@ -338,7 +338,7 @@ Sections: []
# 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 @@ FileHeader:
Type: ET_REL
Machine: EM_MIPS
Sections:
- Type: SHT_PROGBITS
ShName: [[NAME=<none>]]
- Name: .MIPS.abiflags
Type: SHT_MIPS_ABIFLAGS
ISA: MIPS32
Offset: 0x100
ShOffset: [[SHOFFSET=0x100]]
ShSize: [[SHSIZE=24]]
ShName: [[ABIFLAGSNAME=<none>]]
- Type: SHT_PROGBITS
ShName: [[NAME=<none>]]
## 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 @@ Sections:
# 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

View File

@ -547,3 +547,35 @@ Sections:
- 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=<none>]]
- Name: .got
Type: SHT_PROGBITS
ShName: [[GOTNAME=<none>]]
- Type: SHT_PROGBITS
ShName: [[NAME=<none>]]
## 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

View File

@ -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=<none>]]
- Name: .MIPS.options
Type: SHT_MIPS_OPTIONS
ShName: [[OPTNAME=<none>]]
- Type: SHT_PROGBITS
ShName: [[NAME=<none>]]
## 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

View File

@ -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=<none>]]
- Name: .reginfo
Type: SHT_MIPS_REGINFO
ShName: [[REGINFONAME=<none>]]
- Type: SHT_PROGBITS
ShName: [[NAME=<none>]]
## 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

View File

@ -353,6 +353,8 @@ public:
void printSymbolsHelper(bool IsDynamic) const;
std::string getDynamicEntry(uint64_t Type, uint64_t Value) const;
Expected<const typename ELFT::Shdr *> 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 @@ findNotEmptySectionByAddress(const ELFO *Obj, StringRef FileName,
return nullptr;
}
template <class ELFO>
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<unsigned> ElfClass[] = {
{"None", "none", ELF::ELFCLASSNONE},
{"32-bit", "ELF32", ELF::ELFCLASS32},
@ -2457,6 +2450,23 @@ void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) {
}
}
template <class ELFT>
Expected<const typename ELFT::Shdr *>
ELFDumper<ELFT>::findSectionByName(StringRef Name) const {
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
for (const Elf_Shdr &Shdr : cantFail(Obj->sections())) {
if (Expected<StringRef> 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 <class ELFT>
std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type,
uint64_t Value) const {
@ -2864,9 +2874,7 @@ template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() {
ELFDumperStyle->printMipsABIFlags(ObjF);
printMipsOptions();
printMipsReginfo();
MipsGOTParser<ELFT> Parser(Obj, ObjF->getFileName(), dynamic_table(),
dynamic_symbols());
MipsGOTParser<ELFT> 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 @@ public:
const bool IsStatic;
const ELFO * const Obj;
const ELFDumper<ELFT> &Dumper;
MipsGOTParser(const ELFO *Obj, StringRef FileName, Elf_Dyn_Range DynTable,
Elf_Sym_Range DynSyms);
MipsGOTParser(const ELFDumper<ELFT> &D);
Error findGOT(Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms);
Error findPLT(Elf_Dyn_Range DynTable);
@ -2983,12 +2991,11 @@ private:
} // end anonymous namespace
template <class ELFT>
MipsGOTParser<ELFT>::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<ELFT>::MipsGOTParser(const ELFDumper<ELFT> &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 <class ELFT>
Error MipsGOTParser<ELFT>::findGOT(Elf_Dyn_Range DynTable,
@ -2999,7 +3006,12 @@ Error MipsGOTParser<ELFT>::findGOT(Elf_Dyn_Range DynTable,
// Find static GOT secton.
if (IsStatic) {
GotSec = findSectionByName(*Obj, FileName, ".got");
Expected<const Elf_Shdr *> GotOrErr = Dumper.findSectionByName(".got");
if (!GotOrErr)
return GotOrErr.takeError();
else
GotSec = *GotOrErr;
if (!GotSec)
return Error::success();
@ -3318,13 +3330,19 @@ static void printMipsReginfoData(ScopedPrinter &W,
template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() {
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
const Elf_Shdr *Shdr = findSectionByName(*Obj, ObjF->getFileName(), ".reginfo");
if (!Shdr) {
Expected<const Elf_Shdr *> 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<uint8_t> Sec =
unwrapOrError(ObjF->getFileName(), Obj->getSectionContents(Shdr));
ArrayRef<uint8_t> Sec = unwrapOrError(ObjF->getFileName(),
Obj->getSectionContents(*RegInfoOrErr));
if (Sec.size() != sizeof(Elf_Mips_RegInfo<ELFT>)) {
W.startLine() << "The .reginfo section has a wrong size.\n";
return;
@ -3337,17 +3355,21 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() {
template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() {
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
const Elf_Shdr *Shdr =
findSectionByName(*Obj, ObjF->getFileName(), ".MIPS.options");
if (!Shdr) {
Expected<const Elf_Shdr *> 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<uint8_t> Sec =
unwrapOrError(ObjF->getFileName(), Obj->getSectionContents(Shdr));
ArrayRef<uint8_t> Sec = unwrapOrError(ObjF->getFileName(),
Obj->getSectionContents(*MipsOptOrErr));
while (!Sec.empty()) {
if (Sec.size() < sizeof(Elf_Mips_Options<ELFT>)) {
W.startLine() << "The .MIPS.options section has a wrong size.\n";
@ -5959,15 +5981,18 @@ void GNUStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {
template <class ELFT>
Expected<const Elf_Mips_ABIFlags<ELFT> *>
getMipsAbiFlagsSection(const ELFObjectFile<ELFT> *ObjF) {
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
const typename ELFT::Shdr *Shdr =
findSectionByName(*Obj, ObjF->getFileName(), ".MIPS.abiflags");
if (!Shdr)
getMipsAbiFlagsSection(const ELFObjectFile<ELFT> *ObjF,
const ELFDumper<ELFT> &Dumper) {
Expected<const typename ELFT::Shdr *> SecOrErr =
Dumper.findSectionByName(".MIPS.abiflags");
if (!SecOrErr)
return SecOrErr.takeError();
if (*SecOrErr == nullptr)
return nullptr;
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
constexpr StringRef ErrPrefix = "unable to read the .MIPS.abiflags section: ";
Expected<ArrayRef<uint8_t>> DataOrErr = Obj->getSectionContents(Shdr);
Expected<ArrayRef<uint8_t>> DataOrErr = Obj->getSectionContents(*SecOrErr);
if (!DataOrErr)
return createError(ErrPrefix + toString(DataOrErr.takeError()));
@ -5981,7 +6006,7 @@ template <class ELFT>
void GNUStyle<ELFT>::printMipsABIFlags(const ELFObjectFile<ELFT> *ObjF) {
const Elf_Mips_ABIFlags<ELFT> *Flags = nullptr;
if (Expected<const Elf_Mips_ABIFlags<ELFT> *> SecOrErr =
getMipsAbiFlagsSection(ObjF))
getMipsAbiFlagsSection(ObjF, *this->dumper()))
Flags = *SecOrErr;
else
this->reportUniqueWarning(SecOrErr.takeError());
@ -6926,7 +6951,7 @@ template <class ELFT>
void LLVMStyle<ELFT>::printMipsABIFlags(const ELFObjectFile<ELFT> *ObjF) {
const Elf_Mips_ABIFlags<ELFT> *Flags;
if (Expected<const Elf_Mips_ABIFlags<ELFT> *> SecOrErr =
getMipsAbiFlagsSection(ObjF)) {
getMipsAbiFlagsSection(ObjF, *this->dumper())) {
Flags = *SecOrErr;
if (!Flags) {
W.startLine() << "There is no .MIPS.abiflags section in the file.\n";