[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