[PATCH 2/4] objdump: Add variable types and structure for DWARF info parsing
Guillaume VACHERIAS
guillaume.vacherias@foss.st.com
Tue Aug 19 02:12:25 GMT 2025
Introduce structures to represent DWARF debug information. Each structure
simplifies the parsing of attributes under DW_TAG_variable,
DW_TAG_pointer_type, DW_TAG_volatile_type, DW_TAG_const_type,
DW_TAG_union_type, DW_TAG_structure_type, DW_TAG_member, DW_TAG_array_type,
DW_TAG_subrange_type, DW_TAG_enumeration_type, DW_TAG_enumerator,
DW_TAG_typedef and DW_TAG_base_type.
Below is an example of a global variable `unsigned char foo`. The debug
information entry DW_TAG_variable gives the name (DW_AT_name) and location
(DW_AT_location) of the variable foo. It provides also its type with
DW_AT_type which is an offset that corresponds to the entry of
DW_TAG_base_type. Finally with DW_TAG_base_type we can determine the type
(DW_AT_name) and size (DW_AT_byte_size) of `foo`.
<1><1e>: Abbrev Number: 2 (DW_TAG_variable)
<1f> DW_AT_name : foo
<21> DW_AT_decl_file : 1
<22> DW_AT_decl_line : 1
<23> DW_AT_decl_column : 11
<24> DW_AT_type : <0x2e>
<28> DW_AT_external : 1
<28> DW_AT_location : 5 byte block: 3 0 80 0 0 (DW_OP_addr: 8000)
<1><2e>: Abbrev Number: 3 (DW_TAG_base_type)
<2f> DW_AT_byte_size : 1
<30> DW_AT_encoding : 8 (unsigned char)
<31> DW_AT_name : (indirect string, offset: 0x66): char
We declare in each structure a member `die_offset` which is the offset of the
debug entry in DWARF info section. Furthermore we use member `type` associated
with member `ptr_type` to indicate the kind of type the structure represents.
Hence these two fields let us determine the exact type of a variable or
member. For example, to know that `foo` variable is char type, the structure
for `foo` will have:
- member `type` set to `BASE_TYPE`.
- member `ptr_type` pointing to a base_type structure that describes the
char type.
binutils/
* dwarf.h (enum types): New definition. Useful to identify structure
type which holds DWARF information.
(base_type): New typedef. Hold DW_TAG_base_type information.
(type_def): Likewise for DW_TAG_typedef.
(enum_constant): Likewise for DW_TAG_enumerator.
(enum_type): Likewise for DW_TAG_enumeration_type.
(subrange_type): Likewise for DW_TAG_subrange_type.
(tab_type): Likewise for DW_TAG_array_type.
(member_type): Likewise for DW_TAG_member_type.
(member_parent): Likewise for DW_TAG_struct_type, DW_TAG_union_type.
(type_ref): Likewise for DW_TAG_pointer_type, DW_TAG_const_type and
DW_TAG_volatile_type.
(variable_type): Likewise for DW_TAG_variable_type.
(struct_type): New typedef from member_parent.
(union_type): Likewise.
(ptr_type): New typedef from type_ref.
(const_type): Likewise.
(volatile_type): Likewise.
(free_mapping_info_struct): New definition.
* dwarf.c (get_or_create_or_base_type): New function.
(get_or_create_type_def): Likewise.
(get_or_create_enum_constant): Likewise.
(get_or_create_enum_type): Likewise.
(get_or_create_subrange_type): Likewise.
(get_or_create_tab): Likewise.
(get_or_create_member_type): Likewise.
(get_or_create_member_parent): Likewise.
(get_or_create_type_ref): Likewise.
(get_or_create_variable_type): Likewise.
(free_base_type): Likewise.
(free_type_def): Likewise.
(free_enum_type): Likewise.
(free_tab_type): Likewise.
(free_member_parent): Likewise.
(free_struct_type): Likewise.
(free_type_ref): Likewise.
(free_ptr_type): Likewise.
(free_volatile_type): Likewise.
(free_const_type): Likewise.
(free_variable_type): Likewise.
(free_mapping_info_struct): Likewise.
(insert_element_in_list): Create and populate structures that hold
DWARF information to display global variable information.
* objdump.c (dump_global_variable_info): Free created and populated
structures.
---
binutils/dwarf.c | 809 ++++++++++++++++++++++++++++++++++++++++++++-
binutils/dwarf.h | 149 +++++++++
binutils/objdump.c | 1 +
3 files changed, 954 insertions(+), 5 deletions(-)
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 6b24828736b..90fed67e9a7 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -61,6 +61,19 @@ static int need_base_address;
static unsigned int num_debug_info_entries = 0;
static unsigned int alloc_num_debug_info_entries = 0;
static debug_info *debug_information = NULL;
+
+static base_type *base_type_list = NULL;
+static type_def *type_def_list = NULL;
+static enum_type *enum_type_list = NULL;
+static tab_type *tab_type_list = NULL;
+static struct_type *struct_type_list = NULL;
+static union_type *union_type_list = NULL;
+static ptr_type *ptr_type_list = NULL;
+static const_type *const_type_list = NULL;
+static volatile_type *volatile_type_list = NULL;
+static variable_type *variable_type_list = NULL;
+
+static int is_union = false;
/* Special value for num_debug_info_entries to indicate
that the .debug_info section could not be loaded/parsed. */
#define DEBUG_INFO_UNAVAILABLE (unsigned int) -1
@@ -1188,6 +1201,21 @@ get_location_expression (int die_tag,
{
case DW_OP_addr:
SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
+ if (die_tag == DW_TAG_variable && attribute == DW_AT_location)
+ {
+ if (variable_type_list == NULL)
+ {
+ fprintf (stderr,
+ _ ("m_var_map for DW_OP_addr should not be NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ if (!variable_type_list->has_location_addr)
+ {
+ variable_type_list->location_addr = uvalue;
+ variable_type_list->has_location_addr = true;
+ }
+ }
break;
case DW_OP_const1u:
SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
@@ -2567,13 +2595,206 @@ display_lang (uint64_t uvalue)
}
}
+static base_type *
+get_or_create_base_type (uint64_t die_offset)
+{
+ if (base_type_list == NULL || base_type_list->die_offset != die_offset)
+ {
+ base_type *ret = (base_type *)
+ xmalloc (sizeof (base_type));
+ ret->die_offset = die_offset;
+ ret->usize = 0;
+ ret->ssize = 0;
+ ret->next = base_type_list;
+ base_type_list = ret;
+ }
+ return base_type_list;
+}
+
+static type_def *
+get_or_create_type_def (uint64_t die_offset)
+{
+ if (type_def_list == NULL || type_def_list->die_offset != die_offset)
+ {
+ type_def *ret = (type_def *) xmalloc (
+ sizeof (type_def));
+ ret->name = NULL;
+ ret->die_offset = die_offset;
+ ret->ptr_die_offset = 0;
+ ret->type = UNKNOWN;
+ ret->ptr_type = NULL;
+ ret->next = type_def_list;
+ type_def_list = ret;
+ }
+ return type_def_list;
+}
+
+static enum_constant *
+get_or_create_enum_constant (enum_type *head, uint64_t die_offset)
+{
+ if (head == NULL)
+ {
+ fprintf (stderr,
+ _ ("get_or_create_enum_elt: head should not be NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ if (head->enumeration == NULL || head->enumeration->die_offset != die_offset)
+ {
+ enum_constant *enum_const = (enum_constant *)
+ xmalloc (sizeof (enum_constant));
+ enum_const->die_offset = die_offset;
+ enum_const->name = NULL;
+ enum_const->value = 0;
+ enum_const->next = head->enumeration;
+ head->enumeration = enum_const;
+ }
+ return head->enumeration;
+}
+
+static enum_type *
+get_or_create_enum_type (uint64_t die_offset)
+{
+ if (enum_type_list == NULL || enum_type_list->die_offset != die_offset)
+ {
+ enum_type *ret = (enum_type *)
+ xmalloc (sizeof (enum_type));
+ ret->name = NULL;
+ ret->die_offset = die_offset;
+ ret->usize = 0;
+ ret->ssize = 0;
+ ret->enumeration = NULL;
+ ret->next = enum_type_list;
+ enum_type_list = ret;
+ }
+ return enum_type_list;
+}
+
+static subrange_type *
+get_or_create_subrange_type (tab_type * head, uint64_t die_offset)
+{
+ if (head == NULL)
+ {
+ fprintf (stderr,
+ _ ("get_or_create_subrange_type: head should not be NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ if (head->subrange == NULL || head->subrange->die_offset != die_offset)
+ {
+ subrange_type *ret = (subrange_type *)
+ xmalloc (sizeof (subrange_type));
+ ret->die_offset = die_offset;
+ ret->usize = 0;
+ ret->ssize = 0;
+ ret->next = head->subrange;
+ head->subrange = ret;
+ }
+ return head->subrange;
+}
+
+static tab_type *
+get_or_create_tab (uint64_t die_offset)
+{
+ if (tab_type_list == NULL || tab_type_list->die_offset != die_offset)
+ {
+ tab_type *ret = (tab_type *)
+ xmalloc (sizeof (tab_type));
+ ret->die_offset = die_offset;
+ ret->subrange = NULL;
+ ret->type = UNKNOWN;
+ ret->ptr_type = NULL;
+ ret->next = tab_type_list;
+ tab_type_list = ret;
+ }
+ return tab_type_list;
+}
+
+static member_type *
+get_or_create_member_type (member_type *head, uint64_t die_offset)
+{
+ if (head == NULL || head->die_offset != die_offset)
+ {
+ member_type *ret = (member_type *) xmalloc (sizeof (member_type));
+ ret->die_offset = die_offset;
+ ret->ptr_die_offset = 0;
+ ret->member_offset = 0;
+ ret->name = NULL;
+ ret->type = UNKNOWN;
+ ret->ptr_type = NULL;
+ ret->next = head;
+ head = ret;
+ }
+ return head;
+}
+
+static member_parent *
+get_or_create_member_parent (member_parent **head, uint64_t die_offset)
+{
+ if (*head == NULL || (*head)->die_offset != die_offset)
+ {
+ member_parent *ret = (member_parent *)
+ xmalloc (sizeof (member_parent));
+ ret->die_offset = die_offset;
+ ret->usize = 0;
+ ret->ssize = 0;
+ ret->name = NULL;
+ ret->members = NULL;
+ ret->displayed = false;
+ ret->next = *head;
+ *head = ret;
+ }
+ return *head;
+}
+
+static type_ref *
+get_or_create_type_ref (type_ref **head, uint64_t die_offset)
+{
+ if (*head == NULL || (*head)->die_offset != die_offset)
+ {
+ type_ref *ret = (type_ref *)
+ xmalloc (sizeof (type_ref));
+ ret->die_offset = die_offset;
+ ret->ptr_die_offset = 0;
+ ret->usize = 0;
+ ret->ssize = 0;
+ ret->type = UNKNOWN;
+ ret->ptr_type = NULL;
+ ret->next = *head;
+ *head = ret;
+ }
+ return *head;
+}
+
+static variable_type *
+get_or_create_variable_type (uint64_t die_offset)
+{
+ if (variable_type_list == NULL
+ || variable_type_list->die_offset != die_offset)
+ {
+ variable_type *ret = (variable_type *)
+ xmalloc (sizeof (variable_type));
+ ret->die_offset = die_offset;
+ ret->ptr_die_offset = 0;
+ ret->location_addr = 0;
+ ret->has_location_addr = false;
+ ret->name = NULL;
+ ret->type = UNKNOWN;
+ ret->ptr_type = NULL;
+ ret->total_size = 0;
+ ret->next = variable_type_list;
+ variable_type_list = ret;
+ }
+ return variable_type_list;
+}
+
static void
insert_element_in_list (enum dwarf_tag dw_tag,
- enum dwarf_attribute dw_attr ATTRIBUTE_UNUSED,
- uint64_t die_offset ATTRIBUTE_UNUSED,
- uint64_t *uvalue ATTRIBUTE_UNUSED,
- int64_t *svalue ATTRIBUTE_UNUSED,
- const unsigned char *data ATTRIBUTE_UNUSED)
+ enum dwarf_attribute dw_attr,
+ uint64_t die_offset,
+ uint64_t *uvalue,
+ int64_t *svalue,
+ const unsigned char *data)
{
/* TODO: Retrieve attributes information from
below dwarf entries tag. */
@@ -2581,33 +2802,441 @@ insert_element_in_list (enum dwarf_tag dw_tag,
{
/* Base type. */
case DW_TAG_base_type:
+ {
+ base_type *base = get_or_create_base_type (die_offset);
+ if (dw_attr == DW_AT_byte_size)
+ {
+ if (uvalue == NULL && svalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list:"
+ " DW_TAG_base_type-DW_AT_byte_size"
+ " uvalue and svalue are NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ base->usize = ((uvalue != NULL) ? *uvalue : 0);
+ base->ssize = ((svalue != NULL) ? *svalue : 0);
+ }
+ else if (dw_attr == DW_AT_name)
+ {
+ if (uvalue == NULL && data == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: DW_TAG_base_type-DW_AT_name "
+ " uvalue and data are NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ if (data != NULL)
+ base->name = data;
+ else if (uvalue != NULL)
+ base->name = fetch_indirect_string (*uvalue);
+ else
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_base_type-DW_AT_name no name!\n"));
+ }
+ }
break;
/* typedef. */
case DW_TAG_typedef:
+ {
+ type_def *type = get_or_create_type_def (die_offset);
+ if (dw_attr == DW_AT_type)
+ {
+ if (uvalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list:"
+ " DW_TAG_typedef-DW_AT_type uvalue"
+ " and svalue are NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ type->ptr_die_offset = *uvalue;
+ }
+ else if (dw_attr == DW_AT_name)
+ {
+ if (uvalue == NULL && data == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: DW_TAG_typedef-DW_AT_type "
+ "uvalue and data are NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ if (data != NULL)
+ type->name = data;
+ else if (uvalue != NULL)
+ type->name = fetch_indirect_string (*uvalue);
+ else
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_typedef-DW_AT_type no name!\n"));
+ }
+ }
break;
/* enumeration. */
case DW_TAG_enumerator:
+ {
+ enum_constant *head = get_or_create_enum_constant (
+ enum_type_list, die_offset);
+ if (dw_attr == DW_AT_name)
+ {
+ if (data != NULL)
+ head->name = data;
+ else if (uvalue != NULL)
+ head->name = fetch_indirect_string (*uvalue);
+ else
+ fprintf (stderr,
+ _ ("insert_element_in_list:"
+ "DW_TAG_enumerator-DW_AT_name no name!\n"));
+ }
+ else if (dw_attr == DW_AT_const_value)
+ {
+ if (uvalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: DW_TAG_enumerator-DW_AT_name"
+ "uvalue!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ head->value = *uvalue;
+ }
+ }
break;
case DW_TAG_enumeration_type:
+ {
+ enum_type *head = get_or_create_enum_type (die_offset);
+ if (dw_attr == DW_AT_name)
+ {
+ if (uvalue == NULL && data == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list:"
+ "DW_TAG_enumeration_type-DW_AT_name uvalue "
+ "and data are NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ if (data != NULL)
+ head->name = data;
+ else if (uvalue != NULL)
+ head->name = fetch_indirect_string (*uvalue);
+ else
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_enumeration_type-DW_AT_name no name!\n"));
+ }
+ else if (dw_attr == DW_AT_byte_size)
+ {
+ if (uvalue == NULL && svalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_enumeration_type-DW_AT_byte_size"
+ "uvalue and svalue are NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ head->usize = ((uvalue != NULL) ? *uvalue : 0);
+ head->ssize = ((svalue != NULL) ? *svalue : 0);
+ }
+ }
break;
/* Array type. */
case DW_TAG_subrange_type:
+ {
+ subrange_type *head = get_or_create_subrange_type (tab_type_list,
+ die_offset);
+ if (dw_attr == DW_AT_upper_bound
+ || dw_attr == DW_AT_count)
+ {
+ if (uvalue == NULL && svalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list:"
+ "DW_TAG_subrange_type-DW_AT_upper_bound-DW_AT_count "
+ "uvalue and svalue are NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ if (dw_attr == DW_AT_upper_bound)
+ {
+ head->ssize = ((svalue != NULL) ? *svalue + 1 : 0);
+ head->usize = ((uvalue != NULL) ? *uvalue + 1 : 0);
+ }
+ else if (dw_attr == DW_AT_count)
+ {
+ head->ssize = ((svalue != NULL) ? *svalue : 0);
+ head->usize = ((uvalue != NULL) ? *uvalue : 0);
+ }
+ }
+ }
break;
case DW_TAG_array_type:
+ {
+ tab_type *head = get_or_create_tab (die_offset);
+ if (dw_attr == DW_AT_type)
+ {
+ if (uvalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_array_type-DW_AT_type "
+ "uvalue and svalue are NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ head->ptr_die_offset = *uvalue;
+ }
+ }
break;
/* Memnber type. */
case DW_TAG_member:
+ {
+ member_type *member = NULL;
+ if (is_union)
+ {
+ member = get_or_create_member_type (union_type_list->members,
+ die_offset);
+ if (union_type_list->members == NULL
+ || union_type_list->members->die_offset != die_offset)
+ {
+ member->next = union_type_list->members;
+ union_type_list->members = member;
+ }
+ else
+ union_type_list->members = member;
+ }
+ else
+ {
+ member = get_or_create_member_type (struct_type_list->members,
+ die_offset);
+ if (struct_type_list->members == NULL
+ || struct_type_list->members->die_offset != die_offset)
+ {
+ member->next = struct_type_list->members;
+ struct_type_list->members = member;
+ }
+ else
+ struct_type_list->members = member;
+ }
+ if (dw_attr == DW_AT_name)
+ {
+ if (uvalue == NULL && data == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_member-DW_AT_name "
+ "uvalue and data are NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ if (data != NULL)
+ member->name = data;
+ else if (uvalue != NULL)
+ member->name = fetch_indirect_string (*uvalue);
+ else
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_member-DW_AT_name no name!\n"));
+ }
+ else if (dw_attr == DW_AT_type)
+ {
+ if (uvalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_member-DW_AT_type uvalue "
+ "is NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ member->ptr_die_offset = *uvalue;
+ }
+ else if (dw_attr == DW_AT_data_member_location)
+ {
+ if (svalue == NULL && uvalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_member-DW_AT_data_member_location svalue "
+ "and uvalue are NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ if (svalue != NULL)
+ member->member_offset = *svalue;
+ if (uvalue != NULL)
+ member->member_offset = *uvalue;
+ }
+ }
break;
/* Structure type. */
case DW_TAG_structure_type:
/* Union type. */
case DW_TAG_union_type:
+ {
+ member_parent *head = NULL;
+ if (dw_tag == DW_TAG_union_type)
+ {
+ is_union = true;
+ head = get_or_create_member_parent (&union_type_list, die_offset);
+ }
+ else if (dw_tag == DW_TAG_structure_type)
+ {
+ is_union = false;
+ head = get_or_create_member_parent (&struct_type_list,
+ die_offset);
+ }
+ if (dw_attr == DW_AT_name)
+ {
+ if (uvalue == NULL && data == NULL)
+ {
+ fprintf (stderr, _ ("insert_element_in_list: "
+ "DW_TAG_union_type/DW_TAG_structure_type-DW_AT_name "
+ "uvalue and data are NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ if (data != NULL)
+ head->name = data;
+ else if (uvalue != NULL)
+ head->name = fetch_indirect_string (*uvalue);
+ else
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_union_type/DW_TAG_structure_type-DW_AT_byte_size "
+ "uvalue and svalue are NULL!\n"));
+ }
+ else if (dw_attr == DW_AT_byte_size)
+ {
+ if (uvalue == NULL && svalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_union_type/DW_TAG_structure_type-DW_AT_byte_size "
+ "uvalue and svalue are NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ head->usize = ((uvalue != NULL) ? *uvalue : 0);
+ head->ssize = ((svalue != NULL) ? *svalue : 0);
+ }
+ }
break;
case DW_TAG_const_type:
case DW_TAG_volatile_type:
case DW_TAG_pointer_type:
+ {
+ type_ref *head = NULL;
+ if (dw_tag == DW_TAG_const_type)
+ head = get_or_create_type_ref (&const_type_list, die_offset);
+ else if (dw_tag == DW_TAG_volatile_type)
+ head = get_or_create_type_ref (&volatile_type_list, die_offset);
+ else if (dw_tag == DW_TAG_pointer_type)
+ head = get_or_create_type_ref (&ptr_type_list, die_offset);
+ if (dw_attr == DW_AT_type)
+ {
+ if (uvalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_const_type/"
+ "DW_TAG_volatile_type/"
+ "DW_TAG_pointer_type-DW_AT_type "
+ "uvalue should not be NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ head->ptr_die_offset = *uvalue;
+ }
+ if (dw_attr == DW_AT_byte_size
+ && dw_tag == DW_TAG_pointer_type)
+ {
+ if (uvalue == NULL && svalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_const_type/"
+ "DW_TAG_volatile_type/"
+ "DW_TAG_pointer_type-DW_AT_type "
+ "uvalue and svalue should not be NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ head->usize = ((uvalue != NULL) ? *uvalue : 0);
+ head->ssize = ((svalue != NULL) ? *svalue : 0);
+ }
+ }
break;
case DW_TAG_variable:
+ {
+ variable_type *head = get_or_create_variable_type (die_offset);
+ if (dw_attr == DW_AT_name)
+ {
+ if (uvalue == NULL
+ && data == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_variable-DW_AT_name uvalue, "
+ "svalue and data are NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ if (data != NULL)
+ head->name = data;
+ else if (uvalue != NULL)
+ head->name = fetch_indirect_string (*uvalue);
+ else
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_variable-DW_AT_name no name!\n"));
+ }
+ else if (dw_attr == DW_AT_type)
+ {
+ if (uvalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_variable-DW_AT_type uvalue "
+ "is NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ head->ptr_die_offset = *uvalue;
+ }
+ else if (dw_attr == DW_AT_specification)
+ {
+ if (uvalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_variable-DW_AT_sepecification uvalue "
+ "is NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ head->ptr_die_offset = *uvalue;
+ }
+ else if (dw_attr == DW_AT_abstract_origin)
+ {
+ if (uvalue == NULL)
+ {
+ fprintf (stderr,
+ _ ("insert_element_in_list: "
+ "DW_TAG_variable-DW_AT_abstract_origin uvalue "
+ "is NULL!\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ }
+ head->ptr_die_offset = *uvalue;
+ }
+ }
break;
default:
break;
@@ -13260,3 +13889,173 @@ struct dwarf_section_display debug_displays[] =
/* A static assertion. */
extern int debug_displays_assert[ARRAY_SIZE (debug_displays) == max ? 1 : -1];
+
+static void
+free_base_type (void)
+{
+ base_type *current = base_type_list;
+ base_type *next = NULL;
+ while (current != NULL)
+ {
+ next = current->next;
+ free (current);
+ current = next;
+ }
+ base_type_list = NULL;
+}
+
+static void
+free_type_def (void)
+{
+ type_def *current = type_def_list;
+ type_def *next = NULL;
+ while (current != NULL)
+ {
+ next = current->next;
+ free (current);
+ current = next;
+ }
+ type_def_list = NULL;
+}
+
+static void
+free_enum_type (void)
+{
+ enum_type *current = enum_type_list;
+ enum_type *next = NULL;
+ while (current != NULL)
+ {
+ next = current->next;
+ enum_constant *current_enums = current->enumeration;
+ enum_constant *next_enums = NULL;
+ while (current_enums != NULL)
+ {
+ next_enums = current_enums->next;
+ free (current_enums);
+ current_enums = next_enums;
+ }
+ current->enumeration = NULL;
+ free (current);
+ current = next;
+ }
+ enum_type_list = NULL;
+}
+
+static void
+free_tab_type (void)
+{
+ tab_type *current = tab_type_list;
+ tab_type *next = NULL;
+ while (current != NULL)
+ {
+ next = current->next;
+ subrange_type *current_subrange = current->subrange;
+ subrange_type *next_subrange = NULL;
+ while (current_subrange != NULL)
+ {
+ next_subrange = current_subrange->next;
+ free (current_subrange);
+ current_subrange = next_subrange;
+ }
+ current->subrange = NULL;
+ free (current);
+ current = next;
+ }
+ tab_type_list = NULL;
+}
+
+static void
+free_member_parent (member_parent **head)
+{
+ member_parent *current = *head;
+ member_parent *next = NULL;
+ while (current != NULL)
+ {
+ next = current->next;
+ member_type *current_member = current->members;
+ member_type *next_member = NULL;
+ while (current_member != NULL)
+ {
+ next_member = current_member->next;
+ free (current_member);
+ current_member = next_member;
+ }
+ current->members = NULL;
+ free (current);
+ current = next;
+ }
+ *head = NULL;
+}
+
+static void
+free_struct_type (void)
+{
+ free_member_parent (&struct_type_list);
+}
+
+static void
+free_union_type (void)
+{
+ free_member_parent (&union_type_list);
+}
+
+static void
+free_type_ref (type_ref *head)
+{
+ type_ref *current = head;
+ type_ref *next = NULL;
+ while (current != NULL)
+ {
+ next = current->next;
+ free (current);
+ current = next;
+ }
+ head = NULL;
+}
+
+static void
+free_ptr_type (void)
+{
+ free_type_ref (ptr_type_list);
+}
+
+static void
+free_volatile_type (void)
+{
+ free_type_ref (volatile_type_list);
+}
+
+static void
+free_const_type (void)
+{
+ free_type_ref (const_type_list);
+}
+
+static void
+free_variable_type (void)
+{
+ variable_type *current = variable_type_list;
+ variable_type *next = NULL;
+ while (current != NULL)
+ {
+ next = current->next;
+ free (current);
+ current = next;
+ }
+ variable_type_list = NULL;
+}
+
+void
+free_mapping_info_struct ()
+{
+ free_base_type ();
+ free_type_def ();
+ free_enum_type ();
+ free_tab_type ();
+ free_struct_type ();
+ free_union_type ();
+ free_ptr_type ();
+ free_volatile_type ();
+ free_const_type ();
+ free_variable_type ();
+}
diff --git a/binutils/dwarf.h b/binutils/dwarf.h
index 8efd0c37b5b..2c1792cbad2 100644
--- a/binutils/dwarf.h
+++ b/binutils/dwarf.h
@@ -71,6 +71,154 @@ typedef struct
}
DWARF2_Internal_ARange;
+enum types
+{
+ UNKNOWN = 0,
+ BASE_TYPE,
+ TYPE_DEF,
+ ENUM_TYPE,
+ TAB_TYPE,
+ MEMBER_TYPE,
+ STRUCT_TYPE,
+ UNION_TYPE,
+ PTR_TYPE,
+ VOLATILE_TYPE,
+ CONST_TYPE,
+ VARIABLE_TYPE
+};
+
+/* Container for map info information to be generated. */
+typedef struct base_type
+{
+ uint64_t die_offset;
+ uint64_t usize;
+ int64_t ssize;
+ const unsigned char *name;
+
+ struct base_type *next;
+}
+base_type;
+
+typedef struct type_def
+{
+ const unsigned char *name;
+ uint64_t die_offset;
+ uint64_t ptr_die_offset;
+
+ enum types type;
+ void *ptr_type;
+ struct type_def *next;
+}
+type_def;
+
+typedef struct enum_constant
+{
+ uint64_t die_offset;
+ uint64_t value;
+ const unsigned char *name;
+
+ struct enum_constant *next;
+}
+enum_constant;
+
+typedef struct enum_type
+{
+ uint64_t die_offset;
+ uint64_t usize;
+ int64_t ssize;
+ const unsigned char *name;
+ enum_constant *enumeration;
+
+ struct enum_type *next;
+}
+enum_type;
+
+typedef struct subrange_type
+{
+ uint64_t die_offset;
+ uint64_t usize;
+ int64_t ssize;
+
+ struct subrange_type *next;
+}
+subrange_type;
+
+typedef struct tab_type
+{
+ uint64_t die_offset;
+ uint64_t ptr_die_offset;
+ subrange_type *subrange;
+
+ enum types type;
+ void *ptr_type;
+ struct tab_type *next;
+}
+tab_type;
+
+typedef struct member_type
+{
+ uint64_t die_offset;
+ uint64_t ptr_die_offset;
+ int64_t member_offset;
+ const unsigned char *name;
+
+ enum types type;
+ void *ptr_type;
+ struct member_type *next;
+}
+member_type;
+
+typedef struct member_parent
+{
+ uint64_t die_offset;
+ uint64_t usize;
+ int64_t ssize;
+ const unsigned char *name;
+ member_type *members;
+ bool displayed; /* Treat nested structure. */
+
+ struct member_parent *next;
+}
+member_parent;
+
+typedef member_parent struct_type;
+typedef member_parent union_type;
+
+typedef struct type_ref
+{
+ uint64_t die_offset;
+ uint64_t ptr_die_offset;
+ uint64_t usize;
+ int64_t ssize;
+
+ enum types type;
+ void *ptr_type;
+ struct type_ref *next;
+}
+type_ref;
+
+typedef struct type_ref ptr_type;
+typedef struct type_ref const_type;
+typedef struct type_ref volatile_type;
+
+typedef struct variable_type
+{
+ /* field where information retrievable by parsing DWARF. */
+ uint64_t die_offset;
+ uint64_t ptr_die_offset;
+ uint64_t location_addr; /* DW_OP_addr value. */
+ uint64_t ttsize;
+ int has_location_addr;
+ const unsigned char *name;
+
+ /* field where information retrievable by resolving the type. */
+ enum types type;
+ void *ptr_type;
+ uint64_t total_size;
+ struct variable_type *next;
+}
+variable_type;
+
/* N.B. The order here must match the order in debug_displays. */
enum dwarf_section_display_enum
@@ -253,6 +401,7 @@ extern void close_debug_file (void *);
extern void *open_debug_file (const char *);
extern void free_debug_memory (void);
+extern void free_mapping_info_struct (void);
extern int dwarf_select_sections_by_names (const char *);
extern int dwarf_select_sections_by_letters (const char *);
diff --git a/binutils/objdump.c b/binutils/objdump.c
index e955cf8ec89..1e14ffa4228 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -4563,6 +4563,7 @@ dump_global_variable_info (bfd *abfd, asection *section,
if (load_specific_debug_section (info, section, abfd))
{
debug_displays [debug_variable_info].display (sec, abfd);
+ free_mapping_info_struct ();
free_debug_section (info);
}
}
--
2.25.1
More information about the Binutils
mailing list