From bb984ff154d9e532deccdb52b3527496852c5930 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sun, 9 Oct 2011 19:23:41 +0000 Subject: [PATCH] gdb/ Tail call sites reader implementation. * dwarf2read.c (read_call_site_scope): Recognize DW_AT_GNU_tail_call, fill in TYPE_TAIL_CALL_LIST. * gdbtypes.h (struct func_type): New field tail_call_list. (struct call_site): New field tail_call_next. (TYPE_TAIL_CALL_LIST): New definition. --- gdb/ChangeLog | 9 +++++++++ gdb/dwarf2read.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ gdb/gdbtypes.h | 11 +++++++++++ 3 files changed, 67 insertions(+) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a6637561806..8908251c66d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2011-10-09 Jan Kratochvil + + Tail call sites reader implementation. + * dwarf2read.c (read_call_site_scope): Recognize DW_AT_GNU_tail_call, + fill in TYPE_TAIL_CALL_LIST. + * gdbtypes.h (struct func_type): New field tail_call_list. + (struct call_site): New field tail_call_next. + (TYPE_TAIL_CALL_LIST): New definition. + 2011-10-09 Jan Kratochvil Implement basic support for DW_TAG_GNU_call_site. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index a139b96bbf6..abc216369cd 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -6209,6 +6209,53 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) memset (call_site, 0, sizeof (*call_site) - sizeof (*call_site->parameter)); call_site->pc = pc; + if (dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu)) + { + struct die_info *func_die; + + /* Skip also over DW_TAG_inlined_subroutine. */ + for (func_die = die->parent; + func_die && func_die->tag != DW_TAG_subprogram + && func_die->tag != DW_TAG_subroutine_type; + func_die = func_die->parent); + + /* DW_AT_GNU_all_call_sites is a superset + of DW_AT_GNU_all_tail_call_sites. */ + if (func_die + && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_call_sites, cu) + && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_tail_call_sites, cu)) + { + /* TYPE_TAIL_CALL_LIST is not interesting in functions where it is + not complete. But keep CALL_SITE for look ups via call_site_htab, + both the initial caller containing the real return address PC and + the final callee containing the current PC of a chain of tail + calls do not need to have the tail call list complete. But any + function candidate for a virtual tail call frame searched via + TYPE_TAIL_CALL_LIST must have the tail call list complete to be + determined unambiguously. */ + } + else + { + struct type *func_type = NULL; + + if (func_die) + func_type = get_die_type (func_die, cu); + if (func_type != NULL) + { + gdb_assert (TYPE_CODE (func_type) == TYPE_CODE_FUNC); + + /* Enlist this call site to the function. */ + call_site->tail_call_next = TYPE_TAIL_CALL_LIST (func_type); + TYPE_TAIL_CALL_LIST (func_type) = call_site; + } + else + complaint (&symfile_complaints, + _("Cannot find function owning DW_TAG_GNU_call_site " + "DIE 0x%x [in module %s]"), + die->offset, cu->objfile->name); + } + } + attr = dwarf2_attr (die, DW_AT_GNU_call_site_target, cu); if (attr == NULL) attr = dwarf2_attr (die, DW_AT_abstract_origin, cu); diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 523cd8007b5..9d9785bdec7 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -902,6 +902,13 @@ struct func_type this is only fetched from the Dwarf-2 DW_AT_calling_convention attribute. */ unsigned calling_convention; + + /* Only those DW_TAG_GNU_call_site's in this function that have + DW_AT_GNU_tail_call set are linked in this list. Function without its + tail call list complete (DW_AT_GNU_all_tail_call_sites or its superset + DW_AT_GNU_all_call_sites) has TAIL_CALL_LIST NULL, even if some + DW_TAG_GNU_call_site's exist in such function. */ + struct call_site *tail_call_list; }; /* A place where a function gets called from, represented by @@ -913,6 +920,9 @@ struct call_site field as we overload core_addr_hash and core_addr_eq for it. */ CORE_ADDR pc; + /* List successor with head in FUNC_TYPE.TAIL_CALL_LIST. */ + struct call_site *tail_call_next; + /* Describe DW_AT_GNU_call_site_target. Missing attribute uses FIELD_LOC_KIND_DWARF_BLOCK with FIELD_DWARF_BLOCK == NULL. */ struct @@ -1060,6 +1070,7 @@ extern void allocate_gnat_aux_type (struct type *); #define TYPE_GNAT_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.gnat_stuff #define TYPE_DESCRIPTIVE_TYPE(thistype) TYPE_GNAT_SPECIFIC(thistype)->descriptive_type #define TYPE_CALLING_CONVENTION(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->calling_convention +#define TYPE_TAIL_CALL_LIST(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->tail_call_list #define TYPE_BASECLASS(thistype,index) TYPE_FIELD_TYPE(thistype, index) #define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses #define TYPE_BASECLASS_NAME(thistype,index) TYPE_FIELD_NAME(thistype, index) -- 2.30.2