binutils-gdb/gdb/frame-unwind.c
Simon Marchi 8efaf6b352 gdb: make frame_unwind_got_optimized return a not_lval value
TLDR: frame_unwind_got_optimized uses wrong frame id value, trying to
fix it makes GDB sad, return not_lval value and don't use frame id value
instead.

Longer version:

The `prev_register` method of the `frame_unwind` interface corresponds
to asking the question: "where did this frame - passed as a parameter -
save the value this register had in its caller frame?".  When "this
frame" did not save that register value (DW_CFA_undefined in DWARF), the
implementation can use the `frame_unwind_got_optimized` function to
create a struct value that represents the optimized out / not saved
register.

`frame_unwind_got_optimized` marks the value as fully optimized out,
sets the lval field to lval_register and assigns the required data for
lval_register: the next frame id and the register number.  The problem
is that it uses the frame id from the wrong frame (see below for in
depth explanation).  In practice, this is not problematic because the
frame id is never used: the value is already not lazy (and is marked as
optimized out), so the value is never fetched from the target.

When trying to change it to put the right next frame id in the value, we
bump into problems: computing the frame id for some frame requires
unwinding some register, if that register is not saved / optimized out,
we try to get the frame id that we are currently computing.

This patch addresses the problem by changing
`frame_unwind_got_optimized` to return a not_lval value instead.  Doing
so, we don't need to put a frame id, so we don't hit that problem.  It
may seem like an unnecessary change today, because it looks like we're
fixing something that is not broken (from the user point of view).
However, the bug becomes user visible with the following patches, where
inline frames are involved.  I put this change in its own patch to keep
it logically separate.

Let's now illustrate how we are putting the wrong frame id in the value
returned by `frame_unwind_got_optimized`.  Let's assume this stack:

    frame #0
    frame #1
    frame #2
    frame #3

Let's suppose that we are calling `frame_unwind_register_value` with
frame #2 as the "next_frame" parameter and some register number X as the
regnum parameter.  That is like asking the question "where did frame #2
save frame #3's value for register X".

`frame_unwind_register_value` calls the frame unwinder's `prev_register`
method, which in our case is `dwarf2_frame_prev_register`.  Note that in
`dwarf2_frame_prev_register`, the parameter is now called `this_frame`,
but its value is still frame #2, and we are still looking for where
frame #2 saved frame #3's value of register X.

Let's now suppose that frame #2's CFI explicitly indicates that the
register X is was not saved (DW_CFA_undefined).  We go into
`frame_unwind_got_optimized`.

In `frame_unwind_got_optimized`, the intent is to create a value that
represents register X in frame #3.  An lval_register value requires that
we specify the id of the _next_ frame, that is the frame from which we
would need to unwind in order to get the value.  Therefore, we would
want to put the id of frame #2 in there.

However, `frame_unwind_got_optimized` does:

    VALUE_NEXT_FRAME_ID (val)
      = get_frame_id (get_next_frame_sentinel_okay (frame));

where `frame` is frame #2.  The get_next_frame_sentinel_okay call
returns frame #1, so we end up putting frame #1's id in the value.

Let's now pretend that we try to "fix" it by placing the right frame id,
in other words doing this change:

    --- a/gdb/frame-unwind.c
    +++ b/gdb/frame-unwind.c
    @@ -260,8 +260,7 @@ frame_unwind_got_optimized (struct frame_info *frame, int regnum)
       mark_value_bytes_optimized_out (val, 0, TYPE_LENGTH (type));
       VALUE_LVAL (val) = lval_register;
       VALUE_REGNUM (val) = regnum;
    -  VALUE_NEXT_FRAME_ID (val)
    -    = get_frame_id (get_next_frame_sentinel_okay (frame));
    +  VALUE_NEXT_FRAME_ID (val) = get_frame_id (frame);
       return val;
     }

This makes some tests fails, such as gdb.dwarf2/dw2-undefined-ret-addr.exp,
like so:

    ...
    #9  0x0000557a8ab15a5d in internal_error (file=0x557a8b31ef80 "/home/simark/src/binutils-gdb/gdb/frame.c", line=623, fmt=0x557a8b31efe0 "%s: Assertion `%s' failed.") at /home/simark/src/binutils-gdb/gdbsupport/errors.cc:55
    #10 0x0000557a87f816d6 in get_frame_id (fi=0x62100034bde0) at /home/simark/src/binutils-gdb/gdb/frame.c:623
    #11 0x0000557a87f7cac7 in frame_unwind_got_optimized (frame=0x62100034bde0, regnum=16) at /home/simark/src/binutils-gdb/gdb/frame-unwind.c:264
    #12 0x0000557a87a71a76 in dwarf2_frame_prev_register (this_frame=0x62100034bde0, this_cache=0x62100034bdf8, regnum=16) at /home/simark/src/binutils-gdb/gdb/dwarf2/frame.c:1267
    #13 0x0000557a87f86621 in frame_unwind_register_value (next_frame=0x62100034bde0, regnum=16) at /home/simark/src/binutils-gdb/gdb/frame.c:1288
    #14 0x0000557a87f855d5 in frame_register_unwind (next_frame=0x62100034bde0, regnum=16, optimizedp=0x7fff5f459070, unavailablep=0x7fff5f459080, lvalp=0x7fff5f4590a0, addrp=0x7fff5f4590b0, realnump=0x7fff5f459090, bufferp=0x7fff5f459150 "") at /home/simark/src/binutils-gdb/gdb/frame.c:1191
    #15 0x0000557a87f860ef in frame_unwind_register (next_frame=0x62100034bde0, regnum=16, buf=0x7fff5f459150 "") at /home/simark/src/binutils-gdb/gdb/frame.c:1247
    #16 0x0000557a881875f9 in i386_unwind_pc (gdbarch=0x621000190110, next_frame=0x62100034bde0) at /home/simark/src/binutils-gdb/gdb/i386-tdep.c:1971
    #17 0x0000557a87fe58a5 in gdbarch_unwind_pc (gdbarch=0x621000190110, next_frame=0x62100034bde0) at /home/simark/src/binutils-gdb/gdb/gdbarch.c:3062
    #18 0x0000557a87a6267b in dwarf2_tailcall_sniffer_first (this_frame=0x62100034bde0, tailcall_cachep=0x62100034bee0, entry_cfa_sp_offsetp=0x7fff5f4593f0) at /home/simark/src/binutils-gdb/gdb/dwarf2/frame-tailcall.c:387
    #19 0x0000557a87a70cdf in dwarf2_frame_cache (this_frame=0x62100034bde0, this_cache=0x62100034bdf8) at /home/simark/src/binutils-gdb/gdb/dwarf2/frame.c:1198
    #20 0x0000557a87a711c2 in dwarf2_frame_this_id (this_frame=0x62100034bde0, this_cache=0x62100034bdf8, this_id=0x62100034be40) at /home/simark/src/binutils-gdb/gdb/dwarf2/frame.c:1226
    #21 0x0000557a87f81167 in compute_frame_id (fi=0x62100034bde0) at /home/simark/src/binutils-gdb/gdb/frame.c:587
    #22 0x0000557a87f81803 in get_frame_id (fi=0x62100034bde0) at /home/simark/src/binutils-gdb/gdb/frame.c:635
    #23 0x0000557a87f7efef in scoped_restore_selected_frame::scoped_restore_selected_frame (this=0x7fff5f459920) at /home/simark/src/binutils-gdb/gdb/frame.c:320
    #24 0x0000557a891488ae in print_frame_args (fp_opts=..., func=0x621000183b90, frame=0x62100034bde0, num=-1, stream=0x6030000caa20) at /home/simark/src/binutils-gdb/gdb/stack.c:750
    #25 0x0000557a8914e87a in print_frame (fp_opts=..., frame=0x62100034bde0, print_level=0, print_what=SRC_AND_LOC, print_args=1, sal=...) at /home/simark/src/binutils-gdb/gdb/stack.c:1394
    #26 0x0000557a8914c2ae in print_frame_info (fp_opts=..., frame=0x62100034bde0, print_level=0, print_what=SRC_AND_LOC, print_args=1, set_current_sal=1) at /home/simark/src/binutils-gdb/gdb/stack.c:1119
    ...

We end up calling get_frame_id (in the hunk above, frame #10)  while we are
computing it (frame #21), and that's not good.

Now, the question is how do we fix this.  I suggest making the unwinder
return a not_lval value in this case.

The reason why we return an lval_register here is to make sure that this
is printed as "not saved" and not "optimized out" down the line.  See
these two commits:

1. 901461f8eb ("Print registers not saved in the frame as "<not saved>"
   instead of "<optimized out>".").
2. 6bd273ae45 ("Make "set debug frame 1" output print <not saved> instead of
   <optimized out>.")

The current design (introduced by the first commit) is to check the
value's lval to choose which one to print (see val_print_optimized_out).

Making the unwinder return not_lval instead of lval_register doesn't
break "not saved" when doing "print $rax" or "info registers", because
value_fetch_lazy_register only consumes the contents and optimized-out
property from the value the unwinder returned.  The value being
un-lazified stays an lval_register.

I believe that this is a correct technical solution (and not just
papering over the problem), because what we expect of unwinders is to
tell us where a given register's value is saved.  If the value is saved
in memory, -> lval_memory.  If the value is saved in some other register
of the next frame, -> lval_register.  If the value is not saved, it
doesn't really make sense to return an lval_register value.  not_lval
would be more appropriate.  If the code then wants to represent an
optimized out register value (like value_fetch_lazy_register does), then
it's a separate concern which shouldn't involve the unwinder.

This change breaks the output of "set debug frame 1" though (introduced
by the second commit), since that logging statement consumes the return
value of the unwinder directly.  To keep the correct behavior, just make
`frame_unwind_register_value` call `val_print_not_saved` directly,
instead of `val_print_optimized_out`.  This is fine because we know in
this context that we are always talking about a register value, and that
we want to show "not saved" for those.

I augmented the gdb.dwarf2/dw2-reg-undefined.exp test case to test some
cases I stumbled on while working on this, which I think are not tested
anywhere:

- the "set debug frame 1" debug output mentioned above.  It's just debug
  output, but if we want to make sure it doesn't change, it should be
  tested
- printing not-saved register values from the history (should print not
  saved)
- copying a not-saved register value in a convenience variable.  In this
  case, we expect that printing the convenience variable shows
  "optimized out", because we copied the value, not the property of
  where the value came from.

gdb/ChangeLog:

	* frame-unwind.c (frame_unwind_got_optimized): Don't set
	regnum/frame in value.  Call allocate_value_lazy.
	* frame.c (frame_unwind_register_value): Use
	val_print_not_saved.

gdb/testsuite/ChangeLog:

	* gdb.dwarf2/dw2-reg-undefined.exp: Test "set debug frame 1"
	output, printing a "not saved" value from history and printing a
	convenience variable created from a "not saved" value.

Change-Id: If451739a3ef7a5b453b1f50707e21ce16d74807e
2020-08-31 13:22:54 -04:00

332 lines
10 KiB
C

/* Definitions for frame unwinder, for GDB, the GNU debugger.
Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "frame.h"
#include "frame-unwind.h"
#include "dummy-frame.h"
#include "inline-frame.h"
#include "value.h"
#include "regcache.h"
#include "gdb_obstack.h"
#include "target.h"
#include "gdbarch.h"
#include "dwarf2/frame-tailcall.h"
static struct gdbarch_data *frame_unwind_data;
struct frame_unwind_table_entry
{
const struct frame_unwind *unwinder;
struct frame_unwind_table_entry *next;
};
struct frame_unwind_table
{
struct frame_unwind_table_entry *list;
/* The head of the OSABI part of the search list. */
struct frame_unwind_table_entry **osabi_head;
};
/* A helper function to add an unwinder to a list. LINK says where to
install the new unwinder. The new link is returned. */
static struct frame_unwind_table_entry **
add_unwinder (struct obstack *obstack, const struct frame_unwind *unwinder,
struct frame_unwind_table_entry **link)
{
*link = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry);
(*link)->unwinder = unwinder;
return &(*link)->next;
}
static void *
frame_unwind_init (struct obstack *obstack)
{
struct frame_unwind_table *table
= OBSTACK_ZALLOC (obstack, struct frame_unwind_table);
/* Start the table out with a few default sniffers. OSABI code
can't override this. */
struct frame_unwind_table_entry **link = &table->list;
link = add_unwinder (obstack, &dummy_frame_unwind, link);
/* The DWARF tailcall sniffer must come before the inline sniffer.
Otherwise, we can end up in a situation where a DWARF frame finds
tailcall information, but then the inline sniffer claims a frame
before the tailcall sniffer, resulting in confusion. This is
safe to do always because the tailcall sniffer can only ever be
activated if the newer frame was created using the DWARF
unwinder, and it also found tailcall information. */
link = add_unwinder (obstack, &dwarf2_tailcall_frame_unwind, link);
link = add_unwinder (obstack, &inline_frame_unwind, link);
/* The insertion point for OSABI sniffers. */
table->osabi_head = link;
return table;
}
void
frame_unwind_prepend_unwinder (struct gdbarch *gdbarch,
const struct frame_unwind *unwinder)
{
struct frame_unwind_table *table
= (struct frame_unwind_table *) gdbarch_data (gdbarch, frame_unwind_data);
struct frame_unwind_table_entry *entry;
/* Insert the new entry at the start of the list. */
entry = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_table_entry);
entry->unwinder = unwinder;
entry->next = (*table->osabi_head);
(*table->osabi_head) = entry;
}
void
frame_unwind_append_unwinder (struct gdbarch *gdbarch,
const struct frame_unwind *unwinder)
{
struct frame_unwind_table *table
= (struct frame_unwind_table *) gdbarch_data (gdbarch, frame_unwind_data);
struct frame_unwind_table_entry **ip;
/* Find the end of the list and insert the new entry there. */
for (ip = table->osabi_head; (*ip) != NULL; ip = &(*ip)->next);
(*ip) = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_table_entry);
(*ip)->unwinder = unwinder;
}
/* Call SNIFFER from UNWINDER. If it succeeded set UNWINDER for
THIS_FRAME and return 1. Otherwise the function keeps THIS_FRAME
unchanged and returns 0. */
static int
frame_unwind_try_unwinder (struct frame_info *this_frame, void **this_cache,
const struct frame_unwind *unwinder)
{
int res = 0;
unsigned int entry_generation = get_frame_cache_generation ();
frame_prepare_for_sniffer (this_frame, unwinder);
try
{
res = unwinder->sniffer (unwinder, this_frame, this_cache);
}
catch (const gdb_exception &ex)
{
/* Catch all exceptions, caused by either interrupt or error.
Reset *THIS_CACHE, unless something reinitialized the frame
cache meanwhile, in which case THIS_FRAME/THIS_CACHE are now
dangling. */
if (get_frame_cache_generation () == entry_generation)
{
*this_cache = NULL;
frame_cleanup_after_sniffer (this_frame);
}
if (ex.error == NOT_AVAILABLE_ERROR)
{
/* This usually means that not even the PC is available,
thus most unwinders aren't able to determine if they're
the best fit. Keep trying. Fallback prologue unwinders
should always accept the frame. */
return 0;
}
throw;
}
if (res)
return 1;
else
{
/* Don't set *THIS_CACHE to NULL here, because sniffer has to do
so. */
frame_cleanup_after_sniffer (this_frame);
return 0;
}
gdb_assert_not_reached ("frame_unwind_try_unwinder");
}
/* Iterate through sniffers for THIS_FRAME frame until one returns with an
unwinder implementation. THIS_FRAME->UNWIND must be NULL, it will get set
by this function. Possibly initialize THIS_CACHE. */
void
frame_unwind_find_by_frame (struct frame_info *this_frame, void **this_cache)
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct frame_unwind_table *table
= (struct frame_unwind_table *) gdbarch_data (gdbarch, frame_unwind_data);
struct frame_unwind_table_entry *entry;
const struct frame_unwind *unwinder_from_target;
unwinder_from_target = target_get_unwinder ();
if (unwinder_from_target != NULL
&& frame_unwind_try_unwinder (this_frame, this_cache,
unwinder_from_target))
return;
unwinder_from_target = target_get_tailcall_unwinder ();
if (unwinder_from_target != NULL
&& frame_unwind_try_unwinder (this_frame, this_cache,
unwinder_from_target))
return;
for (entry = table->list; entry != NULL; entry = entry->next)
if (frame_unwind_try_unwinder (this_frame, this_cache, entry->unwinder))
return;
internal_error (__FILE__, __LINE__, _("frame_unwind_find_by_frame failed"));
}
/* A default frame sniffer which always accepts the frame. Used by
fallback prologue unwinders. */
int
default_frame_sniffer (const struct frame_unwind *self,
struct frame_info *this_frame,
void **this_prologue_cache)
{
return 1;
}
/* The default frame unwinder stop_reason callback. */
enum unwind_stop_reason
default_frame_unwind_stop_reason (struct frame_info *this_frame,
void **this_cache)
{
struct frame_id this_id = get_frame_id (this_frame);
if (frame_id_eq (this_id, outer_frame_id))
return UNWIND_OUTERMOST;
else
return UNWIND_NO_REASON;
}
/* See frame-unwind.h. */
CORE_ADDR
default_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
int pc_regnum = gdbarch_pc_regnum (gdbarch);
CORE_ADDR pc = frame_unwind_register_unsigned (next_frame, pc_regnum);
pc = gdbarch_addr_bits_remove (gdbarch, pc);
return pc;
}
/* See frame-unwind.h. */
CORE_ADDR
default_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
int sp_regnum = gdbarch_sp_regnum (gdbarch);
return frame_unwind_register_unsigned (next_frame, sp_regnum);
}
/* Helper functions for value-based register unwinding. These return
a (possibly lazy) value of the appropriate type. */
/* Return a value which indicates that FRAME did not save REGNUM. */
struct value *
frame_unwind_got_optimized (struct frame_info *frame, int regnum)
{
struct gdbarch *gdbarch = frame_unwind_arch (frame);
struct type *type = register_type (gdbarch, regnum);
return allocate_optimized_out_value (type);
}
/* Return a value which indicates that FRAME copied REGNUM into
register NEW_REGNUM. */
struct value *
frame_unwind_got_register (struct frame_info *frame,
int regnum, int new_regnum)
{
return value_of_register_lazy (frame, new_regnum);
}
/* Return a value which indicates that FRAME saved REGNUM in memory at
ADDR. */
struct value *
frame_unwind_got_memory (struct frame_info *frame, int regnum, CORE_ADDR addr)
{
struct gdbarch *gdbarch = frame_unwind_arch (frame);
struct value *v = value_at_lazy (register_type (gdbarch, regnum), addr);
set_value_stack (v, 1);
return v;
}
/* Return a value which indicates that FRAME's saved version of
REGNUM has a known constant (computed) value of VAL. */
struct value *
frame_unwind_got_constant (struct frame_info *frame, int regnum,
ULONGEST val)
{
struct gdbarch *gdbarch = frame_unwind_arch (frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
struct value *reg_val;
reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
store_unsigned_integer (value_contents_writeable (reg_val),
register_size (gdbarch, regnum), byte_order, val);
return reg_val;
}
struct value *
frame_unwind_got_bytes (struct frame_info *frame, int regnum, gdb_byte *buf)
{
struct gdbarch *gdbarch = frame_unwind_arch (frame);
struct value *reg_val;
reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
memcpy (value_contents_raw (reg_val), buf, register_size (gdbarch, regnum));
return reg_val;
}
/* Return a value which indicates that FRAME's saved version of REGNUM
has a known constant (computed) value of ADDR. Convert the
CORE_ADDR to a target address if necessary. */
struct value *
frame_unwind_got_address (struct frame_info *frame, int regnum,
CORE_ADDR addr)
{
struct gdbarch *gdbarch = frame_unwind_arch (frame);
struct value *reg_val;
reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
pack_long (value_contents_writeable (reg_val),
register_type (gdbarch, regnum), addr);
return reg_val;
}
void _initialize_frame_unwind ();
void
_initialize_frame_unwind ()
{
frame_unwind_data = gdbarch_data_register_pre_init (frame_unwind_init);
}