Binutils with MCST patches
Go to file
Pedro Alves 1dc8686c48 Eliminate dwarf2_frame_cache recursion, don't unwind from the dwarf2 sniffer (move dwarf2_tailcall_sniffer_first elsewhere).
Two rationales, same patch.

TL;DR 1:

 dwarf2_frame_cache recursion is evil.  dwarf2_frame_cache calls
 dwarf2_tailcall_sniffer_first which then recurses into
 dwarf2_frame_cache.

TL;DR 2:

 An unwinder trying to unwind is evil.  dwarf2_frame_sniffer calls
 dwarf2_frame_cache which calls dwarf2_tailcall_sniffer_first which
 then tries to unwind the PC of the previous frame.

Avoid all that by deferring dwarf2_tailcall_sniffer_first until it's
really necessary.

Rationale 1
===========

A frame sniffer should not try to unwind, because that bypasses all
the validation checks done by get_prev_frame.  The UNWIND_SAME_ID
scenario is one such case where GDB is currently broken because (in
part) of this (the next patch adds a test that would fail without
this).

GDB goes into an infinite loop in value_fetch_lazy, here:

      while (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val))
	{
	  frame = frame_find_by_id (VALUE_FRAME_ID (new_val));
...
	  new_val = get_frame_register_value (frame, regnum);
	}

(top-gdb) bt
#0  value_fetch_lazy (val=0x11516d0) at ../../src/gdb/value.c:3510
#1  0x0000000000584bd8 in value_optimized_out (value=0x11516d0) at ../../src/gdb/value.c:1096
#2  0x00000000006fe7a1 in frame_register_unwind (frame=0x1492600, regnum=16, optimizedp=0x7fffffffcdec, unavailablep=0x7fffffffcde8, lvalp=0x7fffffffcdd8, addrp=
    0x7fffffffcde0, realnump=0x7fffffffcddc, bufferp=0x7fffffffce10 "@\316\377\377\377\177") at ../../src/gdb/frame.c:940
#3  0x00000000006fea3a in frame_unwind_register (frame=0x1492600, regnum=16, buf=0x7fffffffce10 "@\316\377\377\377\177") at ../../src/gdb/frame.c:990
#4  0x0000000000473b9b in i386_unwind_pc (gdbarch=0xf54660, next_frame=0x1492600) at ../../src/gdb/i386-tdep.c:1771
#5  0x0000000000601dfa in gdbarch_unwind_pc (gdbarch=0xf54660, next_frame=0x1492600) at ../../src/gdb/gdbarch.c:2870
#6  0x0000000000693db5 in dwarf2_tailcall_sniffer_first (this_frame=0x1492600, tailcall_cachep=0x14926f0, entry_cfa_sp_offsetp=0x7fffffffcf00)
    at ../../src/gdb/dwarf2-frame-tailcall.c:389
#7  0x0000000000690928 in dwarf2_frame_cache (this_frame=0x1492600, this_cache=0x1492618) at ../../src/gdb/dwarf2-frame.c:1245
#8  0x0000000000690f46 in dwarf2_frame_sniffer (self=0x8e4980, this_frame=0x1492600, this_cache=0x1492618) at ../../src/gdb/dwarf2-frame.c:1423
#9  0x000000000070203b in frame_unwind_find_by_frame (this_frame=0x1492600, this_cache=0x1492618) at ../../src/gdb/frame-unwind.c:112
#10 0x00000000006fd681 in get_frame_id (fi=0x1492600) at ../../src/gdb/frame.c:408
#11 0x00000000007006c2 in get_prev_frame_1 (this_frame=0xdc1860) at ../../src/gdb/frame.c:1826
#12 0x0000000000700b7a in get_prev_frame (this_frame=0xdc1860) at ../../src/gdb/frame.c:2056
#13 0x0000000000514588 in frame_info_to_frame_object (frame=0xdc1860) at ../../src/gdb/python/py-frame.c:322
#14 0x000000000051784c in bootstrap_python_frame_filters (frame=0xdc1860, frame_low=0, frame_high=-1) at ../../src/gdb/python/py-framefilter.c:1396
#15 0x0000000000517a6f in apply_frame_filter (frame=0xdc1860, flags=7, args_type=CLI_SCALAR_VALUES, out=0xed7a90, frame_low=0, frame_high=-1)
    at ../../src/gdb/python/py-framefilter.c:1492
#16 0x00000000005e77b0 in backtrace_command_1 (count_exp=0x0, show_locals=0, no_filters=0, from_tty=1) at ../../src/gdb/stack.c:1777
#17 0x00000000005e7c0f in backtrace_command (arg=0x0, from_tty=1) at ../../src/gdb/stack.c:1891
#18 0x00000000004e37a7 in do_cfunc (c=0xda4fa0, args=0x0, from_tty=1) at ../../src/gdb/cli/cli-decode.c:107
#19 0x00000000004e683c in cmd_func (cmd=0xda4fa0, args=0x0, from_tty=1) at ../../src/gdb/cli/cli-decode.c:1882
#20 0x00000000006f35ed in execute_command (p=0xcc66c2 "", from_tty=1) at ../../src/gdb/top.c:468
#21 0x00000000005f8853 in command_handler (command=0xcc66c0 "bt") at ../../src/gdb/event-top.c:435
#22 0x00000000005f8e12 in command_line_handler (rl=0xfe05f0 "@") at ../../src/gdb/event-top.c:632
#23 0x000000000074d2c6 in rl_callback_read_char () at ../../src/readline/callback.c:220
#24 0x00000000005f8375 in rl_callback_read_char_wrapper (client_data=0x0) at ../../src/gdb/event-top.c:164
#25 0x00000000005f876a in stdin_event_handler (error=0, client_data=0x0) at ../../src/gdb/event-top.c:375
#26 0x00000000005f72fa in handle_file_event (data=...) at ../../src/gdb/event-loop.c:768
#27 0x00000000005f67a3 in process_event () at ../../src/gdb/event-loop.c:342
#28 0x00000000005f686a in gdb_do_one_event () at ../../src/gdb/event-loop.c:406
#29 0x00000000005f68bb in start_event_loop () at ../../src/gdb/event-loop.c:431
#30 0x00000000005f83a7 in cli_command_loop (data=0x0) at ../../src/gdb/event-top.c:179
#31 0x00000000005eeed3 in current_interp_command_loop () at ../../src/gdb/interps.c:327
#32 0x00000000005ef8ff in captured_command_loop (data=0x0) at ../../src/gdb/main.c:267
#33 0x00000000005ed2f6 in catch_errors (func=0x5ef8e4 <captured_command_loop>, func_args=0x0, errstring=0x8b6554 "", mask=RETURN_MASK_ALL)
    at ../../src/gdb/exceptions.c:524
#34 0x00000000005f0d21 in captured_main (data=0x7fffffffd9e0) at ../../src/gdb/main.c:1067
#35 0x00000000005ed2f6 in catch_errors (func=0x5efb9b <captured_main>, func_args=0x7fffffffd9e0, errstring=0x8b6554 "", mask=RETURN_MASK_ALL)
    at ../../src/gdb/exceptions.c:524
#36 0x00000000005f0d57 in gdb_main (args=0x7fffffffd9e0) at ../../src/gdb/main.c:1076
#37 0x000000000045bb6a in main (argc=4, argv=0x7fffffffdae8) at ../../src/gdb/gdb.c:34
(top-gdb)

GDB is trying to unwind the PC register of the previous frame (frame
#5 above), starting from the frame being sniffed (the THIS frame).
But the THIS frame's unwinder says the PC of the previous frame is
actually the same as the previous's frame's next frame (which is the
same frame we started with, the THIS frame), therefore it returns an
lval_register lazy value with frame set to THIS frame.  And so the
value_fetch_lazy loop never ends.


Rationale 2
===========

As an experiment, I tried making dwarf2-frame.c:read_addr_from_reg use
address_from_register.  That caused a bunch of regressions, but it
actually took me a long while to figure out what was going on.  Turns
out dwarf2-frame.c:read_addr_from_reg is called while computing the
frame's CFA, from within dwarf2_frame_cache.  address_from_register
wants to create a register with frame_id set to the frame being
constructed.  To create the frame id, we again call dwarf2_frame_cache,
which given:

static struct dwarf2_frame_cache *
dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
{
...
  if (*this_cache)
    return *this_cache;

returns an incomplete object to the caller:
static void
dwarf2_frame_this_id (struct frame_info *this_frame, void **this_cache,
		      struct frame_id *this_id)
{
  struct dwarf2_frame_cache *cache =
    dwarf2_frame_cache (this_frame, this_cache);
...
 (*this_id) = frame_id_build (cache->cfa, get_frame_func (this_frame));
}

As cache->cfa is still 0 (we were trying to compute it!), and
get_frame_id recalls this id from here on, we end up with a broken
frame id in recorded for this frame.  Later, when inspecting locals,
the dwarf machinery needs to know the selected frame's base, which
calls get_frame_base:

CORE_ADDR
get_frame_base (struct frame_info *fi)
{
  return get_frame_id (fi).stack_addr;
}

which as seen above then returns 0 ...

So I gave up using address_from_register.

But, the pain of investigating this made me want to have GDB itself
assert that recursion never happens here.  So I wrote a patch to do
that.  But, it triggers on current mainline, because
dwarf2_tailcall_sniffer_first, called from dwarf2_frame_cache, unwinds
the this_frame.

A sniffer shouldn't be trying to unwind, exactly because of this sort
of tricky issue.  The patch defers calling
dwarf2_tailcall_sniffer_first until it's really necessary, in
dwarf2_frame_prev_register (thus actually outside the sniffer path).
As this makes the call to dwarf2_frame_sniffer in dwarf2_frame_cache
unnecessary again, the patch removes that too.

Tested on x86_64 Fedora 17.

gdb/
2013-11-22  Pedro Alves  <palves@redhat.com>

	PR 16155
	* dwarf2-frame.c (struct dwarf2_frame_cache)
	<checked_tailcall_bottom, entry_cfa_sp_offset,
	entry_cfa_sp_offset_p>: New fields.
	(dwarf2_frame_cache): Adjust to use the new cache fields instead
	of locals.  Don't call dwarf2_tailcall_sniffer_first here.
	(dwarf2_frame_prev_register): Call it here, but only once.
2013-11-22 13:41:59 +00:00
bfd daily update 2013-11-22 09:32:36 +10:30
binutils Fix version.dll binutils test on non native platforms 2013-11-21 12:04:36 +01:00
config config/ * picflag.m4 (m68k-*-*): Use default PIC flag. 2013-11-21 10:50:04 -07:00
cpu
elfcpp Add R_X86_64_PC32_BND/R_X86_64_PLT32_BND suppor to gold 2013-11-18 09:55:09 -08:00
etc
gas gas/testsuite/ 2013-11-20 11:22:53 +00:00
gdb Eliminate dwarf2_frame_cache recursion, don't unwind from the dwarf2 sniffer (move dwarf2_tailcall_sniffer_first elsewhere). 2013-11-22 13:41:59 +00:00
gold Add R_X86_64_PC32_BND/R_X86_64_PLT32_BND suppor to gold 2013-11-18 09:55:09 -08:00
gprof * gprof.c (inline_file_names): New variable. 2013-11-21 13:13:06 +00:00
include gas/testsuite/ 2013-11-20 11:22:53 +00:00
intl
ld * scripttempl/avr.sc: Set .data section's LMA to next available 2013-11-22 12:00:55 +00:00
libdecnumber
libiberty config/ * picflag.m4 (m68k-*-*): Use default PIC flag. 2013-11-21 10:50:04 -07:00
opcodes gas/testsuite/ 2013-11-20 11:22:53 +00:00
readline
sim sim/ChangeLog: Correct bug number in previous commit. 2013-11-07 16:14:51 +00:00
texinfo
.cvsignore
.gitignore
ChangeLog Fix ChangeLog entries from earlier commit. 2013-11-11 15:34:48 -08:00
compile
config-ml.in
config.guess
config.rpath
config.sub
configure Disable libcilkrts when C++ is not used. 2013-11-08 11:11:42 -07:00
configure.ac Disable libcilkrts when C++ is not used. 2013-11-08 11:11:42 -07:00
COPYING
COPYING3
COPYING3.LIB
COPYING.LIB
COPYING.LIBGLOSS
COPYING.NEWLIB
depcomp
djunpack.bat
install-sh
libtool.m4
lt~obsolete.m4
ltgcc.m4
ltmain.sh
ltoptions.m4
ltsugar.m4
ltversion.m4
MAINTAINERS
Makefile.def Added Cilk runtime library (libcilkrts) into GCC. 2013-11-08 11:11:41 -07:00
Makefile.in * Makefile.in: Regenerate. 2013-11-08 11:11:42 -07:00
Makefile.tpl * Makefile.tpl: Fix typo. * Makefile.in: Regenerate. 2013-11-08 11:11:42 -07:00
makefile.vms
missing
mkdep
mkinstalldirs
move-if-change
README
README-maintainer-mode
setup.com
src-release
symlink-tree
ylwrap

		   README for GNU development tools

This directory contains various GNU compilers, assemblers, linkers, 
debuggers, etc., plus their support routines, definitions, and documentation.

If you are receiving this as part of a GDB release, see the file gdb/README.
If with a binutils release, see binutils/README;  if with a libg++ release,
see libg++/README, etc.  That'll give you info about this
package -- supported targets, how to use it, how to report bugs, etc.

It is now possible to automatically configure and build a variety of
tools with one command.  To build all of the tools contained herein,
run the ``configure'' script here, e.g.:

	./configure 
	make

To install them (by default in /usr/local/bin, /usr/local/lib, etc),
then do:
	make install

(If the configure script can't determine your type of computer, give it
the name as an argument, for instance ``./configure sun4''.  You can
use the script ``config.sub'' to test whether a name is recognized; if
it is, config.sub translates it to a triplet specifying CPU, vendor,
and OS.)

If you have more than one compiler on your system, it is often best to
explicitly set CC in the environment before running configure, and to
also set CC when running make.  For example (assuming sh/bash/ksh):

	CC=gcc ./configure
	make

A similar example using csh:

	setenv CC gcc
	./configure
	make

Much of the code and documentation enclosed is copyright by
the Free Software Foundation, Inc.  See the file COPYING or
COPYING.LIB in the various directories, for a description of the
GNU General Public License terms under which you can copy the files.

REPORTING BUGS: Again, see gdb/README, binutils/README, etc., for info
on where and how to report problems.