summaryrefslogtreecommitdiff
path: root/binutils/dwarf.c
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@google.com>2012-10-24 01:59:38 +0000
committerCary Coutant <ccoutant@google.com>2012-10-24 01:59:38 +0000
commit387c7a3fac1150418a8fa2f3fca672904b9a105b (patch)
tree450459584f5ca062cdeaad873ca46a1cdc6c9f41 /binutils/dwarf.c
parent1d7f078ec0360a038b2e16881bec46d0d0560af7 (diff)
downloadbinutils-redhat-387c7a3fac1150418a8fa2f3fca672904b9a105b.tar.gz
binutils/
* dwarf.c (do_debug_addr, do_debug_cu_index): New global flags. (load_debug_info): Fix typo. (cu_tu_indexes_read, shndx_pool, shndx_pool_size, shndx_pool_used): New global variables. (prealloc_cu_tu_list, add_shndx_to_cu_tu_entry, end_cu_tu_entry) (process_cu_tu_index, load_cu_tu_indexes, find_cu_tu_set) (display_cu_index): New functions. (dwarf_select_sections_by_names): Add "debug_addr", "cu_index". Sort entries alphabetically. (dwarf_select_sections_all): Set do_debug_addr, do_debug_cu_index. (debug_displays): Add .debug_cu_index, .debug_tu_index. Clean up formatting. * dwarf.h (dwarf_section_display_enum): Add dwp_cu_index, dwp_tu_index. (do_debug_addr, do_debug_cu_index): New global flags. (find_cu_tu_set): New function declaration. * objdump.c (usage): Add --dwarf=addr, --dwarf=cu_index. * readelf.c (find_section_in_set): New function. (usage): Add --debug-dump=addr, --debug_dump=cu_index. (process_section_headers): Check do_debug_addr and do_debug_cu_index. (section_subset): New global variable. (load_debug_section): Restrict search to section subset. (display_debug_section): Add section index as paramter. Select subset of sections when dumping a .dwp file. Update caller.
Diffstat (limited to 'binutils/dwarf.c')
-rw-r--r--binutils/dwarf.c289
1 files changed, 246 insertions, 43 deletions
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index fa6860c021..8127ee3d7a 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -62,6 +62,8 @@ int do_gdb_index;
int do_trace_info;
int do_trace_abbrevs;
int do_trace_aranges;
+int do_debug_addr;
+int do_debug_cu_index;
int do_wide;
int dwarf_cutoff_level = -1;
@@ -2313,7 +2315,7 @@ load_debug_info (void * file)
warned_about_missing_comp_units = FALSE;
/* If we have already tried and failed to load the .debug_info
- section then do not bother to repear the task. */
+ section then do not bother to repeat the task. */
if (num_debug_info_entries == DEBUG_INFO_UNAVAILABLE)
return 0;
@@ -5850,6 +5852,200 @@ display_gdb_index (struct dwarf_section *section,
return 1;
}
+/* Collection of CU/TU section sets from .debug_cu_index and .debug_tu_index
+ sections. Each set is stored in SHNDX_POOL as a zero-terminated list of
+ section indexes comprising one set of debug sections from a .dwo file. */
+
+int cu_tu_indexes_read = 0;
+unsigned int *shndx_pool = NULL;
+unsigned int shndx_pool_size = 0;
+unsigned int shndx_pool_used = 0;
+
+/* Pre-allocate enough space for the CU/TU sets needed. */
+
+static void
+prealloc_cu_tu_list (unsigned int nshndx)
+{
+ if (shndx_pool == NULL)
+ {
+ shndx_pool_size = nshndx;
+ shndx_pool_used = 0;
+ shndx_pool = (unsigned int *) xcmalloc (shndx_pool_size,
+ sizeof (unsigned int));
+ }
+ else
+ {
+ shndx_pool_size = shndx_pool_used + nshndx;
+ shndx_pool = (unsigned int *) xcrealloc (shndx_pool, shndx_pool_size,
+ sizeof (unsigned int));
+ }
+}
+
+static void
+add_shndx_to_cu_tu_entry (unsigned int shndx)
+{
+ if (shndx_pool_used >= shndx_pool_size)
+ {
+ error (_("Internal error: out of space in the shndx pool.\n"));
+ return;
+ }
+ shndx_pool [shndx_pool_used++] = shndx;
+}
+
+static void
+end_cu_tu_entry (void)
+{
+ if (shndx_pool_used >= shndx_pool_size)
+ {
+ error (_("Internal error: out of space in the shndx pool.\n"));
+ return;
+ }
+ shndx_pool [shndx_pool_used++] = 0;
+}
+
+/* Process a CU or TU index. If DO_DISPLAY is true, print the contents. */
+
+static int
+process_cu_tu_index (struct dwarf_section *section, int do_display)
+{
+ unsigned char *phdr = section->start;
+ unsigned char *limit = phdr + section->size;
+ unsigned char *phash;
+ unsigned char *pindex;
+ unsigned char *ppool;
+ unsigned int version;
+ unsigned int nused;
+ unsigned int nslots;
+ unsigned int i;
+
+ version = byte_get (phdr, 4);
+ nused = byte_get (phdr + 8, 4);
+ nslots = byte_get (phdr + 12, 4);
+ phash = phdr + 16;
+ pindex = phash + nslots * 8;
+ ppool = pindex + nslots * 4;
+
+ if (!do_display)
+ prealloc_cu_tu_list((limit - ppool) / 4);
+
+ if (do_display)
+ {
+ printf (_("Contents of the %s section:\n\n"), section->name);
+ printf (_(" Version: %d\n"), version);
+ printf (_(" Number of used entries: %d\n"), nused);
+ printf (_(" Number of slots: %d\n\n"), nslots);
+ }
+
+ if (ppool > limit)
+ {
+ warn (_("Section %s too small for %d hash table entries\n"),
+ section->name, nslots);
+ return 0;
+ }
+
+ for (i = 0; i < nslots; i++)
+ {
+ dwarf_vma signature_high;
+ dwarf_vma signature_low;
+ unsigned int j;
+ unsigned char *shndx_list;
+ unsigned int shndx;
+ char buf[64];
+
+ byte_get_64 (phash, &signature_high, &signature_low);
+ if (signature_high != 0 || signature_low != 0)
+ {
+ j = byte_get (pindex, 4);
+ shndx_list = ppool + j * 4;
+ if (do_display)
+ printf (_(" [%3d] Signature: 0x%s Sections: "),
+ i, dwarf_vmatoa64 (signature_high, signature_low,
+ buf, sizeof (buf)));
+ for (;;)
+ {
+ if (shndx_list >= limit)
+ {
+ warn (_("Section %s too small for shndx pool\n"),
+ section->name);
+ return 0;
+ }
+ shndx = byte_get (shndx_list, 4);
+ if (shndx == 0)
+ break;
+ if (do_display)
+ printf (" %d", shndx);
+ else
+ add_shndx_to_cu_tu_entry (shndx);
+ shndx_list += 4;
+ }
+ if (do_display)
+ printf ("\n");
+ else
+ end_cu_tu_entry ();
+ }
+ phash += 8;
+ pindex += 4;
+ }
+
+ if (do_display)
+ printf ("\n");
+
+ return 1;
+}
+
+/* Load the CU and TU indexes if present. This will build a list of
+ section sets that we can use to associate a .debug_info.dwo section
+ with its associated .debug_abbrev.dwo section in a .dwp file. */
+
+static void
+load_cu_tu_indexes (void *file)
+{
+ /* If we have already loaded (or tried to load) the CU and TU indexes
+ then do not bother to repeat the task. */
+ if (cu_tu_indexes_read)
+ return;
+
+ if (load_debug_section (dwp_cu_index, file))
+ process_cu_tu_index (&debug_displays [dwp_cu_index].section, 0);
+
+ if (load_debug_section (dwp_tu_index, file))
+ process_cu_tu_index (&debug_displays [dwp_tu_index].section, 0);
+
+ cu_tu_indexes_read = 1;
+}
+
+/* Find the set of sections that includes section SHNDX. */
+
+unsigned int *
+find_cu_tu_set (void *file, unsigned int shndx)
+{
+ unsigned int i;
+
+ load_cu_tu_indexes (file);
+
+ /* Find SHNDX in the shndx pool. */
+ for (i = 0; i < shndx_pool_used; i++)
+ if (shndx_pool [i] == shndx)
+ break;
+
+ if (i >= shndx_pool_used)
+ return NULL;
+
+ /* Now backup to find the first entry in the set. */
+ while (i > 0 && shndx_pool [i - 1] != 0)
+ i--;
+
+ return shndx_pool + i;
+}
+
+/* Display a .debug_cu_index or .debug_tu_index section. */
+
+static int
+display_cu_index (struct dwarf_section *section, void *file ATTRIBUTE_UNUSED)
+{
+ return process_cu_tu_index (section, 1);
+}
+
static int
display_debug_not_supported (struct dwarf_section *section,
void *file ATTRIBUTE_UNUSED)
@@ -5938,13 +6134,16 @@ dwarf_select_sections_by_names (const char *names)
/* Please keep this table alpha- sorted. */
{ "Ranges", & do_debug_ranges, 1 },
{ "abbrev", & do_debug_abbrevs, 1 },
+ { "addr", & do_debug_addr, 1 },
{ "aranges", & do_debug_aranges, 1 },
+ { "cu_index", & do_debug_cu_index, 1 },
+ { "decodedline", & do_debug_lines, FLAG_DEBUG_LINES_DECODED },
{ "frames", & do_debug_frames, 1 },
{ "frames-interp", & do_debug_frames_interp, 1 },
+ /* The special .gdb_index section. */
+ { "gdb_index", & do_gdb_index, 1 },
{ "info", & do_debug_info, 1 },
{ "line", & do_debug_lines, FLAG_DEBUG_LINES_RAW }, /* For backwards compatibility. */
- { "rawline", & do_debug_lines, FLAG_DEBUG_LINES_RAW },
- { "decodedline", & do_debug_lines, FLAG_DEBUG_LINES_DECODED },
{ "loc", & do_debug_loc, 1 },
{ "macro", & do_debug_macinfo, 1 },
{ "pubnames", & do_debug_pubnames, 1 },
@@ -5952,9 +6151,8 @@ dwarf_select_sections_by_names (const char *names)
/* This entry is for compatability
with earlier versions of readelf. */
{ "ranges", & do_debug_aranges, 1 },
+ { "rawline", & do_debug_lines, FLAG_DEBUG_LINES_RAW },
{ "str", & do_debug_str, 1 },
- /* The special .gdb_index section. */
- { "gdb_index", & do_gdb_index, 1 },
/* These trace_* sections are used by Itanium VMS. */
{ "trace_abbrev", & do_trace_abbrevs, 1 },
{ "trace_aranges", & do_trace_aranges, 1 },
@@ -6083,73 +6281,78 @@ dwarf_select_sections_all (void)
do_trace_info = 1;
do_trace_abbrevs = 1;
do_trace_aranges = 1;
+ do_debug_addr = 1;
+ do_debug_cu_index = 1;
}
struct dwarf_section_display debug_displays[] =
{
- { { ".debug_abbrev", ".zdebug_abbrev", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_abbrev", ".zdebug_abbrev", NULL, NULL, 0, 0, 0 },
display_debug_abbrev, &do_debug_abbrevs, 0 },
- { { ".debug_aranges", ".zdebug_aranges", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_aranges", ".zdebug_aranges", NULL, NULL, 0, 0, 0 },
display_debug_aranges, &do_debug_aranges, 1 },
- { { ".debug_frame", ".zdebug_frame", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_frame", ".zdebug_frame", NULL, NULL, 0, 0, 0 },
display_debug_frames, &do_debug_frames, 1 },
{ { ".debug_info", ".zdebug_info", NULL, NULL, 0, 0, abbrev },
display_debug_info, &do_debug_info, 1 },
- { { ".debug_line", ".zdebug_line", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_line", ".zdebug_line", NULL, NULL, 0, 0, 0 },
display_debug_lines, &do_debug_lines, 1 },
- { { ".debug_pubnames", ".zdebug_pubnames", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_pubnames", ".zdebug_pubnames", NULL, NULL, 0, 0, 0 },
display_debug_pubnames, &do_debug_pubnames, 0 },
- { { ".eh_frame", "", NULL, NULL, 0, 0, abbrev },
+ { { ".eh_frame", "", NULL, NULL, 0, 0, 0 },
display_debug_frames, &do_debug_frames, 1 },
- { { ".debug_macinfo", ".zdebug_macinfo", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_macinfo", ".zdebug_macinfo", NULL, NULL, 0, 0, 0 },
display_debug_macinfo, &do_debug_macinfo, 0 },
- { { ".debug_macro", ".zdebug_macro", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_macro", ".zdebug_macro", NULL, NULL, 0, 0, 0 },
display_debug_macro, &do_debug_macinfo, 1 },
- { { ".debug_str", ".zdebug_str", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_str", ".zdebug_str", NULL, NULL, 0, 0, 0 },
display_debug_str, &do_debug_str, 0 },
- { { ".debug_loc", ".zdebug_loc", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_loc", ".zdebug_loc", NULL, NULL, 0, 0, 0 },
display_debug_loc, &do_debug_loc, 1 },
- { { ".debug_pubtypes", ".zdebug_pubtypes", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_pubtypes", ".zdebug_pubtypes", NULL, NULL, 0, 0, 0 },
display_debug_pubnames, &do_debug_pubtypes, 0 },
- { { ".debug_ranges", ".zdebug_ranges", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_ranges", ".zdebug_ranges", NULL, NULL, 0, 0, 0 },
display_debug_ranges, &do_debug_ranges, 1 },
- { { ".debug_static_func", ".zdebug_static_func", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_static_func", ".zdebug_static_func", NULL, NULL, 0, 0, 0 },
display_debug_not_supported, NULL, 0 },
- { { ".debug_static_vars", ".zdebug_static_vars", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_static_vars", ".zdebug_static_vars", NULL, NULL, 0, 0, 0 },
display_debug_not_supported, NULL, 0 },
{ { ".debug_types", ".zdebug_types", NULL, NULL, 0, 0, abbrev },
display_debug_types, &do_debug_info, 1 },
- { { ".debug_weaknames", ".zdebug_weaknames", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_weaknames", ".zdebug_weaknames", NULL, NULL, 0, 0, 0 },
display_debug_not_supported, NULL, 0 },
- { { ".gdb_index", "", NULL, NULL, 0, 0, abbrev },
- display_gdb_index, &do_gdb_index, 0 },
+ { { ".gdb_index", "", NULL, NULL, 0, 0, 0 },
+ display_gdb_index, &do_gdb_index, 0 },
{ { ".trace_info", "", NULL, NULL, 0, 0, trace_abbrev },
- display_trace_info, &do_trace_info, 1 },
- { { ".trace_abbrev", "", NULL, NULL, 0, 0, abbrev },
- display_debug_abbrev, &do_trace_abbrevs, 0 },
- { { ".trace_aranges", "", NULL, NULL, 0, 0, abbrev },
- display_debug_aranges, &do_trace_aranges, 0 },
+ display_trace_info, &do_trace_info, 1 },
+ { { ".trace_abbrev", "", NULL, NULL, 0, 0, 0 },
+ display_debug_abbrev, &do_trace_abbrevs, 0 },
+ { { ".trace_aranges", "", NULL, NULL, 0, 0, 0 },
+ display_debug_aranges, &do_trace_aranges, 0 },
{ { ".debug_info.dwo", ".zdebug_info.dwo", NULL, NULL, 0, 0, abbrev_dwo },
- display_debug_info, &do_debug_info, 1 },
- { { ".debug_abbrev.dwo", ".zdebug_abbrev.dwo", NULL, NULL, 0, 0, abbrev_dwo },
- display_debug_abbrev, &do_debug_abbrevs, 0 },
+ display_debug_info, &do_debug_info, 1 },
+ { { ".debug_abbrev.dwo", ".zdebug_abbrev.dwo", NULL, NULL, 0, 0, 0 },
+ display_debug_abbrev, &do_debug_abbrevs, 0 },
{ { ".debug_types.dwo", ".zdebug_types.dwo", NULL, NULL, 0, 0, abbrev_dwo },
- display_debug_types, &do_debug_info, 1 },
- { { ".debug_line.dwo", ".zdebug_line.dwo", NULL, NULL, 0, 0, abbrev_dwo },
- display_debug_lines, &do_debug_lines, 1 },
- { { ".debug_loc.dwo", ".zdebug_loc.dwo", NULL, NULL, 0, 0, abbrev_dwo },
+ display_debug_types, &do_debug_info, 1 },
+ { { ".debug_line.dwo", ".zdebug_line.dwo", NULL, NULL, 0, 0, 0 },
+ display_debug_lines, &do_debug_lines, 1 },
+ { { ".debug_loc.dwo", ".zdebug_loc.dwo", NULL, NULL, 0, 0, 0 },
display_debug_loc, &do_debug_loc, 1 },
- { { ".debug_macro.dwo", ".zdebug_macro.dwo",NULL, NULL, 0, 0, abbrev },
+ { { ".debug_macro.dwo", ".zdebug_macro.dwo", NULL, NULL, 0, 0, 0 },
display_debug_macro, &do_debug_macinfo, 1 },
- { { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo",NULL, NULL, 0, 0, abbrev },
+ { { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo", NULL, NULL, 0, 0, 0 },
display_debug_macinfo, &do_debug_macinfo, 0 },
- { { ".debug_str.dwo", ".zdebug_str.dwo", NULL, NULL, 0, 0, str_dwo },
- display_debug_str, &do_debug_str, 1 },
- { { ".debug_str_offsets",".zdebug_str_offsets", NULL, NULL, 0, 0, abbrev },
+ { { ".debug_str.dwo", ".zdebug_str.dwo", NULL, NULL, 0, 0, 0 },
+ display_debug_str, &do_debug_str, 1 },
+ { { ".debug_str_offsets", ".zdebug_str_offsets", NULL, NULL, 0, 0, 0 },
display_debug_str_offsets, NULL, 0 },
- { { ".debug_str_offsets.dwo",".zdebug_str_offsets.dwo", NULL, NULL, 0, 0,
- abbrev },
+ { { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo", NULL, NULL, 0, 0, 0 },
display_debug_str_offsets, NULL, 0 },
- { { ".debug_addr",".zdebug_addr", NULL, NULL, 0, 0, debug_addr },
- display_debug_addr, NULL, 1 },
+ { { ".debug_addr", ".zdebug_addr", NULL, NULL, 0, 0, 0 },
+ display_debug_addr, &do_debug_addr, 1 },
+ { { ".debug_cu_index", "", NULL, NULL, 0, 0, 0 },
+ display_cu_index, &do_debug_cu_index, 0 },
+ { { ".debug_tu_index", "", NULL, NULL, 0, 0, 0 },
+ display_cu_index, &do_debug_cu_index, 0 },
};