This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC][PATCH] fix gdb segv when objfile can't be opened


On 10/19/2017 04:09 PM, Simon Marchi wrote:
> Indeed, "error" throws an exception.  You should be able at least to step into the error function (although it's not particularly useful nor interesting).  It is defined in common/errors.c.
>

Thanks.  I looked at the stack when stopped on 'error', and I see that
there is a TRY/CATCH in 'frame_unwind_try_unwinder'.  That doesn't
handle the exception, and just re-throws it.  It looks like the
exception is ultimately caught in 'print_stack_frame', which explains
why the stack frame is never printed when the exception is thrown
(although it's still unclear why the message passed to 'error' isn't
printed).

Here is the top half of the stack:

#0  gdb_bfd_map_section (sectp=0x31e4eb8, size=0x31ddc58) at gdb_bfd.c:708
#1  0x0000000000628b15 in dwarf2_read_section (objfile=0x31c0be0, info=0x31ddc48) at dwarf2read.c:2553
#2  0x0000000000628e8b in dwarf2_get_section_info (objfile=0x31c0be0, sect=DWARF2_EH_FRAME, sectp=0x31ddf20, bufp=0x31ddf10, sizep=0x31ddf18) at dwarf2read.c:2634
#3  0x0000000000611616 in dwarf2_build_frame_info (objfile=0x31c0be0) at dwarf2-frame.c:2222
#4  0x0000000000610262 in dwarf2_frame_find_fde (pc=0x7ffd1fc37ad0, out_offset=0x0) at dwarf2-frame.c:1707
#5  0x000000000060f874 in dwarf2_frame_sniffer (self=0xa2c480 <dwarf2_frame_unwind>, this_frame=0x2fceb60, this_cache=0x2fceb78) at dwarf2-frame.c:1337
#6  0x00000000006913cc in frame_unwind_try_unwinder (this_frame=0x2fceb60, this_cache=0x2fceb78, unwinder=0xa2c480 <dwarf2_frame_unwind>) at frame-unwind.c:106
#7  0x0000000000691598 in frame_unwind_find_by_frame (this_frame=0x2fceb60, this_cache=0x2fceb78) at frame-unwind.c:164
#8  0x000000000068fe3c in get_frame_type (frame=0x2fceb60) at frame.c:2625
#9  0x000000000077404e in print_frame_info (frame=0x2fceb60, print_level=0, print_what=SRC_AND_LOC, print_args=1, set_current_sal=1) at stack.c:795
#10 0x00000000007729b0 in print_stack_frame (frame=0x2fceb60, print_level=0, print_what=SRC_AND_LOC, set_current_sal=1) at stack.c:177
#11 0x00000000006d3ee5 in print_stop_location (ws=0x7ffd1fc37db0) at infrun.c:8041
#12 0x00000000006d3f5b in print_stop_event (uiout=0x30f1900) at infrun.c:8058
...

>> I was also
>> unable to figure out why the error message isn't displayed.  The new
>> reproducer shows this issue.  I wasn't sure if setting *size or even
>> descriptor->size was the right thing to do, but it seemed reasonable to
>> me since the comment in gdb_bfd.h states that this function updates
>> *size.  There's currently only one caller for 'gdb_bfd_map_section', so
>> I have no problem updating *size there if that is preferred.
> 
> Actually it says "If successful, the section data is returned and *SIZE is set to the size of the section data;".  And this is what I would generally expect from functions.  Unless stated otherwise, the value of output parameters should be considered undefined if the function failed.  So I would lean towards blaming the caller for not taking enough precautions.  It trusts that gdb_bfd_map_section won't fail.
>

I'm not sure how the gdb_bfd_map_section caller can pre-determine that
it will fail.  It looks like there may be situations where
gdb_bfd_map_section doesn't actually need to read the file, so that
would mean that simply checking if the object file is readable before
calling gdb_bfd_map_section might not be a good way to address this.
Outside of that, I don't see what pre-conditions I can check to
determine if gdb_bfd_map_section is going to fail in this case.  Do you
have any suggestions?

To add a little more info, the segfault happens after trying to run
'next' in the debugger after this error is thrown.  Here is a snippet of
the stack:

#0  0x000000000083b3e1 in bfd_getl32 (p=0x0) at libbfd.c:557
#1  0x000000000060fb3e in read_initial_length (abfd=0x31805e0, buf=0x0, bytes_read_ptr=0x7ffd1fc3797c) at dwarf2-frame.c:1482
#2  0x0000000000610592 in decode_frame_entry_1 (unit=0x31ddf40, start=0x0, eh_frame_p=1, cie_table=0x7ffd1fc37b00, fde_table=0x7ffd1fc37af0, entry_type=EH_CIE_OR_FDE_TYPE_ID) at dwarf2-frame.c:1792
#3  0x00000000006111b5 in decode_frame_entry (unit=0x31ddf40, start=0x0, eh_frame_p=1, cie_table=0x7ffd1fc37b00, fde_table=0x7ffd1fc37af0, entry_type=EH_CIE_OR_FDE_TYPE_ID) at dwarf2-frame.c:2090
#4  0x00000000006116d1 in dwarf2_build_frame_info (objfile=0x31c0be0) at dwarf2-frame.c:2247
#5  0x0000000000610262 in dwarf2_frame_find_fde (pc=0x7ffd1fc37d30, out_offset=0x2fcec58) at dwarf2-frame.c:1707
#6  0x000000000060ead3 in dwarf2_frame_cache (this_frame=0x2fceb60, this_cache=0x2fceb78) at dwarf2-frame.c:1000
#7  0x000000000060f2d7 in dwarf2_frame_this_id (this_frame=0x2fceb60, this_cache=0x2fceb78, this_id=0x2fcebc0) at dwarf2-frame.c:1198
#8  0x000000000068baab in compute_frame_id (fi=0x2fceb60) at frame.c:505
#9  0x000000000068bbf7 in get_frame_id (fi=0x2fceb60) at frame.c:537
#10 0x00000000006bee4e in step_command_fsm_prepare (sm=0x3175e10, skip_subroutines=1, single_inst=0, count=1, thread=0x3162ac0) at infcmd.c:1056
#11 0x00000000006bef73 in step_1 (skip_subroutines=1, single_inst=0, count_string=0x0) at infcmd.c:1096
#12 0x00000000006bed3f in next_command (count_string=0x0, from_tty=1) at infcmd.c:969
...

dwarf2_build_frame_info first checks if unit->dwarf_frame_size is
non-zero (it is), then it calls decode_frame_entry on
unit->dwarf_frame_buffer.  unit->dwarf_frame_buffer is null, which
triggers the segfault.  Adding checks in dwarf2_build_frame_info to
check that dwarf_frame_buffer is non-zero (which needs to be done in two
places) also prevents the crash.  However, this doesn't address the
issue that the stack frame info isn't printed when the initial
breakpoint is hit (because gdb_bfd_map_section throws an error).  It
would be nice if this could be gracefully handled so that the current
frame and source code line are printed instead of just dumping you back
to a (gdb) prompt without knowing where you are.  Since my patch changes
the error to a warning, and updates the size pointer, it fixes both of
these issues.

I can imagine two alternatives:

- Change the error to a warning, and make the caller of
  gdb_bfd_map_section check if the returned pointer is NULL, and if so
  set *size to 0.  This requires the ugly-ish early return that I had to
  add in gdb_bfd_map_section.
  
- Add a TRY/CATCH around dwarf2_read_section in dwarf2_get_section_info,
  that sets *sectp, *bufp, and *sizep to NULL.  I'm not sure if I should
  then re-throw the exception.

Thanks,
Mike


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]