diff options
Diffstat (limited to 'gcc/dwarf2ctf.c')
-rw-r--r-- | gcc/dwarf2ctf.c | 1018 |
1 files changed, 0 insertions, 1018 deletions
diff --git a/gcc/dwarf2ctf.c b/gcc/dwarf2ctf.c deleted file mode 100644 index 747b2f6..0000000 --- a/gcc/dwarf2ctf.c +++ /dev/null @@ -1,1018 +0,0 @@ -/* Generate CTF types and objects from the GCC DWARF. - Copyright (C) 2021-2022 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC 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, or (at your option) any later -version. - -GCC 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 GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "dwarf2out.h" -#include "dwarf2out.h" - -#include "dwarf2ctf.h" -#include "ctfc.h" - -/* Forward declarations for some routines defined in this file. */ - -static ctf_id_t -gen_ctf_type (ctf_container_ref, dw_die_ref); - -/* 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 - provide them. - - The DWARF spec suggests using a DIE with DW_TAG_unspecified_type - and name "void" in order to denote the void type. But GCC doesn't - follow this advice. Still we need a DIE to act as a key for void - types, we use ctf_void_die. - - Also, if a subrange type corresponding to an array index does not - specify a type then we assume it is `int'. - - Finally, for types unrepresentable in CTF, we need a DIE to anchor - them to a CTF type of kind unknown. - - The variables below are initialized in ctf_debug_init and hold - references to the proper DIEs. */ - -static GTY (()) dw_die_ref ctf_void_die; -static GTY (()) dw_die_ref ctf_array_index_die; -static GTY (()) dw_die_ref ctf_unknown_die; - -/* Some DIEs have a type description attribute, stored in a DW_AT_type - attribute. However, GCC generates no attribute to signify a `void' - type. - - This can happen in many contexts (return type of a function, - pointed or qualified type, etc) so we use the `ctf_get_AT_type' - function below abstracts this. */ - -static dw_die_ref -ctf_get_AT_type (dw_die_ref die) -{ - dw_die_ref type_die = get_AT_ref (die, DW_AT_type); - return (type_die ? type_die : ctf_void_die); -} - -/* Some data member DIEs have location specified as a DWARF expression - (specifically in DWARF2). Luckily, the expression is a simple - DW_OP_plus_uconst with one operand set to zero. - - Sometimes the data member location may also be negative. In yet some other - cases (specifically union data members), the data member location is - non-existent. Handle all these scenarios here to abstract this. */ - -static HOST_WIDE_INT -ctf_get_AT_data_member_location (dw_die_ref die) -{ - HOST_WIDE_INT field_location = 0; - dw_attr_node * attr; - - /* The field location (in bits) can be determined from - either a DW_AT_data_member_location attribute or a - DW_AT_data_bit_offset attribute. */ - if (get_AT (die, DW_AT_data_bit_offset)) - field_location = get_AT_unsigned (die, DW_AT_data_bit_offset); - else - { - attr = get_AT (die, DW_AT_data_member_location); - if (attr && AT_class (attr) == dw_val_class_loc) - { - dw_loc_descr_ref descr = AT_loc (attr); - /* Operand 2 must be zero; the structure is assumed to be on the - stack in DWARF2. */ - gcc_assert (!descr->dw_loc_oprnd2.v.val_unsigned); - gcc_assert (descr->dw_loc_oprnd2.val_class - == dw_val_class_unsigned_const); - field_location = descr->dw_loc_oprnd1.v.val_unsigned * 8; - } - else - { - attr = get_AT (die, DW_AT_data_member_location); - if (attr && AT_class (attr) == dw_val_class_const) - field_location = AT_int (attr) * 8; - else - field_location = (get_AT_unsigned (die, - DW_AT_data_member_location) - * 8); - } - } - - return field_location; -} - -/* CTF Types' and CTF Variables' Location Information. CTF section does not - emit location information, this is provided for BTF CO-RE use-cases. These - functions fetch information from DWARF Die directly, as such the location - information is not buffered in the CTF container. */ - -const char * -ctf_get_die_loc_file (dw_die_ref die) -{ - if (!die) - return NULL; - - struct dwarf_file_data * file; - file = get_AT_file (die, DW_AT_decl_file); - if (!file) - return NULL; - - return file->filename; -} - -unsigned int -ctf_get_die_loc_line (dw_die_ref die) -{ - if (!die) - return 0; - - return get_AT_unsigned (die, DW_AT_decl_line); -} - -unsigned int -ctf_get_die_loc_col (dw_die_ref die) -{ - if (!die) - return 0; - - return get_AT_unsigned (die, DW_AT_decl_column); -} - -/* Generate CTF for the void type. */ - -static ctf_id_t -gen_ctf_void_type (ctf_container_ref ctfc) -{ - ctf_encoding_t ctf_encoding = {0, 0, 0}; - - /* In CTF the void type is encoded as a 0-byte signed integer - type. */ - - ctf_encoding.cte_bits = 0; - ctf_encoding.cte_format = CTF_INT_SIGNED; - - gcc_assert (ctf_void_die != NULL); - return ctf_add_integer (ctfc, CTF_ADD_ROOT, "void", - &ctf_encoding, ctf_void_die); -} - -/* Generate CTF type of unknown kind. */ - -static ctf_id_t -gen_ctf_unknown_type (ctf_container_ref ctfc) -{ - ctf_id_t unknown_type_id; - - /* In CTF, the unknown type is encoded as a 0 byte sized type with kind - CTF_K_UNKNOWN. Create an encoding object merely to reuse the underlying - ctf_add_encoded interface; the CTF encoding object is not 'used' any more - than just the generation of size from. */ - ctf_encoding_t ctf_encoding = {0, 0, 0}; - - gcc_assert (ctf_unknown_die != NULL); - /* Type de-duplication. */ - if (!ctf_type_exists (ctfc, ctf_unknown_die, &unknown_type_id)) - unknown_type_id = ctf_add_unknown (ctfc, CTF_ADD_ROOT, "unknown", - &ctf_encoding, ctf_unknown_die); - - return unknown_type_id; -} - -/* Sizes of entities can be given in bytes or bits. This function - abstracts this by returning the size in bits of the given entity. - If no DW_AT_byte_size nor DW_AT_bit_size are defined, this function - returns 0. */ - -static uint32_t -ctf_die_bitsize (dw_die_ref die) -{ - dw_attr_node *attr_byte_size = get_AT (die, DW_AT_byte_size); - dw_attr_node *attr_bit_size = get_AT (die, DW_AT_bit_size); - - if (attr_bit_size) - return AT_unsigned (attr_bit_size); - else if (attr_byte_size) - return (AT_unsigned (attr_byte_size) * 8); - else - return 0; -} - -/* Generate CTF for base type (integer, boolean, real, fixed point and complex). - Important: the caller of this API must make sure that duplicate types are - not added. */ - -static ctf_id_t -gen_ctf_base_type (ctf_container_ref ctfc, dw_die_ref type) -{ - ctf_id_t type_id = CTF_NULL_TYPEID; - - ctf_encoding_t ctf_encoding = {0, 0, 0}; - - unsigned int encoding = get_AT_unsigned (type, DW_AT_encoding); - unsigned int bit_size = ctf_die_bitsize (type); - const char * name_string = get_AT_string (type, DW_AT_name); - - switch (encoding) - { - case DW_ATE_void: - - ctf_encoding.cte_format = CTF_INT_SIGNED; - ctf_encoding.cte_bits = 0; - - gcc_assert (name_string); - type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string, - &ctf_encoding, type); - - break; - case DW_ATE_boolean: - - ctf_encoding.cte_format = CTF_INT_BOOL; - ctf_encoding.cte_bits = bit_size; - - gcc_assert (name_string); - type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string, - &ctf_encoding, type); - break; - case DW_ATE_float: - { - unsigned int float_bit_size - = tree_to_uhwi (TYPE_SIZE (float_type_node)); - unsigned int double_bit_size - = tree_to_uhwi (TYPE_SIZE (double_type_node)); - unsigned int long_double_bit_size - = tree_to_uhwi (TYPE_SIZE (long_double_type_node)); - - if (bit_size == float_bit_size) - ctf_encoding.cte_format = CTF_FP_SINGLE; - else if (bit_size == double_bit_size) - ctf_encoding.cte_format = CTF_FP_DOUBLE; - else if (bit_size == long_double_bit_size) - ctf_encoding.cte_format = CTF_FP_LDOUBLE; - else - /* CTF does not have representation for other types. Skip them. */ - break; - - ctf_encoding.cte_bits = bit_size; - type_id = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string, - &ctf_encoding, type); - - break; - } - case DW_ATE_signed_char: - /* FALLTHROUGH */ - case DW_ATE_unsigned_char: - /* FALLTHROUGH */ - case DW_ATE_signed: - /* FALLTHROUGH */ - case DW_ATE_unsigned: - - if (encoding == DW_ATE_signed_char - || encoding == DW_ATE_unsigned_char) - ctf_encoding.cte_format |= CTF_INT_CHAR; - - if (encoding == DW_ATE_signed - || encoding == DW_ATE_signed_char) - ctf_encoding.cte_format |= CTF_INT_SIGNED; - - ctf_encoding.cte_bits = bit_size; - type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string, - &ctf_encoding, type); - break; - - case DW_ATE_complex_float: - { - unsigned int float_bit_size - = tree_to_uhwi (TYPE_SIZE (float_type_node)); - unsigned int double_bit_size - = tree_to_uhwi (TYPE_SIZE (double_type_node)); - unsigned int long_double_bit_size - = tree_to_uhwi (TYPE_SIZE (long_double_type_node)); - - if (bit_size == float_bit_size * 2) - ctf_encoding.cte_format = CTF_FP_CPLX; - else if (bit_size == double_bit_size * 2) - ctf_encoding.cte_format = CTF_FP_DCPLX; - else if (bit_size == long_double_bit_size * 2) - ctf_encoding.cte_format = CTF_FP_LDCPLX; - else - /* CTF does not have representation for other types. Skip them. */ - break; - - ctf_encoding.cte_bits = bit_size; - type_id = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string, - &ctf_encoding, type); - break; - } - default: - /* Ignore. */ - break; - } - - return type_id; -} - -/* Generate CTF for a pointer type. */ - -static ctf_id_t -gen_ctf_pointer_type (ctf_container_ref ctfc, dw_die_ref ptr_type) -{ - ctf_id_t type_id = CTF_NULL_TYPEID; - ctf_id_t ptr_type_id = CTF_NULL_TYPEID; - dw_die_ref pointed_type_die = ctf_get_AT_type (ptr_type); - - type_id = gen_ctf_type (ctfc, pointed_type_die); - - /* 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 - the gen_ctf_type call above. */ - if (ctf_type_exists (ctfc, ptr_type, &ptr_type_id)) - return ptr_type_id; - - ptr_type_id = ctf_add_pointer (ctfc, CTF_ADD_ROOT, type_id, ptr_type); - return ptr_type_id; -} - -/* Generate CTF for an array type. */ - -static ctf_id_t -gen_ctf_array_type (ctf_container_ref ctfc, dw_die_ref array_type) -{ - dw_die_ref c; - ctf_id_t array_elems_type_id = CTF_NULL_TYPEID; - - int vector_type_p = get_AT_flag (array_type, DW_AT_GNU_vector); - if (vector_type_p) - return array_elems_type_id; - - dw_die_ref array_elems_type = ctf_get_AT_type (array_type); - - /* First, register the type of the array elements if needed. */ - array_elems_type_id = gen_ctf_type (ctfc, array_elems_type); - - /* DWARF array types pretend C supports multi-dimensional arrays. - So for the type int[N][M], the array type DIE contains two - subrange_type children, the first with upper bound N-1 and the - second with upper bound M-1. - - CTF, on the other hand, just encodes each array type in its own - array type CTF struct. Therefore we have to iterate on the - children and create all the needed types. */ - - c = dw_get_die_child (array_type); - gcc_assert (c); - do - { - ctf_arinfo_t arinfo; - dw_die_ref array_index_type; - uint32_t array_num_elements; - - c = dw_get_die_sib (c); - - if (dw_get_die_tag (c) == DW_TAG_subrange_type) - { - dw_attr_node *upper_bound_at; - - array_index_type = ctf_get_AT_type (c); - - /* When DW_AT_upper_bound is used to specify the size of an - array in DWARF, it is usually an unsigned constant - specifying the upper bound index of the array. However, - for unsized arrays, such as foo[] or bar[0], - DW_AT_upper_bound is a signed integer constant - instead. */ - - upper_bound_at = get_AT (c, DW_AT_upper_bound); - if (upper_bound_at - && AT_class (upper_bound_at) == dw_val_class_unsigned_const) - /* This is the upper bound index. */ - array_num_elements = get_AT_unsigned (c, DW_AT_upper_bound) + 1; - else if (get_AT (c, DW_AT_count)) - array_num_elements = get_AT_unsigned (c, DW_AT_count); - else - { - /* This is a VLA of some kind. */ - array_num_elements = 0; - } - } - else if (dw_get_die_tag (c) == DW_TAG_enumeration_type) - { - array_index_type = 0; - array_num_elements = 0; - /* XXX writeme. */ - gcc_assert (1); - } - else - gcc_unreachable (); - - /* Ok, mount and register the array type. Note how the array - type we register here is the type of the elements in - subsequent "dimensions", if there are any. */ - - arinfo.ctr_nelems = array_num_elements; - if (array_index_type) - arinfo.ctr_index = gen_ctf_type (ctfc, array_index_type); - else - arinfo.ctr_index = gen_ctf_type (ctfc, ctf_array_index_die); - - arinfo.ctr_contents = array_elems_type_id; - if (!ctf_type_exists (ctfc, c, &array_elems_type_id)) - array_elems_type_id = ctf_add_array (ctfc, CTF_ADD_ROOT, &arinfo, - c); - } - while (c != dw_get_die_child (array_type)); - -#if 0 - /* Type de-duplication. - Consult the ctfc_types hash again before adding the CTF array type because - there can be cases where an array_type type may have been added by the - gen_ctf_type call above. */ - if (!ctf_type_exists (ctfc, array_type, &type_id)) - type_id = ctf_add_array (ctfc, CTF_ADD_ROOT, &arinfo, array_type); -#endif - - return array_elems_type_id; -} - -/* Generate CTF for a typedef. */ - -static ctf_id_t -gen_ctf_typedef (ctf_container_ref ctfc, dw_die_ref tdef) -{ - ctf_id_t tdef_type_id, tid; - const char *tdef_name = get_AT_string (tdef, DW_AT_name); - dw_die_ref tdef_type = ctf_get_AT_type (tdef); - - tid = gen_ctf_type (ctfc, tdef_type); - - /* Type de-duplication. - This is necessary because the ctf for the typedef may have been already - added due to the gen_ctf_type call above. */ - if (!ctf_type_exists (ctfc, tdef, &tdef_type_id)) - { - tdef_type_id = ctf_add_typedef (ctfc, CTF_ADD_ROOT, - tdef_name, - tid, - tdef); - } - return tdef_type_id; -} - -/* Generate CTF for a type modifier. - - If the given DIE contains a valid C modifier (like _Atomic), which is not - supported by CTF, then this function skips the modifier die and continues - with the underlying type. - - For all other cases, this function returns a CTF_NULL_TYPEID; -*/ - -static ctf_id_t -gen_ctf_modifier_type (ctf_container_ref ctfc, dw_die_ref modifier) -{ - uint32_t kind = CTF_K_MAX; - ctf_id_t modifier_type_id, qual_type_id; - dw_die_ref qual_type = ctf_get_AT_type (modifier); - - switch (dw_get_die_tag (modifier)) - { - case DW_TAG_const_type: kind = CTF_K_CONST; break; - case DW_TAG_volatile_type: kind = CTF_K_VOLATILE; break; - case DW_TAG_restrict_type: kind = CTF_K_RESTRICT; break; - case DW_TAG_atomic_type: break; - default: - return CTF_NULL_TYPEID; - } - - /* Register the type for which this modifier applies. */ - qual_type_id = gen_ctf_type (ctfc, qual_type); - - /* Skip generating a CTF modifier record for _Atomic as there is no - representation for it. */ - if (dw_get_die_tag (modifier) == DW_TAG_atomic_type) - return qual_type_id; - - gcc_assert (kind != CTF_K_MAX); - /* Now register the modifier itself. */ - if (!ctf_type_exists (ctfc, modifier, &modifier_type_id)) - modifier_type_id = ctf_add_reftype (ctfc, CTF_ADD_ROOT, - qual_type_id, kind, - modifier); - - return modifier_type_id; -} - -/* Generate CTF for a struct type. */ - -static ctf_id_t -gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, uint32_t kind) -{ - uint32_t bit_size = ctf_die_bitsize (sou); - int declaration_p = get_AT_flag (sou, DW_AT_declaration); - const char *sou_name = get_AT_string (sou, DW_AT_name); - - ctf_id_t sou_type_id; - - /* An incomplete structure or union type is represented in DWARF by - a structure or union DIE that does not have a size attribute and - that has a DW_AT_declaration attribute. This corresponds to a - CTF forward type with kind CTF_K_STRUCT. */ - if (bit_size == 0 && declaration_p) - return ctf_add_forward (ctfc, CTF_ADD_ROOT, - sou_name, kind, sou); - - /* This is a complete struct or union type. Generate a CTF type for - it if it doesn't exist already. */ - if (!ctf_type_exists (ctfc, sou, &sou_type_id)) - sou_type_id = ctf_add_sou (ctfc, CTF_ADD_ROOT, - sou_name, kind, bit_size / 8, - sou); - - /* Now process the struct members. */ - { - dw_die_ref c; - - c = dw_get_die_child (sou); - if (c) - do - { - const char *field_name; - dw_die_ref field_type; - HOST_WIDE_INT field_location; - ctf_id_t field_type_id; - - c = dw_get_die_sib (c); - - field_name = get_AT_string (c, DW_AT_name); - field_type = ctf_get_AT_type (c); - field_location = ctf_get_AT_data_member_location (c); - - /* Generate the field type. */ - field_type_id = gen_ctf_type (ctfc, field_type); - - /* If this is a bit-field, then wrap the field type - generated above with a CTF slice. */ - if (get_AT (c, DW_AT_bit_offset) - || get_AT (c, DW_AT_data_bit_offset)) - { - dw_attr_node *attr; - HOST_WIDE_INT bitpos = 0; - HOST_WIDE_INT bitsize = ctf_die_bitsize (c); - HOST_WIDE_INT bit_offset; - - /* The bit offset is given in bits and it may be - negative. */ - attr = get_AT (c, DW_AT_bit_offset); - if (attr) - { - if (AT_class (attr) == dw_val_class_unsigned_const) - bit_offset = AT_unsigned (attr); - else - bit_offset = AT_int (attr); - - if (BYTES_BIG_ENDIAN) - bitpos = field_location + bit_offset; - else - { - HOST_WIDE_INT bit_size; - - attr = get_AT (c, DW_AT_byte_size); - if (attr) - /* Explicit size given in bytes. */ - bit_size = AT_unsigned (attr) * 8; - else - /* Infer the size from the member type. */ - bit_size = ctf_die_bitsize (field_type); - - bitpos = (field_location - + bit_size - - bit_offset - - bitsize); - } - } - - /* In DWARF5 a data_bit_offset attribute is given with - the offset of the data from the beginning of the - struct. Acknowledge it if present. */ - attr = get_AT (c, DW_AT_data_bit_offset); - if (attr) - bitpos += AT_unsigned (attr); - - field_type_id = ctf_add_slice (ctfc, CTF_ADD_NONROOT, - field_type_id, - bitpos - field_location, - bitsize, - c); - } - - /* Add the field type to the struct or union type. */ - ctf_add_member_offset (ctfc, sou, - field_name, - field_type_id, - field_location); - } - while (c != dw_get_die_child (sou)); - } - - return sou_type_id; -} - -/* Generate CTF for a function type. */ - -static ctf_id_t -gen_ctf_function_type (ctf_container_ref ctfc, dw_die_ref function, - bool from_global_func) -{ - const char *function_name = get_AT_string (function, DW_AT_name); - dw_die_ref return_type = ctf_get_AT_type (function); - - ctf_funcinfo_t func_info; - uint32_t num_args = 0; - - ctf_id_t return_type_id; - ctf_id_t function_type_id; - - /* First, add the return type. */ - return_type_id = gen_ctf_type (ctfc, return_type); - func_info.ctc_return = return_type_id; - - /* Type de-duplication. - Consult the ctfc_types hash before adding the CTF function type. */ - if (ctf_type_exists (ctfc, function, &function_type_id)) - return function_type_id; - - /* Do a first pass on the formals to determine the number of - arguments, and whether the function type gets a varargs. */ - { - dw_die_ref c; - - c = dw_get_die_child (function); - if (c) - do - { - c = dw_get_die_sib (c); - - if (dw_get_die_tag (c) == DW_TAG_formal_parameter) - num_args += 1; - else if (dw_get_die_tag (c) == DW_TAG_unspecified_parameters) - { - func_info.ctc_flags |= CTF_FUNC_VARARG; - num_args += 1; - } - } - while (c != dw_get_die_child (function)); - } - - /* Note the number of typed arguments _includes_ the vararg. */ - func_info.ctc_argc = num_args; - - /* Type de-duplication has already been performed by now. */ - function_type_id = ctf_add_function (ctfc, CTF_ADD_ROOT, - function_name, - (const ctf_funcinfo_t *)&func_info, - function, - from_global_func); - - /* Second pass on formals: generate the CTF types corresponding to - them and add them as CTF function args. */ - { - dw_die_ref c; - unsigned int i = 0; - const char *arg_name; - ctf_id_t arg_type; - - c = dw_get_die_child (function); - if (c) - do - { - c = dw_get_die_sib (c); - - if (dw_get_die_tag (c) == DW_TAG_unspecified_parameters) - { - gcc_assert (i == num_args - 1); - /* Add an argument with type 0 and no name. */ - ctf_add_function_arg (ctfc, function, "", 0); - } - 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); - } - else - /* This is a local variable. Ignore. */ - continue; - } - while (c != dw_get_die_child (function)); - } - - return function_type_id; -} - -/* Generate CTF for an enumeration type. */ - -static ctf_id_t -gen_ctf_enumeration_type (ctf_container_ref ctfc, dw_die_ref enumeration) -{ - const char *enum_name = get_AT_string (enumeration, DW_AT_name); - unsigned int bit_size = ctf_die_bitsize (enumeration); - int declaration_p = get_AT_flag (enumeration, DW_AT_declaration); - - ctf_id_t enumeration_type_id; - - /* If this is an incomplete enum, generate a CTF forward for it and - be done. */ - if (declaration_p) - { - gcc_assert (enum_name); - return ctf_add_forward (ctfc, CTF_ADD_ROOT, enum_name, - CTF_K_ENUM, enumeration); - } - - /* If the size the enumerators is not specified then use the size of - the underlying type, which must be a base type. */ - if (bit_size == 0) - { - dw_die_ref type = ctf_get_AT_type (enumeration); - bit_size = ctf_die_bitsize (type); - } - - /* Generate a CTF type for the enumeration. */ - enumeration_type_id = ctf_add_enum (ctfc, CTF_ADD_ROOT, - enum_name, bit_size / 8, enumeration); - - /* Process the enumerators. */ - { - dw_die_ref c; - - c = dw_get_die_child (enumeration); - if (c) - do - { - const char *enumerator_name; - dw_attr_node *enumerator_value; - HOST_WIDE_INT value_wide_int; - - c = dw_get_die_sib (c); - - enumerator_name = get_AT_string (c, DW_AT_name); - enumerator_value = get_AT (c, DW_AT_const_value); - - /* enumerator_value can be either a signed or an unsigned - constant value. */ - if (AT_class (enumerator_value) == dw_val_class_unsigned_const - || (AT_class (enumerator_value) - == dw_val_class_unsigned_const_implicit)) - value_wide_int = AT_unsigned (enumerator_value); - else - value_wide_int = AT_int (enumerator_value); - - ctf_add_enumerator (ctfc, enumeration_type_id, - enumerator_name, value_wide_int, enumeration); - } - while (c != dw_get_die_child (enumeration)); - } - - return enumeration_type_id; -} - -/* Add a CTF variable record for the given input DWARF DIE. */ - -static void -gen_ctf_variable (ctf_container_ref ctfc, dw_die_ref die) -{ - const char *var_name = get_AT_string (die, DW_AT_name); - dw_die_ref var_type = ctf_get_AT_type (die); - unsigned int external_vis = get_AT_flag (die, DW_AT_external); - ctf_id_t var_type_id; - - /* Avoid duplicates. */ - if (ctf_dvd_lookup (ctfc, die)) - return; - - /* Add the type of the variable. */ - var_type_id = gen_ctf_type (ctfc, var_type); - - /* Generate the new CTF variable and update global counter. */ - (void) ctf_add_variable (ctfc, var_name, var_type_id, die, external_vis); - ctfc->ctfc_num_global_objts += 1; -} - -/* Add a CTF function record for the given input DWARF DIE. */ - -static void -gen_ctf_function (ctf_container_ref ctfc, dw_die_ref die) -{ - ctf_id_t function_type_id; - /* Type de-duplication. - Consult the ctfc_types hash before adding the CTF function type. */ - if (ctf_type_exists (ctfc, die, &function_type_id)) - return; - - /* Add the type of the function and update the global functions - 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 */); - ctfc->ctfc_num_global_funcs += 1; -} - -/* Add CTF type record(s) for the given input DWARF DIE and return its type id. - - If there is already a CTF type corresponding to the given DIE, then - this function returns the type id of the existing type. - - If the given DIE is not recognized as a type, then this function - returns CTF_NULL_TYPEID. */ - -static ctf_id_t -gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die) -{ - ctf_id_t type_id; - int unrecog_die = false; - - if (ctf_type_exists (ctfc, die, &type_id)) - return type_id; - - switch (dw_get_die_tag (die)) - { - case DW_TAG_base_type: - type_id = gen_ctf_base_type (ctfc, die); - break; - case DW_TAG_pointer_type: - type_id = gen_ctf_pointer_type (ctfc, die); - break; - case DW_TAG_typedef: - type_id = gen_ctf_typedef (ctfc, die); - break; - case DW_TAG_array_type: - type_id = gen_ctf_array_type (ctfc, die); - break; - case DW_TAG_structure_type: - type_id = gen_ctf_sou_type (ctfc, die, CTF_K_STRUCT); - break; - case DW_TAG_union_type: - type_id = gen_ctf_sou_type (ctfc, die, CTF_K_UNION); - break; - case DW_TAG_subroutine_type: - type_id = gen_ctf_function_type (ctfc, die, - false /* from_global_func */); - break; - case DW_TAG_enumeration_type: - type_id = gen_ctf_enumeration_type (ctfc, die); - break; - case DW_TAG_atomic_type: - /* FALLTHROUGH */ - case DW_TAG_const_type: - /* FALLTHROUGH */ - case DW_TAG_restrict_type: - /* FALLTHROUGH */ - case DW_TAG_volatile_type: - type_id = gen_ctf_modifier_type (ctfc, die); - break; - case DW_TAG_unspecified_type: - { - const char *name = get_AT_string (die, DW_AT_name); - - if (name && strcmp (name, "void") == 0) - type_id = gen_ctf_void_type (ctfc); - else - type_id = CTF_NULL_TYPEID; - - break; - } - case DW_TAG_reference_type: - type_id = CTF_NULL_TYPEID; - break; - default: - /* Unrecognized DIE. */ - unrecog_die = true; - type_id = CTF_NULL_TYPEID; - break; - } - - /* For all types unrepresented in CTF, use an explicit CTF type of kind - CTF_K_UNKNOWN. */ - if ((type_id == CTF_NULL_TYPEID) && (!unrecog_die)) - type_id = gen_ctf_unknown_type (ctfc); - - return type_id; -} - -/* Prepare for output and write out the CTF debug information. */ - -static void -ctf_debug_finalize (const char *filename, bool btf) -{ - if (btf) - { - btf_output (filename); - btf_finalize (); - } - - else - { - /* Emit the collected CTF information. */ - ctf_output (filename); - - /* Reset the CTF state. */ - ctf_finalize (); - } -} - -bool -ctf_do_die (dw_die_ref die) -{ - ctf_container_ref tu_ctfc = ctf_get_tu_ctfc (); - - /* Note how we tell the caller to continue traversing children DIEs - if this DIE didn't result in CTF records being added. */ - if (dw_get_die_tag (die) == DW_TAG_variable) - { - gen_ctf_variable (tu_ctfc, die); - return false; - } - else if (dw_get_die_tag (die) == DW_TAG_subprogram) - { - gen_ctf_function (tu_ctfc, die); - return false; - } - else - return gen_ctf_type (tu_ctfc, die) == CTF_NULL_TYPEID; -} - -/* Initialize CTF subsystem for CTF debug info generation. */ - -void -ctf_debug_init (void) -{ - /* First, initialize the CTF subsystem. */ - ctf_init (); - - /* Create a couple of DIE structures that we may need. */ - ctf_void_die = new_die_raw (DW_TAG_unspecified_type); - add_name_attribute (ctf_void_die, "void"); - ctf_array_index_die - = base_type_die (integer_type_node, 0 /* reverse */); - add_name_attribute (ctf_array_index_die, "int"); - ctf_unknown_die = new_die_raw (DW_TAG_unspecified_type); - add_name_attribute (ctf_unknown_die, "unknown"); -} - -/* Preprocess the CTF debug information after initialization. */ - -void -ctf_debug_init_postprocess (bool btf) -{ - /* Only BTF requires postprocessing right after init. */ - if (btf) - btf_init_postprocess (); -} - -/* Early finish CTF/BTF debug info. */ - -void -ctf_debug_early_finish (const char * filename) -{ - /* Emit CTF debug info early always. */ - if (ctf_debug_info_level > CTFINFO_LEVEL_NONE - /* Emit BTF debug info early if CO-RE relocations are not - required. */ - || (btf_debuginfo_p () && !btf_with_core_debuginfo_p ())) - ctf_debug_finalize (filename, btf_debuginfo_p ()); -} - -/* Finish CTF/BTF debug info emission. */ - -void -ctf_debug_finish (const char * filename) -{ - /* Emit BTF debug info here when CO-RE relocations need to be generated. - BTF with CO-RE relocations needs to be generated when CO-RE is in effect - for the BPF target. */ - if (btf_with_core_debuginfo_p ()) - { - gcc_assert (btf_debuginfo_p ()); - ctf_debug_finalize (filename, btf_debuginfo_p ()); - } -} - -#include "gt-dwarf2ctf.h" |