Bug 218395 - readelf --debug-dump=loc dumps core when inspecting various ar archives
Summary: readelf --debug-dump=loc dumps core when inspecting various ar archives
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: CURRENT
Hardware: amd64 Any
: --- Affects Some People
Assignee: Ed Maste
URL: https://sourceforge.net/p/elftoolchai...
Keywords:
Depends on:
Blocks:
 
Reported: 2017-04-05 11:16 UTC by Fabian Keil
Modified: 2017-08-30 11:12 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Fabian Keil 2017-04-05 11:16:59 UTC
A recent rebase on FreeBSD 11-STABLE resulted in unexpected
binary changes for ElectroBSD.

Trying diffoscope to look into this triggered a readelf coredump.

The core dump is reproducible with vanilla FreeBSD as well.
Using the FreeBSD 11.0-STABLE #0 r315855 amd64 snapshot:

# readelf --wide --debug-dump=loc /usr/lib/libc_pic.a

File: /usr/lib/libc_pic.a(machdep_ldisx.pico)

Contents of section .debug_loc:
    Offset   Begin    End      Expression
    00000000 00000000 00000018 (DW_OP_reg5 (rdi))
    00000000 00000018 00000073 (DW_OP_reg15 (r15))
    00000000 00000075 0000007c (DW_OP_reg15 (r15))
    00000000 <End of list>
    00000049 00000000 00000015 (DW_OP_reg4 (rsi))
    00000049 00000015 00000071 (DW_OP_reg14 (r14))
    00000049 00000075 0000007c (DW_OP_reg14 (r14))
    00000049 <End of list>
    00000092 00000000 00000012 (DW_OP_reg1 (rdx))
    00000092 00000012 00000039 (DW_OP_reg3 (rbx))
    00000092 0000003b 00000042 (DW_OP_reg3 (rbx))
    00000092 00000047 0000006d (DW_OP_reg3 (rbx))
    00000092 00000075 0000007c (DW_OP_reg3 (rbx))
    00000092 <End of list>
    00000101 00000027 00000039 (DW_OP_reg3 (rbx))
    00000101 0000003b 00000042 (DW_OP_reg3 (rbx))
    00000101 <End of list>
    00000137 0000005e 0000007c (DW_OP_nop)
    00000137 <End of list>

File: /usr/lib/libc_pic.a(bt_close.pico)

Contents of section .debug_loc:
    Offset   Begin    End      Expression
    00000000 00000000 0000000d (DW_OP_reg5 (rdi))
    00000000 0000000d 000000d7 (DW_OP_reg14 (r14))
    00000000 <End of list>
    00000036 00000011 000000d5 (DW_OP_reg3 (rbx))
    00000036 <End of list>
    00000049 <End of list>
    00000059 000000b0 000000cd (DW_OP_reg15 (r15); DW_OP_piece: 4)
    00000059 <End of list>
    0000007e 000000e0 000000f9 (DW_OP_reg5 (rdi))
    0000007e <End of list>
readelf: dwarf_loclist_n failed: Loclist section too short [_dwarf_loclist_add_locdesc(68)]
    000000a1 000000e0 000000e9 (DW_OP_reg4 (rsi); DW_OP_piece: 4)
    000000a1 000000e9 0000011d (DW_OP_reg3 (rbx); DW_OP_piece: 4)
    000000a1 00000121 000001bd (DW_OP_reg3 (rbx); DW_OP_piece: 4)
    000000a1 <End of list>
    000000f0 000000ed 0000011f (DW_OP_reg14 (r14))
    000000f0 00000121 000001bd (DW_OP_reg14 (r14))
    000000f0 <End of list>
Assertion failed: (in_len > 0), function _dwarf_loc_fill_locdesc, file /usr/src/contrib/elftoolchain/libdwarf/libdwarf_loc.c, line 627.
Abort trap (core dumped)

The FreeBSD 12.0-CURRENT #0 r315864 amd64 snapshot can be used to reproduce the
issue as well.

Manually trying the command on various other ar files triggers the same assertion.

Trying to paper over the issue with:

--- a/contrib/elftoolchain/libdwarf/libdwarf_loclist.c
+++ b/contrib/elftoolchain/libdwarf/libdwarf_loclist.c
@@ -63,7 +63,7 @@ _dwarf_loclist_add_locdesc(Dwarf_Debug dbg, Dwarf_CU cu, Dwarf_Section *ds,
 
                /* Otherwise it's normal entry. */
                len = dbg->read(ds->ds_data, off, 2);
-               if (*off + len > ds->ds_size) {
+               if (len <= 0 || *off + len > ds->ds_size) {
                        DWARF_SET_ERROR(dbg, error,
                            DW_DLE_DEBUG_LOC_SECTION_SHORT);
                        return (DW_DLE_DEBUG_LOC_SECTION_SHORT);

didn't work as it results in SIGBUS crashes later on.

I suspect that architectures other than amd64 are affected as well but did not confirm this.
Comment 1 Ed Maste freebsd_committer 2017-04-05 14:33:41 UTC
Thank you for the report. Can you clarify what previous FreeBSD version you rebased from? Specifically, I'd like to know if you were previously based on stable/10, in which case this would be a regression in ELF Tool Chain readelf compared to GNU binutils. If it's a rebase from an earlier stable/11 then it's a regression within ELF Tool Chain.
Comment 2 Fabian Keil 2017-04-05 18:14:10 UTC
Sorry for being vague. While I rebased from 11-STABLE r316168
to r316472, I don't expect this to be a recent regression.

I only run diffoscope on ElectroBSD in case of non-obvious
binary changes which rarely occur.

The bug is (probably) only triggered by ar files and I don't remember if I
ever used diffoscope to investigate ar file changes on 11-STABLE and
thus don't know if this ever worked on the 11 branch.

My oldest running ElectroBSD system is based on 11-STABLE r307312
and readelf is already broken there, but the crash occurs due to a SIGBUS
(when running against the system libc_pic.a):

[fk@elektrobier2 ~]$ readelf --wide --debug-dump=loc /usr/lib/libc_pic.a

File: /usr/lib/libc_pic.a(bt_close.So)

Contents of section .debug_loc:
    Offset   Begin    End      Expression
    00000000 00000000 0000000d (DW_OP_reg5 (rdi))
    00000000 0000000d 000000d7 (DW_OP_reg14 (r14))
    00000000 <End of list>
    00000036 00000011 000000d5 (DW_OP_reg3 (rbx))
    00000036 <End of list>
    00000059 000000b0 000000cd (DW_OP_reg15 (r15); DW_OP_piece: 4)
    00000059 <End of list>
    0000007e 000000e0 000000f9 (DW_OP_reg5 (rdi))
    0000007e <End of list>
    000000a1 000000e0 000000e9 (DW_OP_reg4 (rsi); DW_OP_piece: 4)
    000000a1 000000e9 000001b3 (DW_OP_reg3 (rbx); DW_OP_piece: 4)
    000000a1 <End of list>
    000000db 000000ed 000001b5 (DW_OP_reg14 (r14))
    000000db <End of list>
    000000fe 000000ed 000001b5 (DW_OP_reg14 (r14))
    000000fe <End of list>
    00000121 00000144 00000198 (DW_OP_reg0 (rax))
    00000121 <End of list>
    00000144 0000014e 00000155 (DW_OP_constu: 340322; DW_OP_constu: 3)
    00000144 00000155 0000015c (DW_OP_constu: 340322; DW_OP_constu: 3; DW_OP_piece: 4; DW_OP_reg2 (rcx); DW_OP_piece: 4)
    00000144 0000015c 00000163 (DW_OP_constu: 340322; DW_OP_constu: 3; DW_OP_reg1 (rdx); DW_OP_piece: 4; DW_OP_reg2 (rcx); DW_OP_piece: 4)
    00000144 00000163 0000016f (DW_OP_constu: 340322; DW_OP_constu: 3; DW_OP_reg1 (rdx); DW_OP_piece: 4; DW_OP_reg2 (rcx); DW_OP_piece: 4; DW_OP_reg4 (rsi); DW_OP_piece: 4)
    00000144 0000016f 0000018b (DW_OP_constu: 340322; DW_OP_constu: 3; DW_OP_reg1 (rdx); DW_OP_piece: 4; DW_OP_reg2 (rcx); DW_OP_piece: 4; DW_OP_reg4 (rsi); DW_OP_piece: 4; DW_OP_reg5 (rdi); DW_OP_piece: 4)
    00000144 <End of list>
    000001ec 000001a2 000001b0 (DW_OP_reg2 (rcx); DW_OP_piece: 4)
    000001ec <End of list>

File: /usr/lib/libc_pic.a(bt_conv.So)

Contents of section .debug_loc:
    Offset   Begin    End      Expression
Bus error (core dumped)

I intend to try a couple of older builds tomorrow to see if I
find a revision where readelf works as expected.
Comment 3 Ed Maste freebsd_committer 2017-04-05 18:32:06 UTC
Thank you for the update. I wouldn't be surprised to find that this has never worked on stable/11.

I've submitted an ELF Tool Chain ticket to track this as well (#549, in the URL field of this bug).
Comment 4 Fabian Keil 2017-04-06 12:05:28 UTC
I tried an old ElectroBSD memstick image based on FreeBSD 11.0-CURRENT from May 2015.

It comes with "readelf (elftoolchain r3179M)" which does not crash
with the local /usr/lib/libc_pic.a (compiled with "clang version 3.6.0
(tags/RELEASE_360/final 230434) 20150225)") but all the .debug_loc
sections are shown without content:

----------------
# readelf  --debug-dump=loc /usr/lib/libc_pic.a
[...]
File: /usr/lib/libc_pic.a(wmemcpy.So)

Contents of section .debug_loc:

File: /usr/lib/libc_pic.a(wmemmove.So)

Contents of section .debug_loc:

File: /usr/lib/libc_pic.a(wmemset.So)

Contents of section .debug_loc:
----------------

With the libc_pic.a version built with "clang version 3.9.1 (tags/RELEASE_391/final 289601)
(based on LLVM 3.9.1)" from an ElectroBSD system based on FreeBSD 11-STABLE r313908
readelf crashes due to SIGBUS:

---------------
# readelf  --debug-dump=loc /tmp/libc_pic.a 

File: /tmp/libc_pic.a(machdep_ldisx.pico)

Contents of section .debug_loc:
    Offset   Begin    End      Expression
    00000000 00000000 00000018 (DW_OP_reg5 (rdi))
    00000000 00000018 00000073 (DW_OP_reg15 (r15))
    00000000 00000075 0000007c (DW_OP_reg15 (r15))
    00000000 <End of list>
    00000049 00000000 00000015 (DW_OP_reg4 (rsi))
    00000049 00000015 00000071 (DW_OP_reg14 (r14))
    00000049 00000075 0000007c (DW_OP_reg14 (r14))
    00000049 <End of list>
    00000092 00000000 00000012 (DW_OP_reg1 (rdx))
    00000092 00000012 00000039 (DW_OP_reg3 (rbx))
    00000092 0000003b 00000042 (DW_OP_reg3 (rbx))
    00000092 00000047 0000006d (DW_OP_reg3 (rbx))
    00000092 00000075 0000007c (DW_OP_reg3 (rbx))
    00000092 <End of list>
    00000101 00000027 00000039 (DW_OP_reg3 (rbx))
    00000101 0000003b 00000042 (DW_OP_reg3 (rbx))
    00000101 <End of list>
    00000137 0000005e 0000007c (DW_OP_nop)
    00000137 <End of list>

File: /tmp/libc_pic.a(bt_close.pico)

Contents of section .debug_loc:
    Offset   Begin    End      Expression
Bus error (core dumped)
---------------

There's a noticeable size difference so it's conceivable that
the 2015 libc_pic.a simply does not contain .debug_loc sections:

---------------
# ls -lh /tmp/libc_pic.a /usr/lib/libc_pic.a 
-r--r--r--  1 root  wheel    13M Apr  6 13:40 /tmp/libc_pic.a
-r--r--r--  1 root  wheel   4.4M May  9  2015 /usr/lib/libc_pic.a
---------------

I don't have a vanilla FreeBSD build from the same time frame
but suspect that it's readelf would behave similarly.
Comment 5 commit-hook freebsd_committer 2017-04-17 23:57:04 UTC
A commit references this bug:

Author: emaste
Date: Mon Apr 17 23:56:50 UTC 2017
New revision: 317075
URL: https://svnweb.freebsd.org/changeset/base/317075

Log:
  Update ELF Tool Chain to upstream r3520

  Highlights of changes between r3490 and r3520:

  - Improve C++ demangling
  - Improve compatibility with Binutils tools wrt. error messages
  - Handle additional types/sections/etc. in readelf and elfdump
  - addr2line, cxxfilt: use setvbuf to set line buffering for filter use

  PR:		218395
  MFC after:	2 weeks
  Relnotes:	Yes
  Sponsored by:	The FreeBSD Foundation

Changes:
_U  head/contrib/elftoolchain/
  head/contrib/elftoolchain/addr2line/addr2line.c
_U  head/contrib/elftoolchain/ar/
  head/contrib/elftoolchain/ar/os.FreeBSD.mk
  head/contrib/elftoolchain/common/elfdefinitions.h
  head/contrib/elftoolchain/cxxfilt/cxxfilt.c
  head/contrib/elftoolchain/elfcopy/main.c
  head/contrib/elftoolchain/elfcopy/os.FreeBSD.mk
  head/contrib/elftoolchain/elfcopy/pe.c
  head/contrib/elftoolchain/elfcopy/symbols.c
_U  head/contrib/elftoolchain/elfdump/
  head/contrib/elftoolchain/elfdump/elfdump.c
  head/contrib/elftoolchain/libdwarf/dwarf.h
  head/contrib/elftoolchain/libdwarf/dwarf_attrval.c
  head/contrib/elftoolchain/libdwarf/dwarf_attrval_signed.3
  head/contrib/elftoolchain/libdwarf/dwarf_dump.c
  head/contrib/elftoolchain/libelf/gelf_newehdr.3
  head/contrib/elftoolchain/libelf/gelf_newphdr.3
  head/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3
  head/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c
  head/contrib/elftoolchain/libelftc/libelftc_dem_arm.c
  head/contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c
  head/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c
  head/contrib/elftoolchain/nm/nm.c
  head/contrib/elftoolchain/readelf/readelf.c
  head/contrib/elftoolchain/strings/strings.c
Comment 6 Ed Maste freebsd_committer 2017-04-18 02:49:40 UTC
This should now be fixed by r317075 in HEAD and will be MFC'd in due course.
Comment 7 Fabian Keil 2017-04-26 10:58:26 UTC
Importing r317075/ffb40783fd indeed fixed the issue. Thanks.
Comment 8 Fabian Keil 2017-08-30 11:12:19 UTC
The fix was MFC'd in r317623/f0bd9b16b.