mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-25 16:57:52 +00:00
gdb/
* NEWS: Document inlined function support. * Makefile.in (SFILES): Add inline-frame.c. (COMMON_OBS): Add inline-frame.o. * block.c (contained_in): Rewrite to use lexical nesting. (block_linkage_function): Skip inlined function blocks. (block_inlined_p): New. * block.h (struct block): Update comment. (block_inlined_p): New prototype. * blockframe.c (get_frame_block): Handle inlined functions. (get_frame_function): Do not use block_linkage_function. (block_innermost_frame): Use get_frame_block and contained_in. * breakpoint.c (watchpoint_check): Remove extra reinit_frame_cache. Skip over inlined functions. Simplify epilogue check. (bpstat_check_breakpoint_conditions): Use get_stack_frame_id. Update comments. (set_momentary_breakpoint): Only accept non-inlined frames. (watch_command_1): Use frame_unwind_caller_pc and frame_unwind_caller_id instead of get_prev_frame. (until_break_command): Likewise. Use get_stack_frame_id. * buildsym.c (end_symtab): Set SYMBOL_SYMTAB for block functions. * dwarf2loc.c (dwarf_expr_frame_base): Use block_linkage_function. * dwarf2read.c (process_die): Handle DW_TAG_inlined_subroutine. (read_func_scope, new_symbol): Likewise. Handle arguments specially for inlined functions without call site information. (inherit_abstract_dies): Allow tag mismatch for inlined subroutines. (die_specification): Treat DW_AT_abstract_origin as a specification. (read_type_die): Handle DW_TAG_inlined_subroutine. * frame-unwind.c (frame_unwind_init): Add inline_frame_unwind. * frame.c (fprint_frame_id): Print inline depth. (fprint_frame_type): Handle INLINE_FRAME and SENTINEL_FRAME. (skip_inlined_frames, get_stack_frame_id): New. (frame_unwind_caller_id): Use skip_inlined_frames. (frame_id_inlined_p): New. (frame_id_eq): Make the logic match the comments. Add inline_depth check. (frame_id_inner): Handle inlined functions. (frame_unwind_pc): New function, copied from frame_unwind_caller_pc. (frame_unwind_caller_pc): Use skip_inlined_frames and frame_unwind_pc. (get_prev_frame_1): Check for inline frames. Split out frame allocation to get_prev_frame_raw. (get_prev_frame_raw): New function. (get_prev_frame): Handle inline frames. (get_frame_pc): Use frame_unwind_pc. (get_frame_address_in_block): Skip inlined frames on both sides. (pc_notcurrent): Delete. (find_frame_sal): Rewrite to handle inline call sites. Use get_frame_address_in_block. (deprecated_update_frame_pc_hack): Make static. * frame.h: Update comments. (struct frame_id): Add inline_depth. (enum frame_type): Add INLINE_FRAME. (frame_id_inlined_p, get_stack_frame_id): New prototypes. * gdbthread.h (struct thread_info): Add step_stack_frame_id field. * infcmd.c (set_step_frame): New function. (step_once): Use set_step_frame. Handle inlined functions. (until_next_command): Use set_step_frame. (finish_backward), finish_forward): Use get_stack_frame_id. (finish_command): Support inlined functions. * inferior.h (set_step_info): New prototype. * infrun.c (RESUME_ALL): Use minus_one_ptid. (clear_proceed_status): Clear step_stack_frame_id. (init_wait_for_inferior): Call clear_inline_frame_state. (init_execution_control_state): Make static. (set_step_info): New function. (init_thread_stepping_state): Do not set the symtab or line here. (stepped_in_from): New function. (handle_inferior_event): Handle inlined functions. Use set_step_info. (insert_step_resume_breakpoint_at_frame): Use get_stack_frame_id. (struct inferior_status): Add step_stack_frame_id. (save_inferior_status, restore_inferior_status): Save and restore step_stack_frame_id. * inline-frame.c, inline-frame.h: New files. * minsyms.c (prim_record_minimal_symbol_and_info): Use XCALLOC. * regcache.c (regcache_write_pc): Call reinit_frame_cache. * s390-tdep.c (s390_prologue_frame_unwind_cache): Handle INLINE_FRAME. * stack.c (frame_show_address): New. (print_frame_info, print_frame): Use it. (find_frame_funname): Use get_frame_function. Handle inlined blocks. (frame_info): Mark inlined functions. (backtrace_command_1): Use get_current_user_frame. (print_frame_local_vars, print_frame_label_vars): Update comments. (return_command): Refuse inlined functions. * symtab.c (lookup_symbol_aux_local): Stop at inlined function boundaries. (find_function_start_sal): Avoid inlined functions. (completion_list_add_fields): New function. (default_make_symbol_completion_list): Use it. Use block_static_block and block_global_block. Check for inlined functions. (skip_prologue_using_sal): Avoid line number comparison across inlining. * symtab.h (struct symbol): Add is_inlined. (SYMBOL_INLINED): New. * target.c (target_resume): Call clear_inline_frame_state. * valops.c (value_of_variable): Check block_inlined_p. gdb/doc/ * gdb.texinfo (Debugging Optimized Code): New chapter. (Compiling for Debugging): Reference it. Move some text to the new section. gdb/testsuite/ * gdb.base/break.exp: Add an XFAIL for gcc/36748. * gdb.cp/annota2.exp: Accept frames-invalid in more places. * gdb.opt/Makefile.in (EXECUTABLES): Update. * gdb.opt/clobbered-registers-O2.exp: Update to GPL v3. * gdb.opt/inline-bt.c, gdb.opt/inline-bt.exp, gdb.opt/inline-cmds.c, gdb.opt/inline-cmds.exp, gdb.opt/inline-locals.c, gdb.opt/inline-locals.exp, gdb.opt/inline-markers.c: New files. * lib/gdb.exp (skip_inline_frame_tests): New function. (skip_inline_var_tests): New function.
This commit is contained in:
57
gdb/stack.c
57
gdb/stack.c
@@ -46,6 +46,7 @@
|
||||
#include "gdbthread.h"
|
||||
#include "cp-support.h"
|
||||
#include "disasm.h"
|
||||
#include "inline-frame.h"
|
||||
|
||||
#include "gdb_assert.h"
|
||||
#include <ctype.h>
|
||||
@@ -99,6 +100,30 @@ print_stack_frame_stub (void *args)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return 1 if we should display the address in addition to the location,
|
||||
because we are in the middle of a statement. */
|
||||
|
||||
static int
|
||||
frame_show_address (struct frame_info *frame,
|
||||
struct symtab_and_line sal)
|
||||
{
|
||||
/* If there is a line number, but no PC, then there is no location
|
||||
information associated with this sal. The only way that should
|
||||
happen is for the call sites of inlined functions (SAL comes from
|
||||
find_frame_sal). Otherwise, we would have some PC range if the
|
||||
SAL came from a line table. */
|
||||
if (sal.line != 0 && sal.pc == 0 && sal.end == 0)
|
||||
{
|
||||
if (get_next_frame (frame) == NULL)
|
||||
gdb_assert (inline_skipped_frames (inferior_ptid) > 0);
|
||||
else
|
||||
gdb_assert (get_frame_type (get_next_frame (frame)) == INLINE_FRAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return get_frame_pc (frame) != sal.pc;
|
||||
}
|
||||
|
||||
/* Show or print a stack frame FRAME briefly. The output is format
|
||||
according to PRINT_LEVEL and PRINT_WHAT printing the frame's
|
||||
relative level, function name, argument list, and file name and
|
||||
@@ -565,7 +590,7 @@ print_frame_info (struct frame_info *frame, int print_level,
|
||||
{
|
||||
int done = 0;
|
||||
int mid_statement = ((print_what == SRC_LINE)
|
||||
&& (get_frame_pc (frame) != sal.pc));
|
||||
&& frame_show_address (frame, sal));
|
||||
|
||||
if (annotation_level)
|
||||
done = identify_source_line (sal.symtab, sal.line, mid_statement,
|
||||
@@ -623,7 +648,7 @@ find_frame_funname (struct frame_info *frame, char **funname,
|
||||
*funname = NULL;
|
||||
*funlang = language_unknown;
|
||||
|
||||
func = find_pc_function (get_frame_address_in_block (frame));
|
||||
func = get_frame_function (frame);
|
||||
if (func)
|
||||
{
|
||||
/* In certain pathological cases, the symtabs give the wrong
|
||||
@@ -644,8 +669,13 @@ find_frame_funname (struct frame_info *frame, char **funname,
|
||||
changed (and we'll create a find_pc_minimal_function or some
|
||||
such). */
|
||||
|
||||
struct minimal_symbol *msymbol =
|
||||
lookup_minimal_symbol_by_pc (get_frame_address_in_block (frame));
|
||||
struct minimal_symbol *msymbol = NULL;
|
||||
|
||||
/* Don't attempt to do this for inlined functions, which do not
|
||||
have a corresponding minimal symbol. */
|
||||
if (!block_inlined_p (SYMBOL_BLOCK_VALUE (func)))
|
||||
msymbol
|
||||
= lookup_minimal_symbol_by_pc (get_frame_address_in_block (frame));
|
||||
|
||||
if (msymbol != NULL
|
||||
&& (SYMBOL_VALUE_ADDRESS (msymbol)
|
||||
@@ -719,7 +749,7 @@ print_frame (struct frame_info *frame, int print_level,
|
||||
}
|
||||
get_user_print_options (&opts);
|
||||
if (opts.addressprint)
|
||||
if (get_frame_pc (frame) != sal.pc || !sal.symtab
|
||||
if (frame_show_address (frame, sal) || !sal.symtab
|
||||
|| print_what == LOC_AND_ADDRESS)
|
||||
{
|
||||
annotate_frame_address ();
|
||||
@@ -1042,8 +1072,10 @@ frame_info (char *addr_exp, int from_tty)
|
||||
printf_filtered (_(" Outermost frame: %s\n"),
|
||||
frame_stop_reason_string (reason));
|
||||
}
|
||||
|
||||
if (calling_frame_info)
|
||||
else if (get_frame_type (fi) == INLINE_FRAME)
|
||||
printf_filtered (" inlined into frame %d",
|
||||
frame_relative_level (get_prev_frame (fi)));
|
||||
else
|
||||
{
|
||||
printf_filtered (" called by frame at ");
|
||||
fputs_filtered (paddress (get_frame_base (calling_frame_info)),
|
||||
@@ -1503,7 +1535,9 @@ print_frame_local_vars (struct frame_info *frame, int num_tabs,
|
||||
if (print_block_frame_locals (block, frame, num_tabs, stream))
|
||||
values_printed = 1;
|
||||
/* After handling the function's top-level block, stop. Don't
|
||||
continue to its superblock, the block of per-file symbols. */
|
||||
continue to its superblock, the block of per-file symbols.
|
||||
Also do not continue to the containing function of an inlined
|
||||
function. */
|
||||
if (BLOCK_FUNCTION (block))
|
||||
break;
|
||||
block = BLOCK_SUPERBLOCK (block);
|
||||
@@ -1574,7 +1608,9 @@ print_frame_label_vars (struct frame_info *frame, int this_level_only,
|
||||
return;
|
||||
|
||||
/* After handling the function's top-level block, stop. Don't
|
||||
continue to its superblock, the block of per-file symbols. */
|
||||
continue to its superblock, the block of per-file symbols.
|
||||
Also do not continue to the containing function of an inlined
|
||||
function. */
|
||||
if (BLOCK_FUNCTION (block))
|
||||
break;
|
||||
block = BLOCK_SUPERBLOCK (block);
|
||||
@@ -1840,6 +1876,9 @@ return_command (char *retval_exp, int from_tty)
|
||||
thisfun = get_frame_function (thisframe);
|
||||
gdbarch = get_frame_arch (thisframe);
|
||||
|
||||
if (get_frame_type (get_current_frame ()) == INLINE_FRAME)
|
||||
error (_("Can not force return from an inlined function."));
|
||||
|
||||
/* Compute the return value. If the computation triggers an error,
|
||||
let it bail. If the return type can't be handled, set
|
||||
RETURN_VALUE to NULL, and QUERY_PREFIX to an informational
|
||||
|
||||
Reference in New Issue
Block a user