[Bug tools/22250] New: readelf should support --dwarf-start and --dwarf-depth
https://sourceware.org/bugzilla/show_bug.cgi?id=22250 Bug ID: 22250 Summary: readelf should support --dwarf-start and --dwarf-depth Product: elfutils Version: unspecified Status: NEW Severity: normal Priority: P2 Component: tools Assignee: unassigned at sourceware dot org Reporter: tromey at sourceware dot org CC: elfutils-devel at sourceware dot org Target Milestone: --- objdump supports --dwarf-start and --dwarf-depth options. --dwarf-start specifies the DIE at which to begin dumping. --dwarf-depth specifies how many levels down to print; if there are more levels it just prints "...", like: <0><2174>: Abbrev Number: 1 (DW_TAG_compile_unit) <2175> DW_AT_producer: (indirect string, offset: 0x0): clang LLVM (rustc version 1.20.0 (f3d6973f4 2017-08-27)) <2179> DW_AT_language: 28 (Unknown: 1c) <217b> DW_AT_name: (indirect string, offset: 0x1621): /checkout/src/libstd/lib.rs <217f> DW_AT_stmt_list : 0x9f2 <2183> DW_AT_comp_dir: (indirect string, offset: 0x163d): /checkout/obj <2187> DW_AT_low_pc : 0x0 <218f> DW_AT_ranges : 0x2be80 <1><2193>: ... These are handy for investigating large files with dwarf-mode that is in binutils. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug libdw/22252] New: Parallel parsing of CU's DIEs from libdw
https://sourceware.org/bugzilla/show_bug.cgi?id=22252 Bug ID: 22252 Summary: Parallel parsing of CU's DIEs from libdw Product: elfutils Version: unspecified Status: NEW Severity: normal Priority: P2 Component: libdw Assignee: unassigned at sourceware dot org Reporter: woodard at redhat dot com CC: elfutils-devel at sourceware dot org Target Milestone: --- To speed up the processing of large ELF files which are common in HPC please resolve the data races which prevent parallel parsing of CU's DIEs within ELF files. We'd like to do something like: for(Dwarf_Off cu_off = 0; dwarf_next_unit(dbg(), cu_off, &next_cu_header, &cu_header_length, NULL, &abbrev_offset, &addr_size, &offset_size, &type_signaturep, NULL) == 0; cu_off = next_cu_header) { if(!dwarf_offdie_types(dbg(), cu_off + cu_header_length, ¤t_cu_die)) continue; // Modified for parallelism: rather than a single DwarfWalker holding state, // create a new context and clone before we spawn a thread push(); DwarfWalker mod_walker(*this); pop(); bool ret = cilk_spawn mod_walker.parseModule(false, fixUnknownMod); //bool ret = parseModule(false, fixUnknownMod); if(!ret) { cilk_sync; return false; } compile_offset = next_cu_header; } cilk_sync; Code similar to this is being worked on for dyninst http://www.dyninst.org/ -- You are receiving this mail because: You are on the CC list for the bug.
Re: failed reading "Smallest x86 ELF Hello World"
On Thu, 2017-09-28 at 12:06 -0700, Josh Stone wrote: > From http://timelessname.com/elfbin/ > > Elfutils completely fails to read the file: > > $ eu-readelf --version > eu-readelf (elfutils) 0.169 > Copyright [...] > $ eu-readelf -a hello > eu-readelf: failed reading 'hello': invalid file descriptor > > It's not clear that we should care, since that page even says it's "a > completely corrupted x86 ELF Binary that still runs." But since it's > good enough for the kernel to run it, I'd hope for *something* from > tools. > > It also seems weird to get the message "invalid file descriptor", > from ELF_E_INVALID_FILE, which makes it sound like more like > EBADF. The file descriptor itself is fine - it just doesn't like the > ELF within. At first I though it was because eu-readelf uses libdwfl to get more information about the ELF file. To get all the data about the Dwfl_Modules we might hit some error that might not be relevant for the initial showing of data. But that isn't really it in this case. The first issue is indeed that almost anything that goes wrong when setting up the initial Elf handle ends up being described as ELF_E_INVALID_FILE. Which is not always the correct error code. So I introduced ELF_E_INVALID_ELF which indicates it is bad ELF data being encountered and not just the inability to read the data from the file descriptor. Also in a couple of cases we didn't explicitly set the libelf errno to indicate what really went wrong. I made sure we always do now. libelf: Add ELF_E_INVALID_ELF error value. This at least gives a nicer error message: eu-readelf: failed reading './hello': invalid ELF file data But while auditing this code it is clear we go out of our way to get the section (count) making sure we don't touch any bad data. If there is a change we might read anything bad from the (mmapped) file then we explicitly set the elf->state.elf[64|32].scns.cnt to zero. Which is respected throughout libelf whenever we try to touch section headers. Except... during the initial read we double check e_shoff is sane and error out early. Even though the code right below it explicitly doesn't use it when scncnt is zero. So we can fix this sanity check. libelf: Don't error out when sanity checking e_shoff if scncnt is zero. This then gives similar output to binutils readelf: ELF Header: Magic: 7f 45 4c 46 01 01 01 48 69 20 57 6f 72 6c 64 0a Class: ELF32 Data: 2's complement, little endian Ident Version: 1 (current) OS/ABI:: 72 ABI Version: 105 Type: EXEC (Executable file) Machine: Intel 80386 Version: 1 (current) Entry point address: 0x8048080 Start of program headers: 52 (bytes into file) Start of section headers: 309248 (bytes into file) Flags: 0x80cd Size of this header: 22763 (bytes) Size of program header entries:32 (bytes) Number of program headers entries: 2 Size of section header entries:40 (bytes) Number of section headers entries: 5 Section header string table index: 4 Section Headers: [Nr] Name Type Addr OffSize ES Flags Lk Inf Al Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x00 0x08048000 0x08048000 0xa2 0xa2 R E 0x1000 LOAD 0xa4 0x080490a4 0x080490a4 0x09 0x09 W 0x9007b900 Section to Segment mapping: Segment Sections... 00 01 Maybe it could be improved a little more by adding a warning that 5 section [headers] were expected, but none could be read. But I leave it at this for now. Cheers, Mark
[PATCH 1/2] libelf: Add ELF_E_INVALID_ELF error value.
Add ELF_E_INVALID_ELF which is set when the ELF file data is bad. This is different from ELF_E_INVALID_FILE which is set when the file could not be read. Signed-off-by: Mark Wielaard --- libelf/ChangeLog | 12 + libelf/elf_begin.c | 61 ++ libelf/elf_error.c | 7 +- libelf/elf_getshdrstrndx.c | 20 ++- libelf/libelfP.h | 1 + tests/ChangeLog| 4 +++ tests/msg_tst.c| 1 + 7 files changed, 83 insertions(+), 23 deletions(-) diff --git a/libelf/ChangeLog b/libelf/ChangeLog index 7bd9e1b..36b57dd 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,15 @@ +2017-10-04 Mark Wielaard + + * libelfP.h: Add ELF_E_INVALID_ELF to error values enum. + * elf_error.c (ELF_E_INVALID_ELF_IDX): New define. Use it as value + for ELF_E_INVALID_ELF in msgidx. + * elf_getshdrstrndx.c (elf_getshdrstrndx): Distinquish between pread + failing and not having enough data. + * elf_begin.c (get_shnum): Likewise. Explicitly set libelf errno on + too large value. + (file_read_elf): Make sure to always set libelf errno when returning + NULL. Distinquish between i/o file and elf data errors. + 2017-08-18 Ulf Hermann * gelf_xlate.c: Use attribute_packed. diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c index 6f85038..5545278 100644 --- a/libelf/elf_begin.c +++ b/libelf/elf_begin.c @@ -158,6 +158,7 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, else { Elf32_Word size; + ssize_t r; if (likely (map_address != NULL)) /* gcc will optimize the memcpy to a simple memory @@ -167,11 +168,19 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, + offset))->sh_size, sizeof (Elf32_Word)); else - if (unlikely (pread_retry (fildes, &size, sizeof (Elf32_Word), - offset + ehdr.e32->e_shoff - + offsetof (Elf32_Shdr, sh_size)) + if (unlikely ((r = pread_retry (fildes, &size, + sizeof (Elf32_Word), + offset + ehdr.e32->e_shoff + + offsetof (Elf32_Shdr, + sh_size))) != sizeof (Elf32_Word))) - return (size_t) -1l; + { + if (r < 0) + __libelf_seterrno (ELF_E_INVALID_FILE); + else + __libelf_seterrno (ELF_E_INVALID_ELF); + return (size_t) -1l; + } if (e_ident[EI_DATA] != MY_ELFDATA) CONVERT (size); @@ -207,6 +216,7 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, + offset))->sh_size; else { + ssize_t r; if (likely (map_address != NULL)) /* gcc will optimize the memcpy to a simple memory access while taking care of alignment issues. */ @@ -215,19 +225,30 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, + offset))->sh_size, sizeof (Elf64_Xword)); else - if (unlikely (pread_retry (fildes, &size, sizeof (Elf64_Xword), - offset + ehdr.e64->e_shoff - + offsetof (Elf64_Shdr, sh_size)) + if (unlikely ((r = pread_retry (fildes, &size, + sizeof (Elf64_Xword), + offset + ehdr.e64->e_shoff + + offsetof (Elf64_Shdr, + sh_size))) != sizeof (Elf64_Xword))) - return (size_t) -1l; + { + if (r < 0) + __libelf_seterrno (ELF_E_INVALID_FILE); + else + __libelf_seterrno (ELF_E_INVALID_ELF); + return (size_t) -1l; + } if (e_ident[EI_DATA] != MY_ELFDATA) CONVERT (size); } if (size > ~((GElf_Word) 0)) - /* Invalid value, it is too large. */ - return (size_t) -1l; + { + /* Invalid value, it is too large. */ + __libelf_seterrno (ELF_E_INVALID_ELF); + return (size_t) -1l; +
[PATCH 2/2] libelf: Don't error out when sanity checking e_shoff if scncnt is zero.
We won't use the e_shoff value in that case because we will set elf->state.elf[64|32].scns.cnt to zero to indicate not to read any section header data from the file. Signed-off-by: Mark Wielaard --- libelf/ChangeLog | 5 + libelf/elf_begin.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libelf/ChangeLog b/libelf/ChangeLog index 36b57dd..6aa1c6f 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,5 +1,10 @@ 2017-10-04 Mark Wielaard + * elf_begin.c (file_read_elf): Skip sanity checking e_shoff if scncnt + is zero, we won't use it then. + +2017-10-04 Mark Wielaard + * libelfP.h: Add ELF_E_INVALID_ELF to error values enum. * elf_error.c (ELF_E_INVALID_ELF_IDX): New define. Use it as value for ELF_E_INVALID_ELF in msgidx. diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c index 5545278..fb3a5b5 100644 --- a/libelf/elf_begin.c +++ b/libelf/elf_begin.c @@ -373,7 +373,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, || (((uintptr_t) ((char *) ehdr + e_shoff) & (__alignof__ (Elf32_Shdr) - 1)) == 0))) { - if (unlikely (e_shoff >= maxsize) + if (unlikely (scncnt > 0 && e_shoff >= maxsize) || unlikely (maxsize - e_shoff < scncnt * sizeof (Elf32_Shdr))) { @@ -475,7 +475,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, || (((uintptr_t) ((char *) ehdr + e_shoff) & (__alignof__ (Elf64_Shdr) - 1)) == 0))) { - if (unlikely (e_shoff >= maxsize) + if (unlikely (scncnt > 0 && e_shoff >= maxsize) || unlikely (maxsize - e_shoff < scncnt * sizeof (Elf64_Shdr))) goto free_and_out; -- 1.8.3.1
Re: missing #include in libdw.h?
On Tue, 2017-10-03 at 19:30 +, Bill Williams wrote: > libdw.h uses the DW_CIE_ID_64 define from dwarf.h in a macro > definition, but does not itself include dwarf.h. This makes the > libdw.h header not self-contained if and only if your code uses the > dwarf_cfi_cie_p macro. Is this behavior by design, or a bug? I don't think this is by design. It seems a bug nobody noticed before because people often do include dwarf.h also. But nothing else explicitly needs the dwarf.h constants. It would probably not break anything to explicitly include dwarf.h in libdw.h, but it seems better to just define this constant explicitly in libdw.h as the attached patch does. Does that make sense to you? Thanks, MarkFrom 251bb1c8c4a0a523791874c14826c391173bce4c Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 3 Oct 2017 23:08:01 +0200 Subject: [PATCH] libdw: Define LIBDW_CIE_ID and use it in dwarf_cfi_cie_p. dwarf_cfi_cie_p used DW_CIE_ID_64 from dwarf.h which meant you had to include dwarf.h just to use the dwarf_cfi_cie_p macros. Just define the constant as LIBDW_CIE_ID in libdw.h to keep it independent. Signed-off-by: Mark Wielaard --- libdw/ChangeLog | 4 libdw/libdw.h | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 94e9c9a..e6e7f3b 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,7 @@ +2017-10-03 Mark Wielaard + + * libdw.h: Define LIBDW_CIE_ID and use it in dwarf_cfi_cie_p. + 2017-08-18 Ulf Hermann * memory-access.h: Use attribute_packed. diff --git a/libdw/libdw.h b/libdw/libdw.h index 63a38ff..e42c087 100644 --- a/libdw/libdw.h +++ b/libdw/libdw.h @@ -211,7 +211,9 @@ typedef union Dwarf_FDE fde; } Dwarf_CFI_Entry; -#define dwarf_cfi_cie_p(entry) ((entry)->cie.CIE_id == DW_CIE_ID_64) +/* Same as DW_CIE_ID_64 from dwarf.h to keep libdw.h independent. */ +#define LIBDW_CIE_ID 0xULL +#define dwarf_cfi_cie_p(entry) ((entry)->cie.CIE_id == LIBDW_CIE_ID) /* Opaque type representing a frame state described by CFI. */ typedef struct Dwarf_Frame_s Dwarf_Frame; -- 1.8.3.1
[Bug general/22253] New: RFE elfutils add man pages documenting the API
https://sourceware.org/bugzilla/show_bug.cgi?id=22253 Bug ID: 22253 Summary: RFE elfutils add man pages documenting the API Product: elfutils Version: unspecified Status: NEW Severity: normal Priority: P2 Component: general Assignee: unassigned at sourceware dot org Reporter: woodard at redhat dot com CC: elfutils-devel at sourceware dot org Target Milestone: --- Currently all the documentation for the API for libelf and libdw is in the header files. The dyninst developers are currently porting their library to make use of it and have requested better documentation including information about which functions can be considered MT safe. -- You are receiving this mail because: You are on the CC list for the bug.