summaryrefslogtreecommitdiff
path: root/binutils/dwarf.c
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@google.com>2013-03-01 19:24:07 +0000
committerCary Coutant <ccoutant@google.com>2013-03-01 19:24:07 +0000
commit4ba9a128c88dd93f1295f4e2f9b1e68d76da6a7d (patch)
tree36cbf58941892a52058331bb775ddab70f348682 /binutils/dwarf.c
parentef5c66276a8a434d886e9a68ea70e3cfd86c432a (diff)
downloadbinutils-redhat-4ba9a128c88dd93f1295f4e2f9b1e68d76da6a7d.tar.gz
binutils/
* dwarf.c (cu_tu_indexes_read, shndx_pool, shndx_pool_size) (shndx_pool_used): Move to top of file. (struct cu_tu_set): New type. (cu_count, tu_count, cu_sets, tu_sets): New file scope variables. (fetch_indexed_string): Add "this_set" parameter. Update all callers. (find_cu_tu_set_v2): New function. (read_and_display_attr_value): Add "this_set" parameter. (read_and_display_attr): Likewise. (process_debug_info): Track base offsets for DWARF package files. (load_debug_info): Call load_cu_tu_indexes. (get_DW_SECT_short_name): New function. (process_cu_tu_index): Add support for version 2 DWARF package files.
Diffstat (limited to 'binutils/dwarf.c')
-rw-r--r--binutils/dwarf.c399
1 files changed, 337 insertions, 62 deletions
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 2d107a3258..8a55aeb7e7 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -71,6 +71,36 @@ unsigned long dwarf_start_die;
int dwarf_check = 0;
+/* Collection of CU/TU section sets from .debug_cu_index and .debug_tu_index
+ sections. For version 1 package files, 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. */
+
+static int cu_tu_indexes_read = 0;
+static unsigned int *shndx_pool = NULL;
+static unsigned int shndx_pool_size = 0;
+static unsigned int shndx_pool_used = 0;
+
+/* For version 2 package files, each set contains an array of section offsets
+ and an array of section sizes, giving the offset and size of the
+ contribution from a CU or TU within one of the debug sections.
+ When displaying debug info from a package file, we need to use these
+ tables to locate the corresponding contributions to each section. */
+
+struct cu_tu_set
+{
+ uint64_t signature;
+ dwarf_vma section_offsets[DW_SECT_MAX];
+ size_t section_sizes[DW_SECT_MAX];
+};
+
+static int cu_count = 0;
+static int tu_count = 0;
+static struct cu_tu_set *cu_sets = NULL;
+static struct cu_tu_set *tu_sets = NULL;
+
+static void load_cu_tu_indexes (void *file);
+
/* Values for do_debug_lines. */
#define FLAG_DEBUG_LINES_RAW 1
#define FLAG_DEBUG_LINES_DECODED 2
@@ -450,7 +480,8 @@ fetch_indirect_string (dwarf_vma offset)
}
static const char *
-fetch_indexed_string (dwarf_vma idx, dwarf_vma offset_size, int dwo)
+fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
+ dwarf_vma offset_size, int dwo)
{
enum dwarf_section_display_enum str_sec_idx = dwo ? str_dwo : str;
enum dwarf_section_display_enum idx_sec_idx = dwo ? str_index_dwo : str_index;
@@ -465,6 +496,8 @@ fetch_indexed_string (dwarf_vma idx, dwarf_vma offset_size, int dwo)
/* DWARF sections under Mach-O have non-zero addresses. */
index_offset -= index_section->address;
+ if (this_set != NULL)
+ index_offset += this_set->section_offsets [DW_SECT_STR_OFFSETS];
if (index_offset > index_section->size)
{
warn (_("DW_FORM_GNU_str_index offset too big: %s\n"),
@@ -1253,6 +1286,38 @@ decode_location_expression (unsigned char * data,
return need_frame_base;
}
+/* Find the CU or TU set corresponding to the given CU_OFFSET.
+ This is used for DWARF package files. */
+
+static struct cu_tu_set *
+find_cu_tu_set_v2 (dwarf_vma cu_offset, int do_types)
+{
+ struct cu_tu_set *p;
+ unsigned int nsets;
+ unsigned int dw_sect;
+
+ if (do_types)
+ {
+ p = tu_sets;
+ nsets = tu_count;
+ dw_sect = DW_SECT_TYPES;
+ }
+ else
+ {
+ p = cu_sets;
+ nsets = cu_count;
+ dw_sect = DW_SECT_INFO;
+ }
+ while (nsets > 0)
+ {
+ if (p->section_offsets [dw_sect] == cu_offset)
+ return p;
+ p++;
+ nsets--;
+ }
+ return NULL;
+}
+
static unsigned char *
read_and_display_attr_value (unsigned long attribute,
unsigned long form,
@@ -1263,7 +1328,8 @@ read_and_display_attr_value (unsigned long attribute,
int dwarf_version,
debug_info * debug_info_p,
int do_loc,
- struct dwarf_section * section)
+ struct dwarf_section * section,
+ struct cu_tu_set * this_set)
{
dwarf_vma uvalue = 0;
unsigned char *block_start = NULL;
@@ -1351,7 +1417,7 @@ read_and_display_attr_value (unsigned long attribute,
cu_offset, pointer_size,
offset_size, dwarf_version,
debug_info_p, do_loc,
- section);
+ section, this_set);
case DW_FORM_GNU_addr_index:
uvalue = read_leb128 (data, & bytes_read, 0);
data += bytes_read;
@@ -1475,7 +1541,7 @@ read_and_display_attr_value (unsigned long attribute,
printf (_(" (indexed string: 0x%s): %s"),
dwarf_vmatoa ("x", uvalue),
- fetch_indexed_string (uvalue, offset_size, dwo));
+ fetch_indexed_string (uvalue, this_set, offset_size, dwo));
}
break;
@@ -1553,6 +1619,8 @@ read_and_display_attr_value (unsigned long attribute,
lmax, sizeof (*debug_info_p->have_frame_base));
debug_info_p->max_loc_offsets = lmax;
}
+ if (this_set != NULL)
+ uvalue += this_set->section_offsets [DW_SECT_LOC];
debug_info_p->loc_offsets [num] = uvalue;
debug_info_p->have_frame_base [num] = have_frame_base;
debug_info_p->num_loc_offsets++;
@@ -1904,20 +1972,20 @@ read_and_display_attr (unsigned long attribute,
int dwarf_version,
debug_info * debug_info_p,
int do_loc,
- struct dwarf_section * section)
+ struct dwarf_section * section,
+ struct cu_tu_set * this_set)
{
if (!do_loc)
printf (" %-18s:", get_AT_name (attribute));
data = read_and_display_attr_value (attribute, form, data, cu_offset,
pointer_size, offset_size,
dwarf_version, debug_info_p,
- do_loc, section);
+ do_loc, section, this_set);
if (!do_loc)
printf ("\n");
return data;
}
-
/* Process the contents of a .debug_info section. If do_loc is non-zero
then we are scanning for location lists and we do not want to display
anything to the user. If do_types is non-zero, we are processing
@@ -2025,6 +2093,9 @@ process_debug_info (struct dwarf_section *section,
dwarf_vma signature_high = 0;
dwarf_vma signature_low = 0;
dwarf_vma type_offset = 0;
+ struct cu_tu_set *this_set;
+ dwarf_vma abbrev_base;
+ size_t abbrev_size;
hdrptr = start;
@@ -2049,9 +2120,22 @@ process_debug_info (struct dwarf_section *section,
cu_offset = start - section_begin;
+ this_set = find_cu_tu_set_v2 (cu_offset, do_types);
+
compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size);
hdrptr += offset_size;
+ if (this_set == NULL)
+ {
+ abbrev_base = 0;
+ abbrev_size = debug_displays [abbrev_sec].section.size;
+ }
+ else
+ {
+ abbrev_base = this_set->section_offsets [DW_SECT_ABBREV];
+ abbrev_size = this_set->section_sizes [DW_SECT_ABBREV];
+ }
+
compunit.cu_pointer_size = byte_get (hdrptr, 1);
hdrptr += 1;
@@ -2105,6 +2189,25 @@ process_debug_info (struct dwarf_section *section,
printf (_(" Type Offset: 0x%s\n"),
dwarf_vmatoa ("x", type_offset));
}
+ if (this_set != NULL)
+ {
+ dwarf_vma *offsets = this_set->section_offsets;
+ size_t *sizes = this_set->section_sizes;
+
+ printf (_(" Section contributions:\n"));
+ printf (_(" .debug_abbrev.dwo: 0x%s 0x%s\n"),
+ dwarf_vmatoa ("x", offsets [DW_SECT_ABBREV]),
+ dwarf_vmatoa ("x", sizes [DW_SECT_ABBREV]));
+ printf (_(" .debug_line.dwo: 0x%s 0x%s\n"),
+ dwarf_vmatoa ("x", offsets [DW_SECT_LINE]),
+ dwarf_vmatoa ("x", sizes [DW_SECT_LINE]));
+ printf (_(" .debug_loc.dwo: 0x%s 0x%s\n"),
+ dwarf_vmatoa ("x", offsets [DW_SECT_LOC]),
+ dwarf_vmatoa ("x", sizes [DW_SECT_LOC]));
+ printf (_(" .debug_str_offsets.dwo: 0x%s 0x%s\n"),
+ dwarf_vmatoa ("x", offsets [DW_SECT_STR_OFFSETS]),
+ dwarf_vmatoa ("x", sizes [DW_SECT_STR_OFFSETS]));
+ }
}
if (cu_offset + compunit.cu_length + initial_length_size
@@ -2133,16 +2236,16 @@ process_debug_info (struct dwarf_section *section,
/* Process the abbrevs used by this compilation unit. DWARF
sections under Mach-O have non-zero addresses. */
- if (compunit.cu_abbrev_offset >= debug_displays [abbrev_sec].section.size)
+ if (compunit.cu_abbrev_offset >= abbrev_size)
warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than abbrev section size (%lx)\n"),
(unsigned long) compunit.cu_abbrev_offset,
- (unsigned long) debug_displays [abbrev_sec].section.size);
+ (unsigned long) abbrev_size);
else
process_abbrev_section
- ((unsigned char *) debug_displays [abbrev_sec].section.start
- + compunit.cu_abbrev_offset,
- (unsigned char *) debug_displays [abbrev_sec].section.start
- + debug_displays [abbrev_sec].section.size);
+ (((unsigned char *) debug_displays [abbrev_sec].section.start
+ + abbrev_base + compunit.cu_abbrev_offset),
+ ((unsigned char *) debug_displays [abbrev_sec].section.start
+ + abbrev_base + abbrev_size));
level = 0;
last_level = level;
@@ -2274,12 +2377,15 @@ process_debug_info (struct dwarf_section *section,
tags = read_and_display_attr (attr->attribute,
attr->form,
- tags, cu_offset,
+ tags,
+ cu_offset,
compunit.cu_pointer_size,
offset_size,
compunit.cu_version,
arg,
- do_loc || ! do_printing, section);
+ do_loc || ! do_printing,
+ section,
+ this_set);
}
if (entry->children)
@@ -2323,6 +2429,9 @@ load_debug_info (void * file)
if (num_debug_info_entries > 0)
return num_debug_info_entries;
+ /* If this is a DWARF package file, load the CU and TU indexes. */
+ load_cu_tu_indexes (file);
+
if (load_debug_section (info, file)
&& process_debug_info (&debug_displays [info].section, file, abbrev, 1, 0))
return num_debug_info_entries;
@@ -3715,7 +3824,8 @@ display_debug_macro (struct dwarf_section *section,
curr
= read_and_display_attr_value (0, byte_get (desc++, 1),
curr, 0, 0, offset_size,
- version, NULL, 0, NULL);
+ version, NULL, 0, NULL,
+ NULL);
if (n != nargs - 1)
printf (",");
}
@@ -3888,7 +3998,7 @@ print_addr_index (unsigned int idx, unsigned int len)
{
static char buf[15];
snprintf (buf, sizeof (buf), "[%d]", idx);
- printf("%*s ", len, buf);
+ printf ("%*s ", len, buf);
}
/* Display a location list from a .dwo section. It uses address indexes rather
@@ -5878,15 +5988,6 @@ 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
@@ -5929,7 +6030,42 @@ end_cu_tu_entry (void)
shndx_pool [shndx_pool_used++] = 0;
}
-/* Process a CU or TU index. If DO_DISPLAY is true, print the contents. */
+/* Return the short name of a DWARF section given by a DW_SECT enumerator. */
+
+static const char *
+get_DW_SECT_short_name (unsigned int dw_sect)
+{
+ static char buf[16];
+
+ switch (dw_sect)
+ {
+ case DW_SECT_INFO:
+ return "info";
+ case DW_SECT_TYPES:
+ return "types";
+ case DW_SECT_ABBREV:
+ return "abbrev";
+ case DW_SECT_LINE:
+ return "line";
+ case DW_SECT_LOC:
+ return "loc";
+ case DW_SECT_STR_OFFSETS:
+ return "str_off";
+ case DW_SECT_MACINFO:
+ return "macinfo";
+ case DW_SECT_MACRO:
+ return "macro";
+ default:
+ break;
+ }
+
+ snprintf (buf, sizeof (buf), "%d", dw_sect);
+ return buf;
+}
+
+/* Process a CU or TU index. If DO_DISPLAY is true, print the contents.
+ These sections are extensions for Fission.
+ See http://gcc.gnu.org/wiki/DebugFissionDWP. */
static int
process_cu_tu_index (struct dwarf_section *section, int do_display)
@@ -5940,24 +6076,30 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
unsigned char *pindex;
unsigned char *ppool;
unsigned int version;
+ unsigned int ncols = 0;
unsigned int nused;
unsigned int nslots;
unsigned int i;
+ unsigned int j;
+ dwarf_vma signature_high;
+ dwarf_vma signature_low;
+ char buf[64];
version = byte_get (phdr, 4);
+ if (version >= 2)
+ ncols = byte_get (phdr + 4, 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);
+ if (version >= 2)
+ printf (_(" Number of columns: %d\n"), ncols);
printf (_(" Number of used entries: %d\n"), nused);
printf (_(" Number of slots: %d\n\n"), nslots);
}
@@ -5969,49 +6111,182 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
return 0;
}
- for (i = 0; i < nslots; i++)
+ if (version == 1)
{
- 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)
+ if (!do_display)
+ prealloc_cu_tu_list ((limit - ppool) / 4);
+ for (i = 0; i < nslots; i++)
{
- 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 (;;)
+ unsigned char *shndx_list;
+ unsigned int shndx;
+
+ byte_get_64 (phash, &signature_high, &signature_low);
+ if (signature_high != 0 || signature_low != 0)
{
- if (shndx_list >= limit)
+ 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 (;;)
{
- warn (_("Section %s too small for shndx pool\n"),
- section->name);
- return 0;
+ 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;
}
- shndx = byte_get (shndx_list, 4);
- if (shndx == 0)
- break;
if (do_display)
- printf (" %d", shndx);
+ printf ("\n");
else
- add_shndx_to_cu_tu_entry (shndx);
- shndx_list += 4;
+ end_cu_tu_entry ();
+ }
+ phash += 8;
+ pindex += 4;
+ }
+ }
+ else if (version == 2)
+ {
+ unsigned int val;
+ unsigned int dw_sect;
+ unsigned char *ph = phash;
+ unsigned char *pi = pindex;
+ unsigned char *poffsets = ppool + ncols * 4;
+ unsigned char *psizes = poffsets + nused * ncols * 4;
+ unsigned char *pend = psizes + nused * ncols * 4;
+ bfd_boolean is_tu_index;
+ struct cu_tu_set *this_set = NULL;
+ unsigned int row;
+ unsigned char *prow;
+
+ is_tu_index = strcmp (section->name, ".debug_tu_index") == 0;
+
+ if (pend > limit)
+ {
+ warn (_("Section %s too small for offset and size tables\n"),
+ section->name);
+ return 0;
+ }
+
+ if (do_display)
+ {
+ printf (_(" Offset table\n"));
+ printf (" slot %-16s ",
+ is_tu_index ? _("signature") : _("dwo_id"));
+ }
+ else
+ {
+ if (is_tu_index)
+ {
+ tu_count = nused;
+ tu_sets = xcmalloc (nused, sizeof (struct cu_tu_set));
+ this_set = tu_sets;
}
- if (do_display)
- printf ("\n");
else
- end_cu_tu_entry ();
+ {
+ cu_count = nused;
+ cu_sets = xcmalloc (nused, sizeof (struct cu_tu_set));
+ this_set = cu_sets;
+ }
+ }
+ if (do_display)
+ {
+ for (j = 0; j < ncols; j++)
+ {
+ dw_sect = byte_get (ppool + j * 4, 4);
+ printf (" %8s", get_DW_SECT_short_name (dw_sect));
+ }
+ printf ("\n");
+ }
+ for (i = 0; i < nslots; i++)
+ {
+ byte_get_64 (ph, &signature_high, &signature_low);
+ row = byte_get (pi, 4);
+ if (row != 0)
+ {
+ if (!do_display)
+ memcpy (&this_set[row - 1].signature, ph, sizeof (uint64_t));
+ prow = poffsets + (row - 1) * ncols * 4;
+ if (do_display)
+ printf (_(" [%3d] 0x%s"),
+ i, dwarf_vmatoa64 (signature_high, signature_low,
+ buf, sizeof (buf)));
+ for (j = 0; j < ncols; j++)
+ {
+ val = byte_get (prow + j * 4, 4);
+ if (do_display)
+ printf (" %8d", val);
+ else
+ {
+ dw_sect = byte_get (ppool + j * 4, 4);
+ this_set [row - 1].section_offsets [dw_sect] = val;
+ }
+ }
+ if (do_display)
+ printf ("\n");
+ }
+ ph += 8;
+ pi += 4;
+ }
+
+ ph = phash;
+ pi = pindex;
+ if (do_display)
+ {
+ printf ("\n");
+ printf (_(" Size table\n"));
+ printf (" slot %-16s ",
+ is_tu_index ? _("signature") : _("dwo_id"));
+ }
+ for (j = 0; j < ncols; j++)
+ {
+ val = byte_get (ppool + j * 4, 4);
+ if (do_display)
+ printf (" %8s", get_DW_SECT_short_name (val));
+ }
+ if (do_display)
+ printf ("\n");
+ for (i = 0; i < nslots; i++)
+ {
+ byte_get_64 (ph, &signature_high, &signature_low);
+ row = byte_get (pi, 4);
+ if (row != 0)
+ {
+ prow = psizes + (row - 1) * ncols * 4;
+ if (do_display)
+ printf (_(" [%3d] 0x%s"),
+ i, dwarf_vmatoa64 (signature_high, signature_low,
+ buf, sizeof (buf)));
+ for (j = 0; j < ncols; j++)
+ {
+ val = byte_get (prow + j * 4, 4);
+ if (do_display)
+ printf (" %8d", val);
+ else
+ {
+ dw_sect = byte_get (ppool + j * 4, 4);
+ this_set [row - 1].section_sizes [dw_sect] = val;
+ }
+ }
+ if (do_display)
+ printf ("\n");
+ }
+ ph += 8;
+ pi += 4;
}
- phash += 8;
- pindex += 4;
}
+ else if (do_display)
+ printf (_(" Unsupported version\n"));
if (do_display)
printf ("\n");