[PATCH v3 4/5] objdump: Link and display all variables information
Guillaume VACHERIAS
guillaume.vacherias@foss.st.com
Mon Sep 1 17:50:43 GMT 2025
Implement linking mechanism to recursively resolve the DWARF type information
for variables, members and other type constructs. The linking mechanism is
central to populating fields`type` and `ptr_type` in the various type
structures.
Implement the display for variables and types. It is based on recursively
accessing fields `type` and `ptr_type`, allowing the system to print complex
types such as pointers to structs, arrays of typedefs, or nested const or
volatile types. When printing a variable or member, the code checks the `type`
field to determine the kind of type, and then follows the `ptr_type` pointer
to the next type structure.
binutils/
* dwarf.h (resolve_and_display_variable_info): New definition.
* dwarf.c (PRINT_SPACE, PRINT_LBRACE, PRINT_RBRACE): New macros.
(display_base_type): New function. Display information hold by
base_type structure.
(display_type_def): Likewise for type_def structure.
(display_enum): Likewise for enum_constant structure.
(display_enum_type): Likewise for enum_type structure.
(display_subrange_type): Likewise for subrange_type structure.
(display_tab_type): Likewise for tab_type structure.
(display_member_type): Likewise for member_type structure.
(display_member_parent): Likewise for member_parent structure.
(display_ptr_type): Likewise for ptr_type structure.
(display_variable_type): Likewise for variable_type structure.
(do_link_variable_information): New function. Link a structure which
represents a DWARF information entry to another by populating fields
`type` and `ptr_type`.
(link_variable_information): New function. Go through all existing
structures that hold DWARF information to link each variable_type
element to the type of structure it represents.
(is_nested_structure): New function. Return true if the type of
structure is known else return false, useful to treat nested
structures.
(compute_variable_ttsize): New function. Recursively go through
variable_type element and its structure information to calculate the
total size.
(reset_displayed_field): New function. Set field `displayed` of
member_parent to false to mark already displayed information for a
nested structure field.
(do_resolve_and_display_variable_info): New function. Recursively go
through all element in variable_type_list to link structure type
information and call display function to dump information.
(resolve_and_display_variable_info): New function.
* objdump.c (dump_global_variable_info): Add call to
resolve_and_display_variable_info function.
Signed-off-by: Guillaume VACHERIAS <guillaume.vacherias@foss.st.com>
---
binutils/ChangeLog | 26 ++
binutils/dwarf.c | 590 +++++++++++++++++++++++++++++++++++++++++++++
binutils/dwarf.h | 1 +
binutils/objdump.c | 1 +
4 files changed, 618 insertions(+)
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index cc2ed133ad7..97513d3135c 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -27,6 +27,31 @@
free_mapping_info_struct): Likewise. Free allocated structure elements.
(insert_element_in_list): Likewise. Create and populate structures that
hold DWARF information to display global variable information.
+ (PRINT_SPACE, PRINT_LBRACE, PRINT_RBRACE): New macros.
+ (display_base_type, display_type_def, display_enum, display_enum_type,
+ display_subrange_type, display_tab_type, display_member_type,
+ display_member_parent, display_ptr_type, display_variable_type): New
+ function. Display information hold by each structure type.
+ (do_link_variable_information): New function. Link a structure which
+ represents a DWARF information entry to another by populating fields
+ `type` and `ptr_type`.
+ (link_variable_information): New function. Go through all existing
+ structures that hold DWARF information to link each variable_type
+ element to the type of structure it represents.
+ (is_nested_structure): New function. Return true if the type of
+ structure is known else return false, useful to treat nested
+ structures.
+ (compute_variable_ttsize): New function. Recursively go through
+ variable_type element and its structure information to calculate the
+ total size.
+ (reset_displayed_field): New function. Set field `displayed` of
+ member_parent to false to mark already displayed information for a
+ nested structure field.
+ (do_resolve_and_display_variable_info): New function. Recursively go
+ through all element in variable_type_list to link structure type
+ information and call display function to dump information.
+ (resolve_and_display_variable_info): New function.
+
* dwarf.h (types): New enum. Useful to identify structure type which
holds DWARF information.
@@ -34,6 +59,7 @@
tab_type, member_type, member_parent, type_ref, variable_type): New
typedef.
(free_mapping_info_struct): New definition.
+ (resolve_and_display_variable_info): Likewise.
* objdump.c (dump_global_vars_info): New function. Entry point of
display of variable information option.
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index cbe2a0a4a5e..a31e5bca09f 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -55,6 +55,24 @@
#define DO_TYPES 0x2
#define DO_GLOBAL_VARS 0x4
+#define PRINT_SPACE(n) do { \
+ int _i; \
+ for (_i = 0; _i < (n); ++_i) \
+ putchar (' '); \
+} while (0)
+
+#define PRINT_LBRACE(n) do { \
+ PRINT_SPACE (n); \
+ putchar ('{'); \
+ putchar ('\n'); \
+} while (0)
+
+#define PRINT_RBRACE(n) do { \
+ PRINT_SPACE (n); \
+ putchar ('}'); \
+ putchar ('\n'); \
+} while (0)
+
static const char *regname (unsigned int regno, int row);
static const char *regname_internal_by_table_only (unsigned int regno);
@@ -2599,6 +2617,16 @@ display_lang (uint64_t uvalue)
}
}
+static void
+display_base_type (base_type *bt)
+{
+ printf ("type: %s, size: ", bt->name);
+ if (bt->usize != 0)
+ printf ("0x%lx\n", bt->usize);
+ else if (bt->ssize != 0)
+ printf ("0x%lx\n", bt->ssize);
+}
+
static base_type *
get_or_create_base_type (uint64_t die_offset)
{
@@ -2614,6 +2642,12 @@ get_or_create_base_type (uint64_t die_offset)
return base_type_list;
}
+static void
+display_type_def (type_def *td)
+{
+ printf ("type: typedef %s\n", td->name);
+}
+
static type_def *
get_or_create_type_def (uint64_t die_offset)
{
@@ -2631,6 +2665,17 @@ get_or_create_type_def (uint64_t die_offset)
return type_def_list;
}
+static void
+display_enum (enum_constant *ec, int nb_tab)
+{
+ if (ec != NULL)
+ {
+ display_enum (ec->next, nb_tab);
+ PRINT_SPACE (nb_tab);
+ printf ("value: %s = %ld\n", ec->name, ec->value);
+ }
+}
+
static enum_constant *
get_or_create_enum_constant (enum_type *head, uint64_t die_offset)
{
@@ -2647,6 +2692,15 @@ get_or_create_enum_constant (enum_type *head, uint64_t die_offset)
return head->enumeration;
}
+static void
+display_enum_type (enum_type *et, int nb_tab)
+{
+ printf ("type: enum %s, size: 0x%lx\n", et->name, et->usize);
+ PRINT_LBRACE (nb_tab);
+ display_enum (et->enumeration, nb_tab + 1);
+ PRINT_RBRACE (nb_tab);
+}
+
static enum_type *
get_or_create_enum_type (uint64_t die_offset)
{
@@ -2664,6 +2718,23 @@ get_or_create_enum_type (uint64_t die_offset)
return enum_type_list;
}
+static void
+display_subrange_type (subrange_type *st, int nb_tab)
+{
+ if (st != NULL)
+ {
+ display_subrange_type (st->next, nb_tab);
+ if (st->usize != 0)
+ {
+ printf ("[%ld]", st->usize);
+ }
+ else if (st->ssize != 0)
+ {
+ printf ("[%ld]", st->ssize);
+ }
+ }
+}
+
static subrange_type *
get_or_create_subrange_type (tab_type * head, uint64_t die_offset)
{
@@ -2680,6 +2751,14 @@ get_or_create_subrange_type (tab_type * head, uint64_t die_offset)
return head->subrange;
}
+static void
+display_tab_type (tab_type *tt, int nb_tab)
+{
+ printf ("type: array");
+ display_subrange_type (tt->subrange, nb_tab);
+ printf ("\n");
+}
+
static tab_type *
get_or_create_tab (uint64_t die_offset)
{
@@ -2696,6 +2775,16 @@ get_or_create_tab (uint64_t die_offset)
return tab_type_list;
}
+static void
+display_member_type (member_type *mt, int nb_tab)
+{
+ if (mt == NULL)
+ return;
+
+ PRINT_SPACE (nb_tab);
+ printf ("member: %s, offset: 0x%lx\n", mt->name, mt->member_offset);
+}
+
static member_type *
get_or_create_member_type (member_type *head, uint64_t die_offset)
{
@@ -2714,6 +2803,31 @@ get_or_create_member_type (member_type *head, uint64_t die_offset)
return head;
}
+static void
+display_member_parent (member_parent *mp, int is_struct)
+{
+ if (!is_struct)
+ {
+ printf ("type: union %s, size: ", mp->name);
+ if (mp->ssize != 0)
+ printf ("0x%lx\n", mp->ssize);
+ else if (mp->usize != 0)
+ printf ("0x%lx\n", mp->usize);
+ }
+ else
+ {
+ printf ("type: struct %s, size: ", mp->name);
+ if (mp->ssize != 0)
+ printf ("0x%lx\n", mp->ssize);
+ else if (mp->usize != 0)
+ printf ("0x%lx\n", mp->usize);
+ else
+ printf ("Unknown\n");
+ }
+
+ mp->displayed = true;
+}
+
static member_parent *
get_or_create_member_parent (member_parent **head, uint64_t die_offset)
{
@@ -2732,6 +2846,18 @@ get_or_create_member_parent (member_parent **head, uint64_t die_offset)
return *head;
}
+static void
+display_ptr_type (type_ref *pt)
+{
+ printf ("type: ptr, size: ");
+ if (pt->usize != 0)
+ printf ("0x%lx\n", pt->usize);
+ else if (pt->ssize != 0)
+ printf ("0x%lx\n", pt->ssize);
+ else
+ printf ("unknown\n");
+}
+
static type_ref *
get_or_create_type_ref (type_ref **head, uint64_t die_offset)
{
@@ -2750,6 +2876,130 @@ get_or_create_type_ref (type_ref **head, uint64_t die_offset)
return *head;
}
+static void
+display_variable_type (void *ptr_die, enum types type,
+ int nb_tab)
+{
+ if (ptr_die == NULL)
+ return;
+
+ switch (type)
+ {
+ case UNKNOWN_TYPE:
+ fprintf (stderr,
+ _ ("display_variable_type: UNKNOWN_TYPE variable\n"));
+ free_mapping_info_struct ();
+ xexit (1);
+ case BASE_TYPE:
+ PRINT_SPACE (nb_tab);
+ display_base_type ((base_type *) ptr_die);
+ break;
+ case TYPE_DEF:
+ PRINT_SPACE (nb_tab);
+ display_type_def ((type_def *) ptr_die);
+ PRINT_LBRACE (nb_tab);
+ display_variable_type (((type_def *) ptr_die)->ptr_type,
+ ((type_def *) ptr_die)->type,
+ nb_tab + 1);
+ PRINT_RBRACE (nb_tab);
+ break;
+ case ENUM_TYPE:
+ PRINT_SPACE (nb_tab);
+ display_enum_type ((enum_type *) ptr_die, nb_tab);
+ break;
+ case TAB_TYPE:
+ PRINT_SPACE (nb_tab);
+ display_tab_type ((tab_type *) ptr_die, nb_tab + 1);
+ display_variable_type (((tab_type *) ptr_die)->ptr_type,
+ ((tab_type *) ptr_die)->type,
+ nb_tab + 1);
+ break;
+ case MEMBER_TYPE:
+ if (((member_type *) ptr_die)->next != NULL)
+ display_variable_type (((member_type *) ptr_die)->next,
+ MEMBER_TYPE,
+ nb_tab);
+ display_member_type ((member_type *) ptr_die, nb_tab + 1);
+ display_variable_type (((member_type *) ptr_die)->ptr_type,
+ ((member_type *) ptr_die)->type,
+ nb_tab + 2);
+ break;
+ case STRUCT_TYPE:
+ PRINT_SPACE (nb_tab);
+ if (((member_parent *) ptr_die)->displayed)
+ {
+ printf ("nested: struct %s\n", ((member_parent *) ptr_die)->name);
+ break;
+ }
+ display_member_parent ((member_parent *) ptr_die, true);
+ PRINT_LBRACE (nb_tab);
+ if (((member_parent *) ptr_die)->members != NULL)
+ display_variable_type (((member_parent *) ptr_die)->members,
+ MEMBER_TYPE,
+ nb_tab + 1);
+ else
+ {
+ PRINT_SPACE (nb_tab + 1);
+ printf ("%s has no members as it is an incomplete declaration\n",
+ ((member_parent *) ptr_die)->name);
+ }
+ PRINT_RBRACE (nb_tab);
+ break;
+ case UNION_TYPE:
+ PRINT_SPACE (nb_tab);
+ if (((member_parent *) ptr_die)->displayed)
+ {
+ printf ("nested: struct %s\n", ((member_parent *) ptr_die)->name);
+ break;
+ }
+ display_member_parent ((member_parent *) ptr_die, false);
+ PRINT_LBRACE (nb_tab);
+ if (((member_parent *) ptr_die)->members != NULL)
+ display_variable_type (((member_parent *) ptr_die)->members,
+ MEMBER_TYPE,
+ nb_tab + 1);
+ PRINT_RBRACE (nb_tab);
+ break;
+ case PTR_TYPE:
+ PRINT_SPACE (nb_tab);
+ display_ptr_type ((type_ref *) ptr_die);
+ display_variable_type (((type_ref *) ptr_die)->ptr_type,
+ ((type_ref *) ptr_die)->type,
+ nb_tab + 1);
+ break;
+ case VOLATILE_TYPE:
+ PRINT_SPACE (nb_tab);
+ printf ("type: volatile\n");
+ display_variable_type (((type_ref *) ptr_die)->ptr_type,
+ ((type_ref *) ptr_die)->type,
+ nb_tab + 1);
+ break;
+ case CONST_TYPE:
+ PRINT_SPACE (nb_tab);
+ printf ("type: const\n");
+ display_variable_type (((type_ref *) ptr_die)->ptr_type,
+ ((type_ref *) ptr_die)->type,
+ nb_tab + 1);
+ break;
+ case VARIABLE_TYPE:
+ if (((variable_type *) ptr_die)->name == NULL)
+ printf ("Incomplete declaration variable with location: 0x%08lx ",
+ ((variable_type *) ptr_die)->location_addr);
+ else if (((variable_type *) ptr_die)->location_addr == 0)
+ printf ("of variable %s\n", ((variable_type *) ptr_die)->name);
+ else
+ printf ("%s @ 0x%08lx 0x%08lx\n",
+ ((variable_type *) ptr_die)->name,
+ ((variable_type *) ptr_die)->location_addr,
+ ((variable_type *) ptr_die)->location_addr
+ + ((variable_type *) ptr_die)-> ttsize);
+ display_variable_type (((variable_type *) ptr_die)->ptr_type,
+ ((variable_type *) ptr_die)->type,
+ nb_tab + 1);
+ break;
+ }
+}
+
static variable_type *
get_or_create_variable_type (uint64_t die_offset)
{
@@ -13692,6 +13942,346 @@ struct dwarf_section_display debug_displays[] =
/* A static assertion. */
extern int debug_displays_assert[ARRAY_SIZE (debug_displays) == max ? 1 : -1];
+static void
+do_link_variable_information (void *ptr_die_type,
+ enum types die_type,
+ void *target_die_type,
+ enum types die_type_targeted)
+{
+ switch (die_type)
+ {
+ case UNKNOWN_TYPE:
+ case BASE_TYPE:
+ case ENUM_TYPE:
+ case STRUCT_TYPE:
+ case UNION_TYPE:
+ break;
+ case MEMBER_TYPE:
+ ((member_type *) ptr_die_type)->type = die_type_targeted;
+ ((member_type *) ptr_die_type)->ptr_type = target_die_type;
+ break;
+ case TYPE_DEF:
+ ((type_def *) ptr_die_type)->type = die_type_targeted;
+ ((type_def *) ptr_die_type)->ptr_type = target_die_type;
+ break;
+ case TAB_TYPE:
+ ((tab_type *) ptr_die_type)->type = die_type_targeted;
+ ((tab_type *) ptr_die_type)->ptr_type = target_die_type;
+ break;
+ case PTR_TYPE:
+ case VOLATILE_TYPE:
+ case CONST_TYPE:
+ ((type_ref *) ptr_die_type)->type = die_type_targeted;
+ ((type_ref *) ptr_die_type)->ptr_type = target_die_type;
+ break;
+ case VARIABLE_TYPE:
+ ((variable_type *) ptr_die_type)->type = die_type_targeted;
+ ((variable_type *) ptr_die_type)->ptr_type = target_die_type;
+ break;
+ }
+}
+
+static bool
+is_nested_structure (void *ptr_die_type,
+ enum types die_type)
+{
+ switch (die_type)
+ {
+ case UNKNOWN_TYPE:
+ case BASE_TYPE:
+ case ENUM_TYPE:
+ case STRUCT_TYPE:
+ case UNION_TYPE:
+ return false;
+ case MEMBER_TYPE:
+ return ((member_type *) ptr_die_type)->type != UNKNOWN_TYPE;
+ case TYPE_DEF:
+ return ((type_def *) ptr_die_type)->type != UNKNOWN_TYPE;
+ case TAB_TYPE:
+ return ((tab_type *) ptr_die_type)->type != UNKNOWN_TYPE;
+ case PTR_TYPE:
+ case VOLATILE_TYPE:
+ case CONST_TYPE:
+ return ((type_ref *) ptr_die_type)->type != UNKNOWN_TYPE;
+ case VARIABLE_TYPE:
+ return ((variable_type *) ptr_die_type)->type != UNKNOWN_TYPE;
+ }
+ return false;
+}
+
+static bool
+link_variable_information (void *ptr_die_type,
+ enum types die_type,
+ uint64_t ptr_die_offset)
+{
+ if (ptr_die_type == NULL)
+ return false;
+
+ base_type *i_base_type = base_type_list;
+ type_def *i_type_def = type_def_list;
+ enum_type *i_enum_type = enum_type_list;
+ tab_type *i_tab_type = tab_type_list;
+ member_parent *i_struct_type = struct_type_list;
+ member_parent *i_union_type = union_type_list;
+ type_ref *i_ptr_type = ptr_type_list;
+ type_ref *i_const_type = const_type_list;
+ type_ref *i_volatile_type = volatile_type_list;
+ variable_type *i_variable_type = variable_type_list;
+
+ if (is_nested_structure (ptr_die_type, die_type))
+ return true;
+
+ while (true)
+ {
+ if (i_base_type != NULL)
+ {
+ if (i_base_type->die_offset == ptr_die_offset)
+ {
+ do_link_variable_information (ptr_die_type, die_type,
+ i_base_type, BASE_TYPE);
+ break;
+ }
+ i_base_type = i_base_type->next;
+ }
+ if (i_type_def != NULL)
+ {
+ if (i_type_def->die_offset == ptr_die_offset)
+ {
+ do_link_variable_information (ptr_die_type, die_type,
+ i_type_def, TYPE_DEF);
+ link_variable_information (i_type_def, TYPE_DEF,
+ i_type_def->ptr_die_offset);
+ break;
+ }
+ i_type_def = i_type_def->next;
+ }
+ if (i_enum_type != NULL)
+ {
+ if (i_enum_type->die_offset == ptr_die_offset)
+ {
+ do_link_variable_information (ptr_die_type, die_type,
+ i_enum_type, ENUM_TYPE);
+ break;
+ }
+ i_enum_type = i_enum_type->next;
+ }
+ if (i_tab_type != NULL)
+ {
+ if (i_tab_type->die_offset == ptr_die_offset)
+ {
+ do_link_variable_information (ptr_die_type, die_type,
+ i_tab_type, TAB_TYPE);
+ link_variable_information (i_tab_type, TAB_TYPE,
+ i_tab_type->ptr_die_offset);
+ break;
+ }
+ i_tab_type = i_tab_type->next;
+ }
+ if (i_struct_type != NULL)
+ {
+ if (i_struct_type->die_offset == ptr_die_offset)
+ {
+ do_link_variable_information (ptr_die_type, die_type,
+ i_struct_type, STRUCT_TYPE);
+ member_type *mt = i_struct_type->members;
+ while (mt != NULL)
+ {
+ link_variable_information (mt,
+ MEMBER_TYPE,
+ mt->ptr_die_offset);
+ mt = mt->next;
+ }
+ break;
+ }
+ i_struct_type = i_struct_type->next;
+ }
+ if (i_union_type != NULL)
+ {
+ if (i_union_type->die_offset == ptr_die_offset)
+ {
+ do_link_variable_information (ptr_die_type, die_type,
+ i_union_type, UNION_TYPE);
+ member_type *mt = i_union_type->members;
+ while (mt != NULL)
+ {
+ link_variable_information (mt,
+ MEMBER_TYPE,
+ mt->ptr_die_offset);
+ mt = mt->next;
+ }
+ break;
+ }
+ i_union_type = i_union_type->next;
+ }
+ if (i_ptr_type != NULL)
+ {
+ if (i_ptr_type->die_offset == ptr_die_offset)
+ {
+ do_link_variable_information (ptr_die_type, die_type,
+ i_ptr_type, PTR_TYPE);
+ link_variable_information (i_ptr_type, PTR_TYPE,
+ i_ptr_type->ptr_die_offset);
+ break;
+ }
+ i_ptr_type = i_ptr_type->next;
+ }
+ if (i_const_type != NULL)
+ {
+ if (i_const_type->die_offset == ptr_die_offset)
+ {
+ do_link_variable_information (ptr_die_type, die_type,
+ i_const_type, CONST_TYPE);
+ link_variable_information (i_const_type, CONST_TYPE,
+ i_const_type->ptr_die_offset);
+ break;
+ }
+ i_const_type = i_const_type->next;
+ }
+ if (i_volatile_type != NULL)
+ {
+ if (i_volatile_type->die_offset == ptr_die_offset)
+ {
+ do_link_variable_information (ptr_die_type, die_type,
+ i_volatile_type, VOLATILE_TYPE);
+ link_variable_information (i_volatile_type, VOLATILE_TYPE,
+ i_volatile_type->ptr_die_offset);
+ break;
+ }
+ i_volatile_type = i_volatile_type->next;
+ }
+ if (i_variable_type != NULL)
+ {
+ if (i_variable_type->die_offset == ptr_die_offset)
+ {
+ do_link_variable_information (ptr_die_type, die_type,
+ i_variable_type, VARIABLE_TYPE);
+ link_variable_information (i_variable_type, VARIABLE_TYPE,
+ i_variable_type->ptr_die_offset);
+ break;
+ }
+ i_variable_type = i_variable_type->next;
+ }
+ if (i_base_type == NULL && i_type_def == NULL
+ && i_enum_type == NULL && i_tab_type == NULL
+ && i_struct_type == NULL && i_union_type == NULL
+ && i_ptr_type == NULL && i_ptr_type == NULL
+ && i_const_type == NULL && i_volatile_type == NULL
+ && i_variable_type == NULL)
+ return false;
+ }
+ return true;
+}
+
+static uint64_t
+compute_variable_ttsize (void *ptr_die, enum types type)
+{
+ uint64_t size = 0;
+ if (ptr_die == NULL)
+ return 0;
+
+ switch (type)
+ {
+ case UNKNOWN_TYPE:
+ return 0;
+ case BASE_TYPE:
+ if (((base_type *) ptr_die)->usize != 0)
+ size = ((base_type *) ptr_die)->usize;
+ else if (((base_type *) ptr_die)->ssize != 0)
+ size = ((base_type *) ptr_die)->ssize;
+ return size;
+ case TYPE_DEF:
+ return compute_variable_ttsize (((type_def *) ptr_die)->ptr_type,
+ ((type_def *) ptr_die)->type);
+ case ENUM_TYPE:
+ if (((enum_type *) ptr_die)->usize != 0)
+ size = ((enum_type *) ptr_die)->usize;
+ else if (((enum_type *) ptr_die)->ssize != 0)
+ size = ((enum_type *) ptr_die)->ssize;
+ return size;
+ case TAB_TYPE:
+ {
+ size = (size == 0) ? 1 : size;
+ subrange_type *st = ((tab_type *) ptr_die)->subrange;
+ while (st != NULL)
+ {
+ if (st->usize != 0)
+ size = st->usize * size;
+ else if (st->ssize != 0)
+ size = st->ssize * size;
+ st = st->next;
+ }
+ return size * compute_variable_ttsize (((type_def *) ptr_die)->ptr_type,
+ ((type_def *) ptr_die)->type);
+ }
+ case MEMBER_TYPE:
+ return 0;
+ case STRUCT_TYPE:
+ case UNION_TYPE:
+ if (((member_parent *) ptr_die)->usize != 0)
+ size = ((member_parent *) ptr_die)->usize;
+ else if (((member_parent *) ptr_die)->ssize != 0)
+ size = ((member_parent *) ptr_die)->ssize;
+ return size;
+ case PTR_TYPE:
+ if (((type_ref *) ptr_die)->usize != 0)
+ size = ((type_ref *) ptr_die)->usize;
+ else if (((type_ref *) ptr_die)->ssize != 0)
+ size = ((type_ref *) ptr_die)->ssize;
+ return size;
+ case VOLATILE_TYPE:
+ case CONST_TYPE:
+ return compute_variable_ttsize (((type_ref *) ptr_die)->ptr_type,
+ ((type_ref *) ptr_die)->type);
+ case VARIABLE_TYPE:
+ return compute_variable_ttsize (((type_ref *) ptr_die)->ptr_type,
+ ((type_ref *) ptr_die)->type);
+ }
+ return size;
+}
+
+static void
+reset_displayed_field (member_parent *mp)
+{
+ if (mp == NULL)
+ return;
+ mp->displayed = false;
+ reset_displayed_field (mp->next);
+}
+
+static void
+do_resolve_and_display_variable_info (variable_type *vt)
+{
+ if (vt == NULL)
+ return;
+
+ do_resolve_and_display_variable_info (vt->next);
+
+ if (!link_variable_information (vt, VARIABLE_TYPE, vt->ptr_die_offset))
+ {
+ fprintf (stderr,
+ _ ("failed linking variable informations with variable %s "
+ "with die_offset %lx, ptr_offset %lx and location %lx\n"),
+ vt->name,
+ vt->die_offset,
+ vt->ptr_die_offset,
+ vt->location_addr);
+ }
+ if (vt->has_location_addr)
+ {
+ vt->ttsize = compute_variable_ttsize (vt->ptr_type, vt->type);
+ display_variable_type (vt, VARIABLE_TYPE, 0);
+ printf ("\n");
+ reset_displayed_field (struct_type_list);
+ reset_displayed_field (union_type_list);
+ }
+}
+
+void
+resolve_and_display_variable_info (void)
+{
+ do_resolve_and_display_variable_info (variable_type_list);
+}
+
static void
free_base_type (void)
{
diff --git a/binutils/dwarf.h b/binutils/dwarf.h
index c85d83fcf8e..b72cbc9a8f6 100644
--- a/binutils/dwarf.h
+++ b/binutils/dwarf.h
@@ -395,6 +395,7 @@ extern void free_debug_section (enum dwarf_section_display_enum);
extern bool load_separate_debug_files (void *, const char *);
extern void close_debug_file (void *);
extern void *open_debug_file (const char *);
+extern void resolve_and_display_variable_info (void);
extern void free_debug_memory (void);
extern void free_mapping_info_struct (void);
diff --git a/binutils/objdump.c b/binutils/objdump.c
index b27bc5e30f9..dc18f32fcad 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -4564,6 +4564,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);
+ resolve_and_display_variable_info ();
free_mapping_info_struct ();
free_debug_section (info);
}
--
2.25.1
More information about the Binutils
mailing list