mirror of git://gcc.gnu.org/git/gcc.git
ctf: translate annotation DIEs to internal ctf
Translate DW_TAG_GNU_annotation DIEs created for C attributes btf_decl_tag and btf_type_tag into an in-memory representation in the CTF/BTF container. They will be output in BTF as BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG records. The new CTF kinds used to represent these annotations, CTF_K_DECL_TAG and CTF_K_TYPE_TAG, are expected to be formalized in the next version of the CTF specification. For now they only exist in memory as a translation step to BTF, and are not emitted when generating CTF information. gcc/ * ctfc.cc (ctf_dtu_d_union_selector): Handle CTF_K_DECL_TAG and CTF_K_TYPE_TAG. (ctf_add_type_tag, ctf_add_decl_tag): New. (ctf_add_variable): Return the new ctf_dvdef_ref rather than zero. (new_ctf_container): Initialize new members. (ctfc_delete_container): Deallocate new members. * ctfc.h (ctf_dvdef, ctf_dvdef_t, ctf_dvdef_ref): Move forward declarations earlier in file. (ctf_decl_tag_t): New typedef. (ctf_dtdef): Add ctf_decl_tag_t member to dtd_u union. (ctf_dtu_d_union_enum): Add new CTF_DTU_D_TAG enumerator. (ctf_container): Add ctfc_tags vector and ctfc_type_tags_map hash_map members. (ctf_add_type_tag, ctf_add_decl_tag): New function protos. (ctf_add_variable): Change prototype return type to ctf_dvdef_ref. * dwarf2ctf.cc (gen_ctf_type_tags, gen_ctf_decl_tags) (gen_ctf_decl_tags_for_var): New static functions. (gen_ctf_pointer_type): Handle type tags. (gen_ctf_sou_type): Handle decl tags. (gen_ctf_function_type): Likewise. (gen_ctf_variable): Likewise. (gen_ctf_function): Likewise. (gen_ctf_type): Handle TAG_GNU_annotation DIEs. gcc/testsuite/ * gcc.dg/debug/ctf/ctf-decl-tag-1.c: New test. * gcc.dg/debug/ctf/ctf-type-tag-1.c: New test. include/ * ctf.h (CTF_K_DECL_TAG, CTF_K_TYPE_TAG): New defines.
This commit is contained in:
parent
ac7027f180
commit
9c862a593b
80
gcc/ctfc.cc
80
gcc/ctfc.cc
|
|
@ -107,6 +107,9 @@ ctf_dtu_d_union_selector (ctf_dtdef_ref ctftype)
|
|||
return CTF_DTU_D_ARGUMENTS;
|
||||
case CTF_K_SLICE:
|
||||
return CTF_DTU_D_SLICE;
|
||||
case CTF_K_DECL_TAG:
|
||||
case CTF_K_TYPE_TAG:
|
||||
return CTF_DTU_D_TAG;
|
||||
default:
|
||||
/* The largest member as default. */
|
||||
return CTF_DTU_D_ARRAY;
|
||||
|
|
@ -445,6 +448,68 @@ ctf_add_reftype (ctf_container_ref ctfc, uint32_t flag, ctf_dtdef_ref ref,
|
|||
return dtd;
|
||||
}
|
||||
|
||||
ctf_dtdef_ref
|
||||
ctf_add_type_tag (ctf_container_ref ctfc, uint32_t flag, const char *value,
|
||||
ctf_dtdef_ref ref_dtd)
|
||||
{
|
||||
ctf_dtdef_ref dtd;
|
||||
/* Create a DTD for the tag, but do not place it in the regular types list;
|
||||
CTF format does not (yet) encode tags. */
|
||||
dtd = ggc_cleared_alloc<ctf_dtdef_t> ();
|
||||
|
||||
dtd->dtd_name = ctf_add_string (ctfc, value, &(dtd->dtd_data.ctti_name),
|
||||
CTF_AUX_STRTAB);
|
||||
/* A single DW_TAG_GNU_annotation DIE may be referenced by multiple DIEs,
|
||||
e.g. when multiple distinct types specify the same type tag. We will
|
||||
synthesize multiple CTF DTD records in that case, so we cannot tie them
|
||||
all to the same key (the DW_TAG_GNU_annotation DIE) in ctfc_types. */
|
||||
dtd->dtd_key = NULL;
|
||||
dtd->ref_type = ref_dtd;
|
||||
dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_TYPE_TAG, flag, 0);
|
||||
dtd->dtd_u.dtu_tag.ref_var = NULL; /* Not used for type tags. */
|
||||
dtd->dtd_u.dtu_tag.component_idx = 0; /* Not used for type tags. */
|
||||
|
||||
/* Insert tag directly into the tag list. Type ID will be assigned later. */
|
||||
vec_safe_push (ctfc->ctfc_tags, dtd);
|
||||
|
||||
/* Keep ctfc_aux_strlen updated. */
|
||||
if ((value != NULL) && strcmp (value, ""))
|
||||
ctfc->ctfc_aux_strlen += strlen (value) + 1;
|
||||
|
||||
return dtd;
|
||||
}
|
||||
|
||||
ctf_dtdef_ref
|
||||
ctf_add_decl_tag (ctf_container_ref ctfc, uint32_t flag, const char *value,
|
||||
ctf_dtdef_ref ref_dtd, uint32_t comp_idx)
|
||||
{
|
||||
ctf_dtdef_ref dtd;
|
||||
/* Create a DTD for the tag, but do not place it in the regular types list;
|
||||
ctf format does not (yet) encode tags. */
|
||||
dtd = ggc_cleared_alloc<ctf_dtdef_t> ();
|
||||
|
||||
dtd->dtd_name = ctf_add_string (ctfc, value, &(dtd->dtd_data.ctti_name),
|
||||
CTF_AUX_STRTAB);
|
||||
/* A single DW_TAG_GNU_annotation DIE may be referenced by multiple DIEs,
|
||||
e.g. when multiple distinct declarations specify the same decl tag.
|
||||
We will synthesize multiple CTF DTD records in that case, so we cannot tie
|
||||
them all to the same key (the DW_TAG_GNU_annotation DIE) in ctfc_types. */
|
||||
dtd->dtd_key = NULL;
|
||||
dtd->ref_type = ref_dtd;
|
||||
dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_DECL_TAG, flag, 0);
|
||||
dtd->dtd_u.dtu_tag.ref_var = NULL;
|
||||
dtd->dtd_u.dtu_tag.component_idx = comp_idx;
|
||||
|
||||
/* Insert tag directly into the tag list. Type ID will be assigned later. */
|
||||
vec_safe_push (ctfc->ctfc_tags, dtd);
|
||||
|
||||
/* Keep ctfc_aux_strlen updated. */
|
||||
if ((value != NULL) && strcmp (value, ""))
|
||||
ctfc->ctfc_aux_strlen += strlen (value) + 1;
|
||||
|
||||
return dtd;
|
||||
}
|
||||
|
||||
ctf_dtdef_ref
|
||||
ctf_add_forward (ctf_container_ref ctfc, uint32_t flag, const char * name,
|
||||
uint32_t kind, dw_die_ref die)
|
||||
|
|
@ -691,12 +756,12 @@ ctf_add_member_offset (ctf_container_ref ctfc, dw_die_ref sou,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ctf_dvdef_ref
|
||||
ctf_add_variable (ctf_container_ref ctfc, const char * name, ctf_dtdef_ref ref,
|
||||
dw_die_ref die, unsigned int external_vis,
|
||||
dw_die_ref die_var_decl)
|
||||
{
|
||||
ctf_dvdef_ref dvd, dvd_ignore;
|
||||
ctf_dvdef_ref dvd = NULL, dvd_ignore;
|
||||
|
||||
gcc_assert (name);
|
||||
|
||||
|
|
@ -732,7 +797,7 @@ ctf_add_variable (ctf_container_ref ctfc, const char * name, ctf_dtdef_ref ref,
|
|||
ctfc->ctfc_strlen += strlen (name) + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return dvd;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -949,6 +1014,10 @@ new_ctf_container (void)
|
|||
tu_ctfc->ctfc_ignore_vars
|
||||
= hash_table<ctfc_dvd_hasher>::create_ggc (10);
|
||||
|
||||
vec_alloc (tu_ctfc->ctfc_tags, 100);
|
||||
tu_ctfc->ctfc_type_tags_map
|
||||
= hash_map<ctf_dtdef_ref, ctf_dtdef_ref>::create_ggc (100);
|
||||
|
||||
return tu_ctfc;
|
||||
}
|
||||
|
||||
|
|
@ -1003,6 +1072,11 @@ ctfc_delete_container (ctf_container_ref ctfc)
|
|||
ctfc->ctfc_ignore_vars->empty ();
|
||||
ctfc->ctfc_ignore_vars = NULL;
|
||||
|
||||
ctfc->ctfc_tags = NULL;
|
||||
|
||||
ctfc->ctfc_type_tags_map->empty ();
|
||||
ctfc->ctfc_type_tags_map = NULL;
|
||||
|
||||
ctfc_delete_strtab (&ctfc->ctfc_strtable);
|
||||
ctfc_delete_strtab (&ctfc->ctfc_aux_strtable);
|
||||
if (ctfc->ctfc_vars_list)
|
||||
|
|
|
|||
43
gcc/ctfc.h
43
gcc/ctfc.h
|
|
@ -52,6 +52,10 @@ struct ctf_dtdef;
|
|||
typedef struct ctf_dtdef ctf_dtdef_t;
|
||||
typedef ctf_dtdef_t * ctf_dtdef_ref;
|
||||
|
||||
struct ctf_dvdef;
|
||||
typedef struct ctf_dvdef ctf_dvdef_t;
|
||||
typedef ctf_dvdef_t * ctf_dvdef_ref;
|
||||
|
||||
/* CTF string table element (list node). */
|
||||
|
||||
typedef struct GTY ((chain_next ("%h.cts_next"))) ctf_string
|
||||
|
|
@ -155,6 +159,16 @@ typedef struct GTY (()) ctf_func_arg
|
|||
|
||||
#define ctf_farg_list_next(elem) ((ctf_func_arg_t *)((elem)->farg_next))
|
||||
|
||||
/* Declaration Tag.
|
||||
May be used to annotate struct/union members, variable declarations,
|
||||
function declarations, and function arguments. */
|
||||
|
||||
typedef struct GTY (()) ctf_decl_tag
|
||||
{
|
||||
uint32_t component_idx; /* Index of component to which tag applies. */
|
||||
ctf_dvdef_ref ref_var; /* Non-null iff this tag applies to a variable. */
|
||||
} ctf_decl_tag_t;
|
||||
|
||||
/* Type definition for CTF generation. */
|
||||
|
||||
struct GTY ((for_user)) ctf_dtdef
|
||||
|
|
@ -184,6 +198,8 @@ struct GTY ((for_user)) ctf_dtdef
|
|||
ctf_func_arg_t * GTY ((tag ("CTF_DTU_D_ARGUMENTS"))) dtu_argv;
|
||||
/* slice. */
|
||||
ctf_sliceinfo_t GTY ((tag ("CTF_DTU_D_SLICE"))) dtu_slice;
|
||||
/* decl tag. */
|
||||
ctf_decl_tag_t GTY ((tag ("CTF_DTU_D_TAG"))) dtu_tag;
|
||||
} dtd_u;
|
||||
};
|
||||
|
||||
|
|
@ -201,9 +217,6 @@ struct GTY ((for_user)) ctf_dvdef
|
|||
ctf_id_t dvd_id; /* ID of this variable. Only used for BTF. */
|
||||
};
|
||||
|
||||
typedef struct ctf_dvdef ctf_dvdef_t;
|
||||
typedef ctf_dvdef_t * ctf_dvdef_ref;
|
||||
|
||||
/* Location information for CTF Types and CTF Variables. */
|
||||
|
||||
typedef struct GTY (()) ctf_srcloc
|
||||
|
|
@ -222,7 +235,8 @@ enum ctf_dtu_d_union_enum {
|
|||
CTF_DTU_D_ARRAY,
|
||||
CTF_DTU_D_ENCODING,
|
||||
CTF_DTU_D_ARGUMENTS,
|
||||
CTF_DTU_D_SLICE
|
||||
CTF_DTU_D_SLICE,
|
||||
CTF_DTU_D_TAG,
|
||||
};
|
||||
|
||||
enum ctf_dtu_d_union_enum
|
||||
|
|
@ -287,6 +301,17 @@ typedef struct GTY (()) ctf_container
|
|||
/* CTF variables to be ignored. */
|
||||
hash_table <ctfc_dvd_hasher> * GTY (()) ctfc_ignore_vars;
|
||||
|
||||
/* BTF type and decl tags. Not yet represented in CTF. These tags also
|
||||
uniquely have a one-to-many relation with DIEs, meaning a single DIE
|
||||
may translate to multiple CTF/BTF records. For both of these reasons,
|
||||
they cannot be stored in the regular types table. */
|
||||
vec <ctf_dtdef_ref, va_gc> * GTY (()) ctfc_tags;
|
||||
/* Type tags logically form part of the type chain similar to cv-quals.
|
||||
Therefore references to types need to know if the referred-to type has
|
||||
any type tags, and if so to refer to the outermost type tag. This map
|
||||
maps a type to the outermost type tag created for it, if any. */
|
||||
hash_map <ctf_dtdef_ref, ctf_dtdef_ref> * GTY (()) ctfc_type_tags_map;
|
||||
|
||||
/* CTF string table. */
|
||||
ctf_strtable_t ctfc_strtable;
|
||||
/* Auxilliary string table. At this time, used for keeping func arg names
|
||||
|
|
@ -440,15 +465,19 @@ extern ctf_dtdef_ref ctf_add_function (ctf_container_ref, uint32_t,
|
|||
dw_die_ref, bool, int);
|
||||
extern ctf_dtdef_ref ctf_add_sou (ctf_container_ref, uint32_t, const char *,
|
||||
uint32_t, unsigned HOST_WIDE_INT, dw_die_ref);
|
||||
|
||||
extern ctf_dtdef_ref ctf_add_type_tag (ctf_container_ref, uint32_t,
|
||||
const char *, ctf_dtdef_ref);
|
||||
extern ctf_dtdef_ref ctf_add_decl_tag (ctf_container_ref, uint32_t,
|
||||
const char *, ctf_dtdef_ref, uint32_t);
|
||||
extern int ctf_add_enumerator (ctf_container_ref, ctf_dtdef_ref, const char *,
|
||||
HOST_WIDE_INT, dw_die_ref);
|
||||
extern int ctf_add_member_offset (ctf_container_ref, dw_die_ref, const char *,
|
||||
ctf_dtdef_ref, uint64_t);
|
||||
extern int ctf_add_function_arg (ctf_container_ref, dw_die_ref,
|
||||
const char *, ctf_dtdef_ref);
|
||||
extern int ctf_add_variable (ctf_container_ref, const char *, ctf_dtdef_ref,
|
||||
dw_die_ref, unsigned int, dw_die_ref);
|
||||
extern ctf_dvdef_ref ctf_add_variable (ctf_container_ref, const char *,
|
||||
ctf_dtdef_ref, dw_die_ref, unsigned int,
|
||||
dw_die_ref);
|
||||
|
||||
extern ctf_dtdef_ref ctf_lookup_tree_type (ctf_container_ref, const tree);
|
||||
|
||||
|
|
|
|||
135
gcc/dwarf2ctf.cc
135
gcc/dwarf2ctf.cc
|
|
@ -32,6 +32,17 @@ along with GCC; see the file COPYING3. If not see
|
|||
static ctf_dtdef_ref
|
||||
gen_ctf_type (ctf_container_ref, dw_die_ref);
|
||||
|
||||
static void
|
||||
gen_ctf_decl_tags (ctf_container_ref, dw_die_ref, ctf_dtdef_ref, uint32_t);
|
||||
|
||||
static void
|
||||
gen_ctf_decl_tags_for_var (ctf_container_ref, dw_die_ref, ctf_dvdef_ref);
|
||||
|
||||
static ctf_dtdef_ref
|
||||
handle_ctf_type_tags (ctf_container_ref ctc, dw_die_ref annot_die,
|
||||
ctf_dtdef_ref ref_dtd);
|
||||
|
||||
|
||||
/* All the DIE structures we handle come from the DWARF information
|
||||
generated by GCC. However, there are three situations where we need
|
||||
to create our own created DIE structures because GCC doesn't
|
||||
|
|
@ -335,6 +346,17 @@ gen_ctf_pointer_type (ctf_container_ref ctfc, dw_die_ref ptr_type)
|
|||
|
||||
pointed_dtd = gen_ctf_type (ctfc, pointed_type_die);
|
||||
|
||||
/* Handle BTF type tags. */
|
||||
if (btf_debuginfo_p ())
|
||||
{
|
||||
dw_die_ref annot_die = get_AT_ref (ptr_type, DW_AT_GNU_annotation);
|
||||
ctf_dtdef_ref tag_dtd
|
||||
= handle_ctf_type_tags (ctfc, annot_die, pointed_dtd);
|
||||
|
||||
if (tag_dtd)
|
||||
pointed_dtd = tag_dtd;
|
||||
}
|
||||
|
||||
/* Type de-duplication.
|
||||
Consult the ctfc_types hash again before adding the CTF pointer type
|
||||
because there can be cases where a pointer type may have been added by
|
||||
|
|
@ -536,6 +558,7 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, uint32_t kind)
|
|||
/* Now process the struct members. */
|
||||
{
|
||||
dw_die_ref c;
|
||||
uint32_t idx = 0;
|
||||
|
||||
c = dw_get_die_child (sou);
|
||||
if (c)
|
||||
|
|
@ -620,6 +643,9 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, uint32_t kind)
|
|||
field_name,
|
||||
field_dtd,
|
||||
field_location);
|
||||
|
||||
gen_ctf_decl_tags (ctfc, c, sou_dtd, idx);
|
||||
idx++;
|
||||
}
|
||||
while (c != dw_get_die_child (sou));
|
||||
}
|
||||
|
|
@ -703,14 +729,18 @@ gen_ctf_function_type (ctf_container_ref ctfc, dw_die_ref function,
|
|||
gcc_assert (i == num_args - 1);
|
||||
/* Add an argument with type 0 and no name. */
|
||||
ctf_add_function_arg (ctfc, function, "", NULL);
|
||||
/* Handle any declaration tags on the argument. */
|
||||
gen_ctf_decl_tags (ctfc, c, function_dtd, i);
|
||||
}
|
||||
else if (dw_get_die_tag (c) == DW_TAG_formal_parameter)
|
||||
{
|
||||
i++;
|
||||
arg_name = get_AT_string (c, DW_AT_name);
|
||||
arg_type = gen_ctf_type (ctfc, ctf_get_AT_type (c));
|
||||
/* Add the argument to the existing CTF function type. */
|
||||
ctf_add_function_arg (ctfc, function, arg_name, arg_type);
|
||||
/* Handle any declaration tags on the argument. */
|
||||
gen_ctf_decl_tags (ctfc, c, function_dtd, i);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
/* This is a local variable. Ignore. */
|
||||
|
|
@ -801,6 +831,7 @@ gen_ctf_variable (ctf_container_ref ctfc, dw_die_ref die)
|
|||
dw_die_ref var_type = ctf_get_AT_type (die);
|
||||
unsigned int external_vis = get_AT_flag (die, DW_AT_external);
|
||||
ctf_dtdef_ref var_dtd;
|
||||
ctf_dvdef_ref dvd;
|
||||
|
||||
/* Avoid duplicates. */
|
||||
if (ctf_dvd_lookup (ctfc, die))
|
||||
|
|
@ -821,10 +852,13 @@ gen_ctf_variable (ctf_container_ref ctfc, dw_die_ref die)
|
|||
var_dtd = gen_ctf_type (ctfc, var_type);
|
||||
|
||||
/* Generate the new CTF variable and update global counter. */
|
||||
(void) ctf_add_variable (ctfc, var_name, var_dtd, die, external_vis, decl);
|
||||
dvd = ctf_add_variable (ctfc, var_name, var_dtd, die, external_vis, decl);
|
||||
/* Skip updating the number of global objects at this time. This is updated
|
||||
later after pre-processing as some CTF variable records although
|
||||
generated now, will not be emitted later. [PR105089]. */
|
||||
|
||||
/* Handle declaration tags on the variable. */
|
||||
gen_ctf_decl_tags_for_var (ctfc, die, dvd);
|
||||
}
|
||||
|
||||
/* Add a CTF function record for the given input DWARF DIE. */
|
||||
|
|
@ -842,8 +876,97 @@ gen_ctf_function (ctf_container_ref ctfc, dw_die_ref die)
|
|||
counter. Note that DWARF encodes function types in both
|
||||
DW_TAG_subroutine_type and DW_TAG_subprogram in exactly the same
|
||||
way. */
|
||||
(void) gen_ctf_function_type (ctfc, die, true /* from_global_func */);
|
||||
function_dtd = gen_ctf_function_type (ctfc, die, true /* from_global_func */);
|
||||
ctfc->ctfc_num_global_funcs += 1;
|
||||
|
||||
/* Handle declaration tags on the function. */
|
||||
gen_ctf_decl_tags (ctfc, die, function_dtd, -1U);
|
||||
}
|
||||
|
||||
static ctf_dtdef_ref
|
||||
handle_ctf_type_tags (ctf_container_ref ctfc, dw_die_ref annot_die,
|
||||
ctf_dtdef_ref ref_dtd)
|
||||
{
|
||||
if (!annot_die || !ref_dtd)
|
||||
return NULL;
|
||||
|
||||
/* Recurse first. */
|
||||
dw_die_ref next_annot;
|
||||
if ((next_annot = get_AT_ref (annot_die, DW_AT_GNU_annotation)))
|
||||
ref_dtd = handle_ctf_type_tags (ctfc, next_annot, ref_dtd);
|
||||
|
||||
ctf_dtdef_ref tag_dtd = NULL;
|
||||
const char *name = get_AT_string (annot_die, DW_AT_name);
|
||||
const char *value = get_AT_string (annot_die, DW_AT_const_value);
|
||||
|
||||
if (strcmp (name, "btf_type_tag") == 0)
|
||||
tag_dtd = ctf_add_type_tag (ctfc, CTF_ADD_ROOT, value, ref_dtd);
|
||||
|
||||
return tag_dtd;
|
||||
}
|
||||
|
||||
/* Handle any DW_AT_GNU_annotation on decl DIE by constructing a CTF_K_DECL_TAG
|
||||
type for the DW_TAG_GNU_annotation DIE to which it points, if this has not
|
||||
been previously constructed. There may be multiple annotations chained
|
||||
together by further occurances of DW_AT_GNU_annotation in the annoation DIEs
|
||||
themselves, in which case a corresponding CTF_K_DECL_TAG type is created for
|
||||
each. Unlike TYPE_TAGs, which form a chain, each DECL_TAG individually
|
||||
refers directly to the annotated decl, which should be supplied in REF_DTD.
|
||||
IDX is the zero-based component index indicating to which function parameter
|
||||
or struct or union member the DECL_TAG refers, or (uint32_t) -1 if it refers
|
||||
to a function decl or sou itself.
|
||||
Note that because individual DECL_TAGs refer direcly to the annotated decl,
|
||||
they cannot be deduplicated across usages. */
|
||||
|
||||
static void
|
||||
gen_ctf_decl_tags (ctf_container_ref ctfc, dw_die_ref die,
|
||||
ctf_dtdef_ref ref_dtd, uint32_t idx)
|
||||
{
|
||||
if (!btf_debuginfo_p () || !die || !ref_dtd)
|
||||
return;
|
||||
|
||||
dw_die_ref annot_die = get_AT_ref (die, DW_AT_GNU_annotation);
|
||||
while (annot_die)
|
||||
{
|
||||
const char *name = get_AT_string (annot_die, DW_AT_name);
|
||||
const char *value = get_AT_string (annot_die, DW_AT_const_value);
|
||||
|
||||
if (strcmp (name, "btf_decl_tag") == 0)
|
||||
(void) ctf_add_decl_tag (ctfc, CTF_ADD_ROOT, value, ref_dtd, idx);
|
||||
|
||||
annot_die = get_AT_ref (annot_die, DW_AT_GNU_annotation);
|
||||
}
|
||||
}
|
||||
|
||||
/* Like gen_ctf_decl_tags above, but specifically for variables. Declaration
|
||||
tags may appear on variables or other declarations like functions, but due
|
||||
to the distinction in CTF between variables and types the processing in
|
||||
each case is slightly different. REF_DVD is the CTF record for the variable
|
||||
which is annotated. */
|
||||
|
||||
static void
|
||||
gen_ctf_decl_tags_for_var (ctf_container_ref ctfc, dw_die_ref die,
|
||||
ctf_dvdef_ref ref_dvd)
|
||||
{
|
||||
if (!btf_debuginfo_p () || !die || !ref_dvd)
|
||||
return;
|
||||
|
||||
ctf_dtdef_ref tag_dtd = NULL;
|
||||
|
||||
dw_die_ref annot_die = get_AT_ref (die, DW_AT_GNU_annotation);
|
||||
while (annot_die)
|
||||
{
|
||||
const char *name = get_AT_string (annot_die, DW_AT_name);
|
||||
const char *value = get_AT_string (annot_die, DW_AT_const_value);
|
||||
|
||||
if (strcmp (name, "btf_decl_tag") == 0)
|
||||
{
|
||||
tag_dtd = ctf_add_decl_tag (ctfc, CTF_ADD_ROOT, value, NULL, -1U);
|
||||
tag_dtd->dtd_u.dtu_tag.ref_var = ref_dvd;
|
||||
}
|
||||
|
||||
annot_die = get_AT_ref (annot_die, DW_AT_GNU_annotation);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add CTF type record(s) for the given input DWARF DIE and return its type id.
|
||||
|
|
@ -910,6 +1033,12 @@ gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
|
|||
|
||||
break;
|
||||
}
|
||||
case DW_TAG_GNU_annotation:
|
||||
/* These DIEs are traversed by gen_ctf_type_tags by following
|
||||
any DW_AT_GNU_annotation present in other types. */
|
||||
dtd = NULL;
|
||||
unrecog_die = true;
|
||||
break;
|
||||
case DW_TAG_reference_type:
|
||||
dtd = NULL;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
/* CTF generation for btf_decl_tag attribute.
|
||||
|
||||
CTF does not encode these attributes and no CTF_K_DECL_TAG record should be
|
||||
emitted; these records only exist internally to facilitate translation
|
||||
to BTF. */
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O0 -gctf -dA" } */
|
||||
|
||||
int x __attribute__((btf_decl_tag ("some_tag")));
|
||||
|
||||
struct S {
|
||||
int a;
|
||||
int b __attribute__((btf_decl_tag ("_b")));
|
||||
int c;
|
||||
};
|
||||
|
||||
struct S some_S;
|
||||
|
||||
void
|
||||
__attribute__((btf_decl_tag ("__func")))
|
||||
foo (int *ptr __attribute__((btf_decl_tag ("w"))), int val)
|
||||
{
|
||||
*ptr = val;
|
||||
}
|
||||
|
||||
/* Expect 5 CTF types: int, struct, void, int*, void (int*, int). */
|
||||
/* { dg-final { scan-assembler-times "ctt_info" 5 } } */
|
||||
/* Ensure no CTF_K_DECL_TAG record is emitted. */
|
||||
/* { dg-final { scan-assembler-not "\[\t \]0x3c*\[\t \]+\[^\n\]*ctt_info" } } */
|
||||
/* { dg-final { scan-assembler-not "\[\t \]0x3e*\[\t \]+\[^\n\]*ctt_info" } } */
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/* CTF generation for btf_type_tag attribute.
|
||||
|
||||
CTF does not encode these attributes and no CTF_K_TYPE_TAG record should be
|
||||
emitted; these records only exist internally to facilitate translation
|
||||
to BTF. */
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O0 -gctf -dA" } */
|
||||
|
||||
int * __attribute__((btf_type_tag ("some_tag"))) x;
|
||||
|
||||
typedef unsigned int __attribute__((btf_type_tag ("other_tag"))) uint;
|
||||
const uint u;
|
||||
|
||||
/* Expect 5 CTF types: int, int*, unsigned int, typedef, const. */
|
||||
/* { dg-final { scan-assembler-times "ctt_info" 5 } } */
|
||||
/* Ensure no CTF_K_TYPE_TAG record is emitted. */
|
||||
/* { dg-final { scan-assembler-not "\[\t \]0x40*\[\t \]+\[^\n\]*ctt_info" } } */
|
||||
/* { dg-final { scan-assembler-not "\[\t \]0x42*\[\t \]+\[^\n\]*ctt_info" } } */
|
||||
|
|
@ -423,6 +423,10 @@ union
|
|||
#define CTF_K_CONST 12 /* ctt_type is base type. */
|
||||
#define CTF_K_RESTRICT 13 /* ctt_type is base type. */
|
||||
#define CTF_K_SLICE 14 /* Variant data is a ctf_slice_t. */
|
||||
#define CTF_K_DECL_TAG 15 /* Declaration tag. Internal use only.
|
||||
Not valid externally until CTF V4. */
|
||||
#define CTF_K_TYPE_TAG 16 /* Type tag. Internal use only.
|
||||
Not valid externally until CTF V4. */
|
||||
|
||||
#define CTF_K_MAX 63 /* Maximum possible (V2) CTF_K_* value. */
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue