diff options
author | Georgii Rymar <grimar@accesssoftek.com> | 2020-12-03 17:14:05 +0300 |
---|---|---|
committer | Georgii Rymar <grimar@accesssoftek.com> | 2020-12-09 12:31:46 +0300 |
commit | bdfafc4613bd2ff933c846708f4726128fb4b1ce (patch) | |
tree | baa5e87db2435c6d67323bbc47d4fbf8c0118eb7 | |
parent | d53656900921de5bb26b849b5910efd05a233107 (diff) | |
download | llvm-project-bdfafc4613bd2ff933c846708f4726128fb4b1ce.tar.gz |
[llvm-readelf/obj] - Improve diagnostics when printing NT_FILE notes.
This changes the `printNotesHelper` to report warnings on its side when
there are errors when dumping notes.
With that we can provide more content when reporting warnings about broken notes.
Differential revision: https://reviews.llvm.org/D92636
-rw-r--r-- | llvm/test/tools/llvm-readobj/ELF/note-core-ntfile-bad.test | 16 | ||||
-rw-r--r-- | llvm/tools/llvm-readobj/ELFDumper.cpp | 62 |
2 files changed, 52 insertions, 26 deletions
diff --git a/llvm/test/tools/llvm-readobj/ELF/note-core-ntfile-bad.test b/llvm/test/tools/llvm-readobj/ELF/note-core-ntfile-bad.test index ca3033c7248a..5a497c23a795 100644 --- a/llvm/test/tools/llvm-readobj/ELF/note-core-ntfile-bad.test +++ b/llvm/test/tools/llvm-readobj/ELF/note-core-ntfile-bad.test @@ -9,7 +9,9 @@ # RUN: yaml2obj --docnum=1 %s -o %t1.o # RUN: llvm-readelf -n %t1.o 2>&1 | FileCheck -DFILE=%t1.o %s --check-prefix=ERR-HEADER-SHORT -# ERR-HEADER-SHORT: warning: '[[FILE]]': malformed note: header too short +# RUN: llvm-readobj -n %t1.o 2>&1 | FileCheck -DFILE=%t1.o %s --check-prefix=ERR-HEADER-SHORT + +# ERR-HEADER-SHORT: warning: '[[FILE]]': unable to read note with index 0 from the PT_NOTE segment with index 1: the note of size 0x8 is too short, expected at least 0x10 # .section ".note.foo", "a" # .align 4 @@ -38,7 +40,9 @@ ProgramHeaders: # RUN: yaml2obj --docnum=2 %s -o %t2.o # RUN: llvm-readelf -n %t2.o 2>&1 | FileCheck -DFILE=%t2.o %s --check-prefix=ERR-NULL-TERM -# ERR-NULL-TERM: warning: '[[FILE]]': malformed note: not NUL terminated +# RUN: llvm-readobj -n %t2.o 2>&1 | FileCheck -DFILE=%t2.o %s --check-prefix=ERR-NULL-TERM + +# ERR-NULL-TERM: warning: '[[FILE]]': unable to read note with index 0 from the PT_NOTE segment with index 1: the note is not NUL terminated # .section ".note.foo", "a" # .align 4 @@ -72,7 +76,9 @@ ProgramHeaders: # RUN: yaml2obj --docnum=3 %s -o %t3.o # RUN: llvm-readelf -n %t3.o 2>&1 | FileCheck -DFILE=%t3.o %s --check-prefix=ERR-FILE-COUNT -# ERR-FILE-COUNT: warning: '[[FILE]]': malformed note: too short for number of files +# RUN: llvm-readobj -n %t3.o 2>&1 | FileCheck -DFILE=%t3.o %s --check-prefix=ERR-FILE-COUNT + +# ERR-FILE-COUNT: warning: '[[FILE]]': unable to read note with index 0 from the PT_NOTE segment with index 1: unable to read file mappings (found 2): the note of size 0x2c is too short # .section ".note.foo", "a" # .align 4 @@ -106,7 +112,9 @@ ProgramHeaders: # RUN: yaml2obj --docnum=4 %s -o %t4.o # RUN: llvm-readelf -n %t4.o 2>&1 | FileCheck -DFILE=%t4.o %s --check-prefix=ERR-FILE-END-EARLY -# ERR-FILE-END-EARLY: warning: '[[FILE]]': malformed note: too few filenames +# RUN: llvm-readobj -n %t4.o 2>&1 | FileCheck -DFILE=%t4.o %s --check-prefix=ERR-FILE-END-EARLY + +# ERR-FILE-END-EARLY: warning: '[[FILE]]': unable to read note with index 0 from the PT_NOTE segment with index 1: unable to read the file name for the mapping with index 2: the note of size 0x44 is truncated # .section ".note.foo", "a" # .align 4 diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 2a286cb0b50d..279e406397d5 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -5333,19 +5333,20 @@ static Expected<CoreNote> readCoreNote(DataExtractor Desc) { const int Bytes = Desc.getAddressSize(); if (!Desc.isValidOffsetForAddress(2)) - return createStringError(object_error::parse_failed, - "malformed note: header too short"); + return createError("the note of size 0x" + Twine::utohexstr(Desc.size()) + + " is too short, expected at least 0x" + + Twine::utohexstr(Bytes * 2)); if (Desc.getData().back() != 0) - return createStringError(object_error::parse_failed, - "malformed note: not NUL terminated"); + return createError("the note is not NUL terminated"); uint64_t DescOffset = 0; uint64_t FileCount = Desc.getAddress(&DescOffset); Ret.PageSize = Desc.getAddress(&DescOffset); if (!Desc.isValidOffsetForAddress(3 * FileCount * Bytes)) - return createStringError(object_error::parse_failed, - "malformed note: too short for number of files"); + return createError("unable to read file mappings (found " + + Twine(FileCount) + "): the note of size 0x" + + Twine::utohexstr(Desc.size()) + " is too short"); uint64_t FilenamesOffset = 0; DataExtractor Filenames( @@ -5353,10 +5354,14 @@ static Expected<CoreNote> readCoreNote(DataExtractor Desc) { Desc.isLittleEndian(), Desc.getAddressSize()); Ret.Mappings.resize(FileCount); + size_t I = 0; for (CoreFileMapping &Mapping : Ret.Mappings) { + ++I; if (!Filenames.isValidOffsetForDataOfSize(FilenamesOffset, 1)) - return createStringError(object_error::parse_failed, - "malformed note: too few filenames"); + return createError( + "unable to read the file name for the mapping with index " + + Twine(I) + ": the note of size 0x" + Twine::utohexstr(Desc.size()) + + " is truncated"); Mapping.Start = Desc.getAddress(&DescOffset); Mapping.End = Desc.getAddress(&DescOffset); Mapping.Offset = Desc.getAddress(&DescOffset); @@ -5521,7 +5526,7 @@ static void printNotesHelper( llvm::function_ref<void(Optional<StringRef>, typename ELFT::Off, typename ELFT::Addr)> StartNotesFn, - llvm::function_ref<void(const typename ELFT::Note &)> ProcessNoteFn, + llvm::function_ref<Error(const typename ELFT::Note &)> ProcessNoteFn, llvm::function_ref<void()> FinishNotesFn) { const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile(); @@ -5533,8 +5538,14 @@ static void printNotesHelper( StartNotesFn(expectedToOptional(Obj.getSectionName(S)), S.sh_offset, S.sh_size); Error Err = Error::success(); - for (const typename ELFT::Note Note : Obj.notes(S, Err)) - ProcessNoteFn(Note); + size_t I = 0; + for (const typename ELFT::Note Note : Obj.notes(S, Err)) { + if (Error E = ProcessNoteFn(Note)) + Dumper.reportUniqueWarning( + "unable to read note with index " + Twine(I) + " from the " + + describe(Obj, S) + ": " + toString(std::move(E))); + ++I; + } if (Err) Dumper.reportUniqueWarning("unable to read notes from the " + describe(Obj, S) + ": " + @@ -5559,8 +5570,15 @@ static void printNotesHelper( continue; StartNotesFn(/*SecName=*/None, P.p_offset, P.p_filesz); Error Err = Error::success(); - for (const typename ELFT::Note Note : Obj.notes(P, Err)) - ProcessNoteFn(Note); + size_t Index = 0; + for (const typename ELFT::Note Note : Obj.notes(P, Err)) { + if (Error E = ProcessNoteFn(Note)) + Dumper.reportUniqueWarning("unable to read note with index " + + Twine(Index) + + " from the PT_NOTE segment with index " + + Twine(I) + ": " + toString(std::move(E))); + ++Index; + } if (Err) Dumper.reportUniqueWarning( "unable to read notes from the PT_NOTE segment with index " + @@ -5584,7 +5602,7 @@ template <class ELFT> void GNUStyle<ELFT>::printNotes() { OS << " Owner Data size \tDescription\n"; }; - auto ProcessNote = [&](const Elf_Note &Note) { + auto ProcessNote = [&](const Elf_Note &Note) -> Error { StringRef Name = Note.getName(); ArrayRef<uint8_t> Descriptor = Note.getDesc(); Elf_Word Type = Note.getType(); @@ -5617,11 +5635,10 @@ template <class ELFT> void GNUStyle<ELFT>::printNotes() { DataExtractor DescExtractor(Descriptor, ELFT::TargetEndianness == support::little, sizeof(Elf_Addr)); - Expected<CoreNote> Note = readCoreNote(DescExtractor); - if (Note) - printCoreNote<ELFT>(OS, *Note); + if (Expected<CoreNote> NoteOrErr = readCoreNote(DescExtractor)) + printCoreNote<ELFT>(OS, *NoteOrErr); else - reportWarning(Note.takeError(), this->FileName); + return NoteOrErr.takeError(); } } else if (!Descriptor.empty()) { OS << " description data:"; @@ -5629,6 +5646,7 @@ template <class ELFT> void GNUStyle<ELFT>::printNotes() { OS << " " << format("%02x", B); OS << '\n'; } + return Error::success(); }; printNotesHelper(this->dumper(), PrintHeader, ProcessNote, []() {}); @@ -6836,7 +6854,7 @@ template <class ELFT> void LLVMStyle<ELFT>::printNotes() { auto EndNotes = [&] { NoteScope.reset(); }; - auto ProcessNote = [&](const Elf_Note &Note) { + auto ProcessNote = [&](const Elf_Note &Note) -> Error { DictScope D2(W, "Note"); StringRef Name = Note.getName(); ArrayRef<uint8_t> Descriptor = Note.getDesc(); @@ -6871,15 +6889,15 @@ template <class ELFT> void LLVMStyle<ELFT>::printNotes() { DataExtractor DescExtractor(Descriptor, ELFT::TargetEndianness == support::little, sizeof(Elf_Addr)); - Expected<CoreNote> Note = readCoreNote(DescExtractor); - if (Note) + if (Expected<CoreNote> Note = readCoreNote(DescExtractor)) printCoreNoteLLVMStyle(*Note, W); else - reportWarning(Note.takeError(), this->FileName); + return Note.takeError(); } } else if (!Descriptor.empty()) { W.printBinaryBlock("Description data", Descriptor); } + return Error::success(); }; printNotesHelper(this->dumper(), StartNotes, ProcessNote, EndNotes); |