@@ -2294,6 +2294,7 @@ objdump [@option{-a}|@option{--archive-headers}]
[@option{-WN}|@option{--dwarf=no-follow-links}]
[@option{-wD}|@option{--dwarf=use-debuginfod}]
[@option{-wE}|@option{--dwarf=do-not-use-debuginfod}]
+ [@option{--map-global-vars}]
[@option{-L}|@option{--process-links}]
[@option{--ctf=}@var{section}]
[@option{--sframe=}@var{section}]
@@ -2540,6 +2541,12 @@ for specification with @option{-b} or @option{-m}.
Display information for section @var{name}. This option may be
specified multiple times.
+@item --map-global-vars
+Display global variable information. This option only works when the object
+file is compiled with the debug option. More precisely, it relies on DWARF2
+debug information entries. It is useful for tracking the location and type of
+all global variables in the given object file.
+
@item -L
@itemx --process-links
Display the contents of non-debug sections found in separate debuginfo
@@ -53,6 +53,7 @@
#define DO_LOC 0x1
#define DO_TYPES 0x2
+#define DO_GLOBAL_VARS 0x4
static const char *regname (unsigned int regno, int row);
static const char *regname_internal_by_table_only (unsigned int regno);
@@ -1165,6 +1166,141 @@ display_block (unsigned char *data,
return data;
}
+static int
+get_location_expression (int die_tag,
+ unsigned long attribute,
+ unsigned char * data,
+ unsigned int pointer_size,
+ unsigned int offset_size,
+ int dwarf_version,
+ uint64_t length,
+ uint64_t die_offset,
+ uint64_t cu_offset,
+ struct dwarf_section * section)
+{
+ unsigned op;
+ uint64_t uvalue = 0;
+ int64_t svalue;
+ unsigned char *end = data + length;
+ int need_frame_base = 0;
+
+ while (data < end)
+ {
+ op = *data++;
+
+ switch (op)
+ {
+ case DW_OP_addr:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
+ break;
+ case DW_OP_const1u:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
+ break;
+ case DW_OP_const1s:
+ SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 1, end);
+ break;
+ case DW_OP_const2u:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
+ break;
+ case DW_OP_const2s:
+ SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end);
+ break;
+ case DW_OP_const4u:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
+ break;
+ case DW_OP_const4s:
+ SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 4, end);
+ break;
+ case DW_OP_const8u:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 8, end);
+ break;
+ case DW_OP_const8s:
+ SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 8, end);
+ break;
+ case DW_OP_bra:
+ SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end);
+ break;
+ case DW_OP_skip:
+ SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end);
+ break;
+
+ case DW_OP_deref_size:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
+ break;
+ case DW_OP_xderef_size:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
+ break;
+
+ case DW_OP_call2:
+ SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end);
+ break;
+ case DW_OP_call4:
+ SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 4, end);
+ break;
+ case DW_OP_call_ref:
+ if (dwarf_version == -1)
+ /* No way to tell where the next op is, so just bail. */
+ return need_frame_base;
+ else if (dwarf_version == 2)
+ SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
+ else
+ SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+ break;
+ case DW_OP_implicit_value:
+ READ_ULEB (uvalue, data, end);
+ break;
+ case DW_OP_implicit_pointer:
+ case DW_OP_GNU_implicit_pointer:
+ if (dwarf_version == -1)
+ return need_frame_base;
+ else if (dwarf_version == 2)
+ SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
+ else
+ SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+ break;
+ case DW_OP_entry_value:
+ case DW_OP_GNU_entry_value:
+ READ_ULEB (uvalue, data, end);
+ /* PR 17531: file: 0cc9cd00. */
+ if (uvalue > (size_t) (end - data))
+ uvalue = end - data;
+ if (get_location_expression
+ (die_tag, attribute, data, pointer_size, offset_size,
+ dwarf_version, uvalue, die_offset, cu_offset, section))
+ need_frame_base = 1;
+ data += uvalue;
+ break;
+ case DW_OP_const_type:
+ case DW_OP_GNU_const_type:
+ READ_ULEB (uvalue, data, end);
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
+ break;
+ case DW_OP_deref_type:
+ case DW_OP_GNU_deref_type:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
+ break;
+ case DW_OP_GNU_parameter_ref:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
+ break;
+ case DW_OP_addrx:
+ READ_ULEB (uvalue, data, end);
+ break;
+ case DW_OP_GNU_variable_value:
+ if (dwarf_version == -1)
+ return need_frame_base;
+ else if (dwarf_version == 2)
+ SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
+ else
+ SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+ break;
+
+ default:
+ return need_frame_base;
+ }
+ }
+ return need_frame_base;
+}
+
static int
decode_location_expression (unsigned char * data,
unsigned int pointer_size,
@@ -2435,6 +2571,47 @@ display_lang (uint64_t uvalue)
}
}
+static void
+insert_element_in_list (enum dwarf_tag dw_tag,
+ enum dwarf_attribute dw_attr ATTRIBUTE_UNUSED,
+ uint64_t die_offset ATTRIBUTE_UNUSED,
+ const uint64_t *uvalue ATTRIBUTE_UNUSED,
+ const int64_t *svalue ATTRIBUTE_UNUSED,
+ const char *data ATTRIBUTE_UNUSED,
+ bool is_union ATTRIBUTE_UNUSED)
+{
+ /* TODO: Retrieve attributes information from
+ below dwarf entries tag. */
+ switch (dw_tag)
+ {
+ case DW_TAG_base_type:
+ break;
+ case DW_TAG_typedef:
+ break;
+ case DW_TAG_enumerator:
+ break;
+ case DW_TAG_enumeration_type:
+ break;
+ case DW_TAG_subrange_type:
+ break;
+ case DW_TAG_array_type:
+ break;
+ case DW_TAG_member:
+ break;
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ break;
+ case DW_TAG_const_type:
+ case DW_TAG_volatile_type:
+ case DW_TAG_pointer_type:
+ break;
+ case DW_TAG_variable:
+ break;
+ default:
+ break;
+ }
+}
+
static unsigned char *
read_and_display_attr_value (unsigned long attribute,
unsigned long form,
@@ -2451,7 +2628,11 @@ read_and_display_attr_value (unsigned long attribute,
struct dwarf_section *section,
struct cu_tu_set *this_set,
char delimiter,
- int level)
+ int level,
+ bool do_var_map,
+ int die_tag,
+ unsigned long die_offset,
+ bool is_union)
{
int64_t svalue;
uint64_t uvalue = 0;
@@ -2577,7 +2758,9 @@ read_and_display_attr_value (unsigned long attribute,
cu_offset, pointer_size,
offset_size, dwarf_version,
debug_info_p, do_loc,
- section, this_set, delimiter, level);
+ section, this_set, delimiter, level,
+ do_var_map, die_tag, die_offset,
+ is_union);
case DW_FORM_implicit_const:
uvalue = implicit_const;
@@ -2592,6 +2775,9 @@ read_and_display_attr_value (unsigned long attribute,
case DW_FORM_ref_addr:
if (!do_loc)
printf ("%c<%#" PRIx64 ">", delimiter, uvalue);
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ &uvalue, NULL, NULL, is_union);
break;
case DW_FORM_GNU_ref_alt:
@@ -2603,6 +2789,9 @@ read_and_display_attr_value (unsigned long attribute,
else
printf ("%c<alt %#" PRIx64 ">", delimiter, uvalue);
}
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ &uvalue, NULL, NULL, is_union);
/* FIXME: Follow the reference... */
break;
@@ -2611,8 +2800,14 @@ read_and_display_attr_value (unsigned long attribute,
case DW_FORM_ref4:
case DW_FORM_ref_sup4:
case DW_FORM_ref_udata:
- if (!do_loc)
- printf ("%c<%#" PRIx64 ">", delimiter, uvalue + cu_offset);
+ {
+ uint64_t utmp = uvalue + cu_offset;
+ if (!do_loc)
+ printf ("%c<%#" PRIx64 ">", delimiter, utmp);
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ &utmp, NULL, NULL, is_union);
+ }
break;
case DW_FORM_data4:
@@ -2620,6 +2815,9 @@ read_and_display_attr_value (unsigned long attribute,
case DW_FORM_sec_offset:
if (!do_loc)
printf ("%c%#" PRIx64, delimiter, uvalue);
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ &uvalue, NULL, NULL, is_union);
break;
case DW_FORM_flag_present:
@@ -2629,27 +2827,40 @@ read_and_display_attr_value (unsigned long attribute,
case DW_FORM_sdata:
if (!do_loc)
printf ("%c%" PRId64, delimiter, uvalue);
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ &uvalue, NULL, NULL, is_union);
break;
case DW_FORM_udata:
if (!do_loc)
printf ("%c%" PRIu64, delimiter, uvalue);
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ &uvalue, NULL, NULL, is_union);
break;
case DW_FORM_implicit_const:
if (!do_loc)
printf ("%c%" PRId64, delimiter, implicit_const);
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ NULL, &implicit_const, NULL, is_union);
break;
case DW_FORM_ref_sup8:
case DW_FORM_ref8:
case DW_FORM_data8:
- if (!do_loc)
+ if (!do_loc || do_var_map)
{
uint64_t utmp = uvalue;
if (form == DW_FORM_ref8)
utmp += cu_offset;
- printf ("%c%#" PRIx64, delimiter, utmp);
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ &utmp, NULL, NULL, is_union);
+ else
+ printf ("%c%#" PRIx64, delimiter, utmp);
}
break;
@@ -2661,11 +2872,24 @@ read_and_display_attr_value (unsigned long attribute,
else
printf (" %#" PRIx64 "%016" PRIx64, uvalue_hi, uvalue);
}
+ if (do_var_map)
+ {
+ if (uvalue_hi == 0)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ &uvalue, NULL, NULL, is_union);
+ else
+ insert_element_in_list (die_tag, attribute, die_offset,
+ &uvalue_hi, NULL, NULL, is_union);
+ }
break;
case DW_FORM_string:
if (!do_loc)
printf ("%c%.*s", delimiter, (int) (end - data), data);
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ NULL, NULL, (const char *) data,
+ is_union);
data += strnlen ((char *) data, end - data);
if (data < end)
data++;
@@ -2719,6 +2943,10 @@ read_and_display_attr_value (unsigned long attribute,
printf (_("%c(indirect string, offset: %#" PRIx64 "): %s"),
delimiter, uvalue, fetch_indirect_string (uvalue));
}
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ NULL, NULL, (const char *)
+ fetch_indirect_string (uvalue), is_union);
break;
case DW_FORM_line_strp:
@@ -2732,6 +2960,10 @@ read_and_display_attr_value (unsigned long attribute,
printf (_("%c(indirect line string, offset: %#" PRIx64 "): %s"),
delimiter, uvalue, fetch_indirect_line_string (uvalue));
}
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ NULL, NULL, (const char *)
+ fetch_indirect_line_string (uvalue), is_union);
break;
case DW_FORM_GNU_str_index:
@@ -2755,6 +2987,9 @@ read_and_display_attr_value (unsigned long attribute,
else
printf (_("%c(indexed string: %#" PRIx64 "): %s"),
delimiter, uvalue, strng);
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ NULL, NULL, strng, is_union);
}
break;
@@ -2769,6 +3004,10 @@ read_and_display_attr_value (unsigned long attribute,
printf (_("%c(alt indirect string, offset: %#" PRIx64 ") %s"),
delimiter, uvalue, fetch_alt_indirect_string (uvalue));
}
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ NULL, NULL, fetch_alt_indirect_string (uvalue),
+ is_union);
break;
case DW_FORM_indirect:
@@ -2779,6 +3018,9 @@ read_and_display_attr_value (unsigned long attribute,
if (!do_loc)
printf ("%c%s: %#" PRIx64, delimiter, do_wide ? "" : "signature",
uvalue);
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ &uvalue, NULL, NULL, is_union);
break;
case DW_FORM_GNU_addr_index:
@@ -2855,14 +3097,25 @@ read_and_display_attr_value (unsigned long attribute,
/* We have already displayed the form name. */
if (idx != (uint64_t) -1)
- printf (_("%c(index: %#" PRIx64 "): %#" PRIx64),
- delimiter, uvalue, idx);
+ {
+ printf (_("%c(index: %#" PRIx64 "): %#" PRIx64),
+ delimiter, uvalue, idx);
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ &uvalue, NULL, NULL, is_union);
+ }
}
break;
case DW_FORM_strp_sup:
- if (!do_loc)
- printf ("%c<%#" PRIx64 ">", delimiter, uvalue + cu_offset);
+ {
+ uint64_t utmp = uvalue + cu_offset;
+ if (!do_loc)
+ printf ("%c<%#" PRIx64 ">", delimiter, utmp);
+ if (do_var_map)
+ insert_element_in_list (die_tag, attribute, die_offset,
+ &utmp, NULL, NULL, is_union);
+ }
break;
default:
@@ -3143,6 +3396,72 @@ read_and_display_attr_value (unsigned long attribute,
}
}
+ if (do_var_map)
+ {
+ switch (attribute)
+ {
+ case DW_AT_frame_base:
+ case DW_AT_location:
+ case DW_AT_loclists_base:
+ case DW_AT_rnglists_base:
+ case DW_AT_str_offsets_base:
+ case DW_AT_string_length:
+ case DW_AT_return_addr:
+ case DW_AT_data_member_location:
+ case DW_AT_vtable_elem_location:
+ case DW_AT_segment:
+ case DW_AT_static_link:
+ case DW_AT_use_location:
+ case DW_AT_call_value:
+ case DW_AT_GNU_call_site_value:
+ case DW_AT_call_data_value:
+ case DW_AT_GNU_call_site_data_value:
+ case DW_AT_call_target:
+ case DW_AT_GNU_call_site_target:
+ case DW_AT_call_target_clobbered:
+ case DW_AT_GNU_call_site_target_clobbered:
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_data_location:
+ case DW_AT_stride:
+ case DW_AT_upper_bound:
+ case DW_AT_lower_bound:
+ case DW_AT_rank:
+ if (block_start)
+ get_location_expression (die_tag,
+ attribute,
+ block_start,
+ pointer_size,
+ offset_size,
+ dwarf_version,
+ die_offset,
+ uvalue,
+ cu_offset,
+ section);
+ break;
+ case DW_AT_data_bit_offset:
+ case DW_AT_byte_size:
+ case DW_AT_bit_size:
+ case DW_AT_string_length_byte_size:
+ case DW_AT_string_length_bit_size:
+ case DW_AT_bit_stride:
+ if (form == DW_FORM_exprloc)
+ get_location_expression (die_tag,
+ attribute,
+ block_start,
+ pointer_size,
+ offset_size,
+ dwarf_version,
+ die_offset,
+ uvalue,
+ cu_offset,
+ section);
+ break;
+ default:
+ break;
+ }
+ }
+
if (do_loc || attribute == 0)
return data;
@@ -3490,7 +3809,11 @@ read_and_display_attr (unsigned long attribute,
int do_loc,
struct dwarf_section *section,
struct cu_tu_set *this_set,
- int level)
+ int level,
+ bool do_var_map,
+ int die_tag,
+ unsigned long die_offset,
+ bool is_union)
{
if (!do_loc)
printf (" %-18s:", get_AT_name (attribute));
@@ -3498,7 +3821,9 @@ read_and_display_attr (unsigned long attribute,
start, data, end,
cu_offset, pointer_size, offset_size,
dwarf_version, debug_info_p,
- do_loc, section, this_set, ' ', level);
+ do_loc, section, this_set, ' ', level,
+ do_var_map, die_tag, die_offset,
+ is_union);
if (!do_loc)
printf ("\n");
return data;
@@ -3753,6 +4078,8 @@ read_bases (abbrev_entry * entry,
and we do not want to display anything to the user.
If do_types is TRUE, we are processing a .debug_types section instead of
a .debug_info section.
+ If do_var_map is TRUE, we are processing a .debug_types section without
+ displaying anything to the user yet.
The information displayed is restricted by the values in DWARF_START_DIE
and DWARF_CUTOFF_LEVEL.
Returns TRUE upon success. Otherwise an error or warning message is
@@ -3834,7 +4161,7 @@ process_debug_info (struct dwarf_section * section,
alloc_num_debug_info_entries = num_units;
}
- if (!(do_flags & DO_LOC))
+ if (!(do_flags & DO_LOC) || (do_flags & DO_GLOBAL_VARS))
{
load_debug_section_with_follow (str, file);
load_debug_section_with_follow (line_str, file);
@@ -3961,6 +4288,7 @@ process_debug_info (struct dwarf_section * section,
uint64_t abbrev_base;
size_t abbrev_size;
unsigned char *end_cu;
+ bool is_union;
hdrptr = start;
cu_offset = start - section_begin;
@@ -4132,6 +4460,7 @@ process_debug_info (struct dwarf_section * section,
level = 0;
last_level = level;
saved_level = -1;
+ is_union = false;
while (tags < start)
{
unsigned long abbrev_number;
@@ -4255,6 +4584,12 @@ process_debug_info (struct dwarf_section * section,
/* Don't reset that for nested subprogram. */
have_frame_base = 0;
break;
+ case DW_TAG_structure_type:
+ is_union = false;
+ break;
+ case DW_TAG_union_type:
+ is_union = true;
+ break;
}
debug_info *debug_info_p = ((debug_information
@@ -4316,7 +4651,11 @@ process_debug_info (struct dwarf_section * section,
|| ! do_printing,
section,
this_set,
- level);
+ level,
+ do_flags & DO_GLOBAL_VARS,
+ entry->tag,
+ die_offset,
+ is_union);
}
/* If a locview attribute appears before a location one,
@@ -4620,7 +4959,8 @@ display_formatted_table (unsigned char *data,
0, 0, linfo->li_offset_size,
linfo->li_version, NULL,
((content_type == DW_LNCT_path) != (namepass == 1)),
- section, NULL, '\t', -1);
+ section, NULL, '\t', -1,
+ false, 0, 0, false);
}
}
@@ -5280,7 +5620,8 @@ display_debug_lines_decoded (struct dwarf_section * section,
linfo.li_offset_size,
linfo.li_version,
NULL, 1, section,
- NULL, '\t', -1);
+ NULL, '\t', -1,
+ false, 0, 0, false);
}
if (data >= end)
{
@@ -5379,7 +5720,8 @@ display_debug_lines_decoded (struct dwarf_section * section,
linfo.li_offset_size,
linfo.li_version,
NULL, 1, section,
- NULL, '\t', -1);
+ NULL, '\t', -1,
+ false, 0, 0, false);
}
if (data >= end)
{
@@ -6595,7 +6937,8 @@ display_debug_macro (struct dwarf_section *section,
start, curr, end, 0, 0,
offset_size, version,
NULL, 0, section,
- NULL, ' ', -1);
+ NULL, ' ', -1,
+ false, 0, 0, false);
if (n != nargs - 1)
printf (",");
}
@@ -7683,6 +8026,13 @@ display_debug_str (struct dwarf_section *section,
return 1;
}
+static int
+display_variable_mapping_info (struct dwarf_section *section, void *file)
+{
+ return process_debug_info (section, file, section->abbrev_sec,
+ DO_LOC | DO_GLOBAL_VARS);
+}
+
static int
display_debug_info (struct dwarf_section *section, void *file)
{
@@ -10972,7 +11322,8 @@ display_debug_names (struct dwarf_section *section, void *file)
0, 0, offset_size,
dwarf_version, NULL,
(tagno < 0), section,
- NULL, '=', -1);
+ NULL, '=', -1,
+ false, 0, 0, false);
}
++tagno;
}
@@ -12926,6 +13277,7 @@ struct dwarf_section_display debug_displays[] =
in the main file. Hence we need to have two entries for .debug_str. */
{ { ".debug_str", ".zdebug_str", "", NO_ABBREVS }, display_debug_str, &do_debug_str, false },
{ { ".note.gnu.build-id", "", "", NO_ABBREVS }, display_debug_not_supported, NULL, false },
+ { { ".debug_info", ".zdebug_info", ".dwinfo", ABBREV (abbrev)}, display_variable_mapping_info, &do_debug_info, true }
};
/* A static assertion. */
@@ -124,6 +124,7 @@ enum dwarf_section_display_enum
debug_sup,
separate_debug_str,
note_gnu_build_id,
+ debug_variable_info,
max
};
@@ -138,6 +138,7 @@ static bool color_output = false; /* --visualize-jumps=color. */
static bool extended_color_output = false; /* --visualize-jumps=extended-color. */
static int process_links = false; /* --process-links. */
static int show_all_symbols; /* --show-all-symbols. */
+static bool dump_global_vars; /* --map-global-vars. */
static bool decompressed_dumps = false; /* -Z, --decompress. */
static struct symbol_entry
@@ -327,6 +328,8 @@ usage (FILE *stream, int status)
-WE --dwarf=do-not-use-debuginfod\n\
When following links, do not query debuginfod servers\n"));
#endif
+ fprintf (stream, _("\
+ --map-global-vars Display memory mapping of global variables\n"));
fprintf (stream, _("\
-L, --process-links Display the contents of non-debug sections in\n\
separate debuginfo files. (Implies -WK)\n"));
@@ -496,7 +499,8 @@ enum option_values
#endif
OPTION_SFRAME,
OPTION_VISUALIZE_JUMPS,
- OPTION_DISASSEMBLER_COLOR
+ OPTION_DISASSEMBLER_COLOR,
+ OPTION_MAP_GLOBAL_VARS
};
static struct option long_options[]=
@@ -567,6 +571,7 @@ static struct option long_options[]=
{"visualize-jumps", optional_argument, 0, OPTION_VISUALIZE_JUMPS},
{"wide", no_argument, NULL, 'w'},
{"disassembler-color", required_argument, NULL, OPTION_DISASSEMBLER_COLOR},
+ {"map-global-vars", no_argument, NULL, OPTION_MAP_GLOBAL_VARS},
{NULL, no_argument, NULL, 0}
};
@@ -4528,10 +4533,47 @@ dump_dwarf_section (bfd *abfd, asection *section,
}
}
-/* Dump the dwarf debugging information. */
+static void
+dump_global_variable_info (bfd *abfd, asection *section,
+ void *arg)
+{
+ const char *name = bfd_section_name (section);
+ const char *match;
+ bool is_mainfile = *(bool *) arg;
+
+ if (*name == 0)
+ return;
+
+ if (!is_mainfile && !process_links
+ && (section->flags & SEC_DEBUGGING) == 0)
+ return;
+
+ if (startswith (name, ".gnu.linkonce.wi."))
+ match = ".debug_info";
+ else
+ match = name;
+
+ if (((strcmp (debug_displays [info].section.uncompressed_name,match) == 0
+ || strcmp (debug_displays [info].section.compressed_name, match) == 0
+ || strcmp (debug_displays [info].section.xcoff_name, match) == 0))
+ && debug_displays [info].enabled != NULL
+ && *debug_displays [info].enabled)
+ {
+ struct dwarf_section *sec = &debug_displays [info].section;
+ if (load_specific_debug_section (info, section, abfd))
+ {
+ debug_displays [debug_variable_info].display (sec, abfd);
+ free_debug_section (info);
+ }
+ }
+}
+
+/* Dump the dwarf debugging information helper. */
static void
-dump_dwarf (bfd *abfd, bool is_mainfile)
+dump_dwarf_info (bfd *abfd,
+ void (*operation) (bfd *, asection *, void *),
+ bool is_mainfile)
{
/* The byte_get pointer should have been set at the start of dump_bfd(). */
if (byte_get == NULL)
@@ -4557,7 +4599,23 @@ dump_dwarf (bfd *abfd, bool is_mainfile)
init_dwarf_by_bfd_arch_and_mach (bfd_get_arch (abfd),
bfd_get_mach (abfd));
- bfd_map_over_sections (abfd, dump_dwarf_section, (void *) &is_mainfile);
+ bfd_map_over_sections (abfd, operation, (void *) &is_mainfile);
+}
+
+/* Dump the dwarf debugging information. */
+
+static void
+dump_dwarf (bfd *abfd, bool is_mainfile)
+{
+ dump_dwarf_info (abfd, dump_dwarf_section, is_mainfile);
+}
+
+/* Dump all global variable information in memory. */
+
+static void
+dump_global_vars_info (bfd *abfd, bool is_mainfile)
+{
+ dump_dwarf_info (abfd, dump_global_variable_info, is_mainfile);
}
/* Read ABFD's section SECT_NAME into *CONTENTS, and return a pointer to
@@ -5829,6 +5887,8 @@ dump_bfd (bfd *abfd, bool is_mainfile)
if (dump_dynamic_symtab)
dump_symbols (abfd, true);
}
+ if (dump_global_vars)
+ dump_global_vars_info (abfd, is_mainfile);
if (dump_dwarf_section_info)
dump_dwarf (abfd, is_mainfile);
if (is_mainfile || process_links)
@@ -6284,6 +6344,11 @@ main (int argc, char **argv)
process_links = true;
do_follow_links = true;
break;
+ case OPTION_MAP_GLOBAL_VARS:
+ dump_global_vars = true;
+ dwarf_select_sections_all ();
+ seenflag = true;
+ break;
case 'W':
seenflag = true;
if (optarg)
@@ -6423,6 +6488,7 @@ main (int argc, char **argv)
dump_any_debugging = (dump_debugging
|| dump_dwarf_section_info
+ || dump_global_vars
|| process_links
|| with_source_code);