Currently we might derive the dynamic symbol table size from the DT_HASH hash table (using its `nchain` field).
It is possible to crash dumpers with a broken relocation that refers to a symbol with an index
that is too large. To trigger it, the inferred size of the dynamic symbol table should go past the end of the object.
This patch adds a size validation + warning.
Differential revision: https://reviews.llvm.org/D86923
Our implementation of stack sizes section dumping heavily uses `ELFObjectFile<ELFT>`,
while the rest of the code uses `ELFFile<ELFT>`.
That APIs are very different. `ELFObjectFile<ELFT>` is very generic
and has `SectionRef`, `RelocationRef`, `SymbolRef` and other generic concepts.
The `ELFFile<ELFT>` class works directly with `Elf_Shdr`, `Elf_Rel[a]`, `Elf_Sym` etc,
what is probably much cleaner for ELF dumper.
Also, `ELFObjectFile<ELFT>` API does not always provide a way to check
for possible errors. E.g. the implementation of `symbol_end()` does not verify the `sh_size`:
```
template <class ELFT>
basic_symbol_iterator ELFObjectFile<ELFT>::symbol_end() const {
const Elf_Shdr *SymTab = DotSymtabSec;
if (!SymTab)
return symbol_begin();
DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym));
return basic_symbol_iterator(SymbolRef(Sym, this));
}
```
There are many other examples which makes me thing we might win from
switching to `ELFFile<ELFT>` API, where we heavily validate an input data already.
This patch is the first step in this direction. I've converted the large portion of the code
to use `ELFFile<ELFT>`.
Differential revision: https://reviews.llvm.org/D87362
`ELFFile<ELFT>` has many methods that take pointers,
though they assume that arguments are never null and
hence could take references instead.
This patch performs such clean-up.
Differential revision: https://reviews.llvm.org/D87385
In addition to printing the individual fields, synthesize and
print the corresponding prolog for the unwind info (in reverse
order, to match how it's printed for non-packed unwind info).
Differential Revision: https://reviews.llvm.org/D87370
This changes messages reported to stop using dynamic section names (use `describe()` instead).
This allows to avoid `unwrapOrError` and improves diagnostics.
Differential revision: https://reviews.llvm.org/D87503
It has following issues:
1) `getStaticSymbolName` returns `std::string`, but the code
assigns a result to `Expected<std::string>`.
2) The code uses `unwrapOrError` and never tests the error reported.
This patch fixes these issues.
Differential revision: https://reviews.llvm.org/D87507
There is some code that can be shared between GNU/LLVM styles.
Also, this fixes 2 inconsistencies related to dumping unknown note types:
1) For GNU style we printed "Unknown note type: (0x00000003)" in some cases, and
"Unknown note type (0x00000003)" (no colon) in other cases.
GNU readelf always prints `:`. This patch removes the related code
duplication and does the same.
2) For LLVM style in some cases we printed "Unknown note type (0x00000003)",
but sometimes just "Unknown (0x00000003)". The latter is the right form, which
is consistent with other unknowns that are printed in LLVM style.
Rebased on top of D87453.
Differential revision: https://reviews.llvm.org/D87454
This matches how e.g. stp/ldp and other opcodes are printed differently
for epilogues.
Also add a missing --strict-whitespace in an existing test that
was added explicitly for testing vertical alignment, and change to
using temp files for the generated object files.
Differential Revision: https://reviews.llvm.org/D87363
LLVM style code can be simplified to avoid the duplication of logic
related to printing dynamic relocations.
Differential revision: https://reviews.llvm.org/D87089
Currently we have 2 large `printDynamicRelocations` methods that
have a very similar code for GNU/LLVM styles.
This patch removes the duplication and renames them to `printDynamicReloc`
for consistency.
Differential revision: https://reviews.llvm.org/D87087
It removes templating for Elf_Rel[a] handling that we
introduced earlier and introduces a helper class instead.
It was briefly discussed in D87087, which showed,
why having templates is probably not ideal for the generalization
of dumpers code.
Differential revision: https://reviews.llvm.org/D87141
We have the `RelSymbol<ELFT>` struct and can use it instead
of `std::pair<const Elf_Sym *, std::string>` in a few methods.
This is a bit cleaner.
Differential revision: https://reviews.llvm.org/D87092
Instead of referring to stack sizes sections only by name, we can add
section indexes and types to warnings reported.
Differential revision: https://reviews.llvm.org/D86934
We have 2 DumpStyles currently:
`class GNUStyle : public DumpStyle<ELFT>` and `class LLVMStyle : public DumpStyle<ELFT>`.
The problem of `DumpStyle` interface is that almost for each method
we provide `const ELFFile<ELFT> *` as argument. But in fact each of
dump styles keeps `ELFDumper<ELFT> *Dumper` which can be used to get an object from.
But since we use the `Obj` too often, I've decided to introduce a one more reference member
instead of reading it from the `Dumper` each time:
`const ELFFile<ELFT> &Obj;` This is kind of similar to `FileName` member which we have already:
it is also used to store a the file name which can be read from `Dumper->getElfObject()->getFileName()`.
I had to adjust the code which previously worked with a pointer to an object
and now works with a reference.
In a follow-up I am going to try to get rid of `const ELFObjectFile<ELFT>` arguments
which are still passed to a set of functions.
Differential revision: https://reviews.llvm.org/D87040
Add support in llvm-readobj for displaying them and support in the
asm parsser, AArch64TargetStreamer and MCWin64EH for emitting them.
The directives for the remaining basic opcodes have names that
match the opcode in the documentation.
The directives for custom stack cases, that are named
MSFT_OP_TRAP_FRAME, MSFT_OP_MACHINE_FRAME, MSFT_OP_CONTEXT
and MSFT_OP_CLEAR_UNWOUND_TO_CALL, are given matching assembler
directive names that fit into the rest of the opcode naming;
.seh_trap_frame, .seh_context, .seh_clear_unwound_to_call
The opcode MSFT_OP_MACHINE_FRAME is mapped to the existing
opecode enum UOP_PushMachFrame that is used on x86_64, and also
uses the corresponding existing x86_64 directive name
.seh_pushframe.
Differential Revision: https://reviews.llvm.org/D86889
We have Error.cpp/.h which contains some code for working with error codes.
In fact we use Error/Expected<> almost everywhere already and we can get rid
of these files.
Note: a few places in the code used readobj specific error codes,
e.g. `return readobj_error::unknown_symbol`. But these codes are never really used,
i.e. the code checks the fact of a success/error call only.
So I've changes them to `return inconvertibleErrorCode()` for now.
It seems that these places probably should be converted to use `Error`/`Expected<>`.
Differential revision: https://reviews.llvm.org/D86772
This replaces `reportError` calls with `reportUniqueWarning` and improves testing
for the code that is related to stack sizes dumping.
Differential revision: https://reviews.llvm.org/D86783
Imagine we have an archive that has 3 objects in the following order:
<valid known object>,<unknown object> and <valid known object>.
Currently llvm-readelf/obj report an error and stops dumping in the middle.
This patch changes the error reported to warning.
Differential revision: https://reviews.llvm.org/D86771
We have a few helper functions like the following:
```
std::error_code create*Dumper(...)
```
In fact we do not need or want to use `std::error_code` and the code
can be simpler if we just return `std::unique_ptr<ObjDumper>`.
This patch does this change and refines the signature of `createDumper`
as well.
Differential revision: https://reviews.llvm.org/D86718
We have no tests for OS/ABI values specific to
EM_TI_C6000, ELFOSABI_AMDGPU_MESA3D and ELFOSABI_ARM machines.
Also, related arrays in the code are not grouped together.
(That is why such testing was missed I guess).
The patch fixes that all.
Differential revision: https://reviews.llvm.org/D86341
llvm-readobj crashes when `-S --section-symbols` is used
on an object that has no symbol table.
The patch fixes it.
Differential revision: https://reviews.llvm.org/D86520
Currently, when a program header type is unknown, we dont print anything:
```
ProgramHeader {
Type: (0x60000000)
```
With this patch the output will be:
```
ProgramHeader {
Type: Unknown (0x60000000)
```
It was discussed in D85526 and consistent with what we print for
'--sections' already, e.g.:
```
Section {
Name: .sec
Type: Unknown (0x7FFFFFFF)
}
```
Differential revision: https://reviews.llvm.org/D86213
This allows to get rid of "Invalid data was encountered while parsing the file"
error reported in cases when sh_size/sh_offset of sections are broken.
Differential revision: https://reviews.llvm.org/D86451
The code that reports "PT_DYNAMIC segment offset + size exceeds the size of the file"
has an issue: it is possible to bypass the validation by overflowing the size + offset result.
Differential revision: https://reviews.llvm.org/D85519
Currently we have `checkDRI` and two `createDRIFrom` methods which
are used to create `DynRegionInfo` objects.
And we have an issue: constructions like:
`ObjF->getELFFile()->base() + P->p_offset`
that are used in `createDRIFrom` functions might overflow.
I had to revert `D85519` which triggered such UBSan failure.
This NFC, simplifies and generalizes how we create `DynRegionInfo` objects.
It will allow us to introduce more/better validation checks in a single place.
It also will allow to change `createDRI` to return `Expected<>` so
that we will be able to stop using the `reportError`, which
is used inside currently, and have a warning instead.
Differential revision: https://reviews.llvm.org/D86297
This reverts commit 455d5a8a065b4b93df11d1696dc1546c403465a5.
It broke UBSan:
http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap-ubsan/builds/21386/steps/check-llvm%20ubsan/logs/stdio
/b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test:62:10: error: WARN3: expected string not found in input
# WARN3: error: '[[FILE]]': Invalid data was encountered while parsing the file
^
<stdin>:2:1: note: scanning from here
/b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp:1956:46: runtime error: addition of unsigned offset to 0x0000020c5b30 overflowed to 0x0000020c5b2f
^
<stdin>:2:1: note: with "FILE" equal to "/b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/test/tools/llvm-readobj/ELF/Output/malformed-pt-dynamic\\.test\\.tmp3"
/b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp:1956:46: runtime error: addition of unsigned offset to 0x0000020c5b30 overflowed to 0x0000020c5b2f
^
<stdin>:2:117: note: possible intended match here
/b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp:1956:46: runtime error: addition of unsigned offset to 0x0000020c5b30 overflowed to 0x0000020c5b2f
^
Input file: <stdin>
Check file: /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test
The code that reports "PT_DYNAMIC segment offset + size exceeds the size of the file"
has an issue: it is possible to bypass the validation by overflowing the size + offset result.
Differential revision: https://reviews.llvm.org/D85519
This fixes existent FIXMEs: we should not error out when unable to
find the number of relocations.
Differential revision: https://reviews.llvm.org/D85891
Splitted out from D85519.
Currently we report "PT_DYNAMIC segment offset + size exceeds the size of the file",
this changes it to
"PT_DYNAMIC segment offset (0x1234) + file size (0x5678) exceeds the size of the file (0x68ab)"
Differential revision: https://reviews.llvm.org/D85654
`getElfSegmentType` and `getElfPtType` are methods that are used for printing
segment types for LLVM and GNU styles accordingly.
This patch does a cleanup and simplification that allows to avoid
the code duplication and to get rid of one macro.
Differential revision: https://reviews.llvm.org/D85830
Specifying --headers is equivalent to setting --file-headers,
--program-headers and --section-headers at the same time.
The existent test case uses a precompiled object and doesn't test the
output properly. This patch fixes it.
Differential revision: https://reviews.llvm.org/D85832
This removes the last `unwrapOrError` call from the `printRelocationsHelper`.
There is a little additional complexity because of `SHT_RELR/SHT_ANDROID_RELR` sections.
Such sections contains only relative relocations and they do not have a
symbol table associated with them, hence we should not try to treat
their `sh_link` field as a reference to a symbol table.
Differential revision: https://reviews.llvm.org/D85430
It removes all `unwrapOrError` calls except the first one, which
is is bit different and can be removed separately.
Differential revision: https://reviews.llvm.org/D85303
It adds the proper warnings reporting and updates the mips-reginfo.test to
remove using of the precompiled binary.
Differential revision: https://reviews.llvm.org/D85511
Add support for constant MachO::CPU_SUBTYPE_ARM64_V8. This constant is
needed so as to match `llvm-libtool-darwin`'s behavior to that of
cctools' libtool when `-arch_only` flag is passed in on command line.
Reviewed by jhenderson, alexshap, smeenai
Differential Revision: https://reviews.llvm.org/D85041
The `decode_relrs` helper is declared as:
`Expected<std::vector<Elf_Rel>> decode_relrs(Elf_Relr_Range relrs) const;`
it never returns an error though and hence can be simplified to return
a vector.
Differential revision: https://reviews.llvm.org/D85302
Currently, we only test the `--stackmap` option here:
https://github.com/llvm/llvm-project/blob/master/llvm/test/Object/stackmap-dump.test
it uses a precompiled MachO binary currently and I've found no tests for this option for ELF.
The implementation also has issues. For example, it might assert on a wrong version
of the .llvm-stackmaps section. Or it might crash on an empty or truncated section.
This patch introduces a new tools/llvm-readobj/ELF test file as well as implements a few
basic checks to catch simple crashes/issues
It also eliminates `unwrapOrError` calls in `printStackMap()`.
Differential revision: https://reviews.llvm.org/D85208
http://lab.llvm.org:8011/builders/clang-cmake-x86_64-avx2-linux/builds/15718/steps/build%20stage%201/logs/stdio:
FAILED: /usr/bin/c++ -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Itools/llvm-readobj -I/home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/tools/llvm-readobj -Iinclude -I/home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/include -march=broadwell -fPIC -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wno-maybe-uninitialized -Wdelete-non-virtual-dtor -Wno-comment -fdiagnostics-color -ffunction-sections -fdata-sections -O3 -fno-exceptions -fno-rtti -UNDEBUG -std=c++14 -MD -MT tools/llvm-readobj/CMakeFiles/llvm-readobj.dir/ELFDumper.cpp.o -MF tools/llvm-readobj/CMakeFiles/llvm-readobj.dir/ELFDumper.cpp.o.d -o tools/llvm-readobj/CMakeFiles/llvm-readobj.dir/ELFDumper.cpp.o -c /home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp
/home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp: In function ‘llvm::Expected<const llvm::object::Elf_Mips_Options<ELFT>*> readMipsOptions(const uint8_t*, llvm::ArrayRef<unsigned char>&, bool&)’:
/home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp:3374:12: error: parse error in template argument list
if (O->size < ExpectedSize)
Note: I played with godbolt.org and was able to catch the similar "error in template argument list" error when used gcc 4.9.0 with this code.
Fix: try to introduce a variable to store `O->size`, it helped to me in godbolt.
http://lab.llvm.org:8011/builders/clang-cmake-x86_64-avx2-linux/builds/15710/steps/build%20stage%201/logs/stdio
fails with:
/home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp: In function ‘llvm::Expected<const llvm::object::Elf_Mips_Options<ELFT>*> readMipsOptions(const uint8_t*, llvm::ArrayRef<unsigned char>&, bool&)’:
/home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp:3373:19: error: the value of ‘ExpectedSize’ is not usable in a constant expression
if (O->size < ExpectedSize)
^
/home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp:3369:10: note: ‘size_t ExpectedSize’ is not const
size_t ExpectedSize =
^
/home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp:3373:12: error: parse error in template argument list
if (O->size < ExpectedSize)
^
/home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp: In instantiation of ‘llvm::Expected<const llvm::object::Elf_Mips_Options<ELFT>*> readMipsOptions(const uint8_t*, llvm::ArrayRef<unsigned char>&, bool&) [with ELFT = llvm::object::ELFType<(llvm::support::endianness)0u, true>; uint8_t = unsigned char]’:
/home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp:3400:30: required from ‘void {anonymous}::ELFDumper<ELFT>::printMipsOptions() [with ELFT = llvm::object::ELFType<(llvm::support::endianness)0u, true>]’
/home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp:2878:21: required from ‘void {anonymous}::ELFDumper<ELFT>::printArchSpecificInfo() [with ELFT = llvm::object::ELFType<(llvm::support::endianness)0u, true>]’
/home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp:6999:1: required from here
/home/ssglocal/clang-cmake-x86_64-avx2-linux/clang-cmake-x86_64-avx2-linux/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp:3373:5: error: ‘size’ is not a member template function
Fix: add 2 `const` words to variables.
`printMipsOptions()` and the test related has the following issues currently:
1) It does not check the value of Elf_Mips_Options<ELFT>::size field.
2) For ODK_REGINFO options it is possible to read past the end of buffer,
because there is no check against the `sizeof(Elf_Mips_RegInfo<ELFT>)`.
3) The error about the broken size is just printed to the standard output.
4) The binary input is used for the test.
5) There is no testing for multiple options in the .MIPS.options section,
though the code supports it.
6) Only llvm-readobj is tested, but not llvm-readelf.
7) "Unsupported MIPS options tag" message does not reveal the tag ID/name.
This patch fixes all of these points.
Differential revision: https://reviews.llvm.org/D84854
It turns out that findSectionByName can return
const Elf_Shdr * instead of Expected<>, because its
code never returns an error currently (it reports warnings instead).
Differential revision: https://reviews.llvm.org/D85135
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