Add support for reading Aarch64 core dumps.
[binutils-gdb.git] / binutils / dwarf.c
index d5f7baf33a152368358cdbbbf583e767c97765ea..a6986ad4045d8ef9cecb30808e8d637cc840d637 100644 (file)
@@ -1,5 +1,5 @@
 /* dwarf.c -- display DWARF contents of a BFD binary file
-   Copyright 2005-2013 Free Software Foundation, Inc.
+   Copyright (C) 2005-2014 Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
 
 #include "dwarf.h"
 #include "gdb/gdb-index.h"
 
-#if !HAVE_DECL_STRNLEN
-size_t strnlen (const char *, size_t);
-#endif
-
 static const char *regname (unsigned int regno, int row);
 
 static int have_frame_base;
@@ -560,8 +556,6 @@ fetch_indirect_string (dwarf_vma offset)
   if (section->start == NULL)
     return (const unsigned char *) _("<no .debug_str section>");
 
-  /* DWARF sections under Mach-O have non-zero addresses.  */
-  offset -= section->address;
   if (offset > section->size)
     {
       warn (_("DW_FORM_strp offset too big: %s\n"),
@@ -587,8 +581,6 @@ fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
     return (dwo ? _("<no .debug_str_offsets.dwo section>")
                : _("<no .debug_str_offsets section>"));
 
-  /* 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)
@@ -1472,7 +1464,7 @@ read_and_display_attr_value (unsigned long attribute,
   unsigned char * orig_data = data;
   unsigned int bytes_read;
 
-  if (data == end)
+  if (data == end && form != DW_FORM_flag_present)
     {
       warn (_("corrupt attribute\n"));
       return data;
@@ -1595,6 +1587,7 @@ read_and_display_attr_value (unsigned long attribute,
 
     case DW_FORM_ref8:
     case DW_FORM_data8:
+      if (!do_loc)
        {
          dwarf_vma high_bits;
          dwarf_vma utmp;
@@ -1808,11 +1801,10 @@ read_and_display_attr_value (unsigned long attribute,
     return data;
 
   /* For some attributes we can display further information.  */
-  printf ("\t");
-
   switch (attribute)
     {
     case DW_AT_inline:
+      printf ("\t");
       switch (uvalue)
        {
        case DW_INL_not_inlined:
@@ -1835,6 +1827,7 @@ read_and_display_attr_value (unsigned long attribute,
       break;
 
     case DW_AT_language:
+      printf ("\t");
       switch (uvalue)
        {
          /* Ordered by the numeric value of these constants.  */
@@ -1878,6 +1871,7 @@ read_and_display_attr_value (unsigned long attribute,
       break;
 
     case DW_AT_encoding:
+      printf ("\t");
       switch (uvalue)
        {
        case DW_ATE_void:               printf ("(void)"); break;
@@ -1918,6 +1912,7 @@ read_and_display_attr_value (unsigned long attribute,
       break;
 
     case DW_AT_accessibility:
+      printf ("\t");
       switch (uvalue)
        {
        case DW_ACCESS_public:          printf ("(public)"); break;
@@ -1930,6 +1925,7 @@ read_and_display_attr_value (unsigned long attribute,
       break;
 
     case DW_AT_visibility:
+      printf ("\t");
       switch (uvalue)
        {
        case DW_VIS_local:              printf ("(local)"); break;
@@ -1940,6 +1936,7 @@ read_and_display_attr_value (unsigned long attribute,
       break;
 
     case DW_AT_virtuality:
+      printf ("\t");
       switch (uvalue)
        {
        case DW_VIRTUALITY_none:        printf ("(none)"); break;
@@ -1950,6 +1947,7 @@ read_and_display_attr_value (unsigned long attribute,
       break;
 
     case DW_AT_identifier_case:
+      printf ("\t");
       switch (uvalue)
        {
        case DW_ID_case_sensitive:      printf ("(case_sensitive)"); break;
@@ -1961,6 +1959,7 @@ read_and_display_attr_value (unsigned long attribute,
       break;
 
     case DW_AT_calling_convention:
+      printf ("\t");
       switch (uvalue)
        {
        case DW_CC_normal:      printf ("(normal)"); break;
@@ -1976,6 +1975,7 @@ read_and_display_attr_value (unsigned long attribute,
       break;
 
     case DW_AT_ordering:
+      printf ("\t");
       switch (uvalue)
        {
        case -1: printf (_("(undefined)")); break;
@@ -2001,7 +2001,7 @@ read_and_display_attr_value (unsigned long attribute,
       if ((dwarf_version < 4
            && (form == DW_FORM_data4 || form == DW_FORM_data8))
          || form == DW_FORM_sec_offset)
-       printf (_("(location list)"));
+       printf (_(" (location list)"));
       /* Fall through.  */
     case DW_AT_allocated:
     case DW_AT_associated:
@@ -2013,7 +2013,7 @@ read_and_display_attr_value (unsigned long attribute,
        {
          int need_frame_base;
 
-         printf ("(");
+         printf ("\t(");
          need_frame_base = decode_location_expression (block_start,
                                                        pointer_size,
                                                        offset_size,
@@ -2049,7 +2049,7 @@ read_and_display_attr_value (unsigned long attribute,
 
            abbrev_number = read_uleb128 (section->start + uvalue, NULL, end);
 
-           printf (_("[Abbrev Number: %ld"), abbrev_number);
+           printf (_("\t[Abbrev Number: %ld"), abbrev_number);
            /* Don't look up abbrev for DW_FORM_ref_addr, as it very often will
               use different abbrev table, and we don't track .debug_info chunks
               yet.  */
@@ -2366,8 +2366,7 @@ process_debug_info (struct dwarf_section *section,
 
       free_abbrevs ();
 
-      /* Process the abbrevs used by this compilation unit. DWARF
-        sections under Mach-O have non-zero addresses.  */
+      /* Process the abbrevs used by this compilation unit.  */
       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,
@@ -3506,9 +3505,29 @@ find_debug_info_for_offset (unsigned long offset)
   return NULL;
 }
 
+static const char *
+get_gdb_index_symbol_kind_name (gdb_index_symbol_kind kind)
+{
+  /* See gdb/gdb-index.h.  */
+  static const char * const kinds[] =
+  {
+    N_ ("no info"),
+    N_ ("type"),
+    N_ ("variable"),
+    N_ ("function"),
+    N_ ("other"),
+    N_ ("unused5"),
+    N_ ("unused6"),
+    N_ ("unused7")
+  };
+
+  return _ (kinds[kind]);
+}
+
 static int
-display_debug_pubnames (struct dwarf_section *section,
-                       void *file ATTRIBUTE_UNUSED)
+display_debug_pubnames_worker (struct dwarf_section *section,
+                              void *file ATTRIBUTE_UNUSED,
+                              int is_gnu)
 {
   DWARF2_Internal_PubNames names;
   unsigned char *start = section->start;
@@ -3576,7 +3595,10 @@ display_debug_pubnames (struct dwarf_section *section,
       printf (_("  Size of area in .debug_info section: %ld\n"),
              (long) names.pn_size);
 
-      printf (_("\n    Offset\tName\n"));
+      if (is_gnu)
+       printf (_("\n    Offset  Kind          Name\n"));
+      else
+       printf (_("\n    Offset\tName\n"));
 
       do
        {
@@ -3585,7 +3607,29 @@ display_debug_pubnames (struct dwarf_section *section,
          if (offset != 0)
            {
              data += offset_size;
-             printf ("    %-6lx\t%s\n", offset, data);
+             if (is_gnu)
+               {
+                 unsigned int kind_data;
+                 gdb_index_symbol_kind kind;
+                 const char *kind_name;
+                 int is_static;
+
+                 SAFE_BYTE_GET (kind_data, data, 1, end);
+                 data++;
+                 /* GCC computes the kind as the upper byte in the CU index
+                    word, and then right shifts it by the CU index size.
+                    Left shift KIND to where the gdb-index.h accessor macros
+                    can use it.  */
+                 kind_data <<= GDB_INDEX_CU_BITSIZE;
+                 kind = GDB_INDEX_SYMBOL_KIND_VALUE (kind_data);
+                 kind_name = get_gdb_index_symbol_kind_name (kind);
+                 is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (kind_data);
+                 printf ("    %-6lx  %s,%-10s  %s\n",
+                         offset, is_static ? _("s") : _("g"),
+                         kind_name, data);
+               }
+             else
+               printf ("    %-6lx\t%s\n", offset, data);
              data += strnlen ((char *) data, end - data) + 1;
            }
        }
@@ -3596,6 +3640,18 @@ display_debug_pubnames (struct dwarf_section *section,
   return 1;
 }
 
+static int
+display_debug_pubnames (struct dwarf_section *section, void *file)
+{
+  return display_debug_pubnames_worker (section, file, 0);
+}
+
+static int
+display_debug_gnu_pubnames (struct dwarf_section *section, void *file)
+{
+  return display_debug_pubnames_worker (section, file, 1);
+}
+
 static int
 display_debug_macinfo (struct dwarf_section *section,
                       void *file ATTRIBUTE_UNUSED)
@@ -4373,9 +4429,8 @@ display_debug_loc (struct dwarf_section *section, void *file)
   if (!seen_first_offset)
     error (_("No location lists in .debug_info section!\n"));
 
-  /* DWARF sections under Mach-O have non-zero addresses.  */
   if (debug_information [first].num_loc_offsets > 0
-      && debug_information [first].loc_offsets [0] != section->address)
+      && debug_information [first].loc_offsets [0] != 0)
     warn (_("Location lists in %s section start at 0x%s\n"),
          section->name,
          dwarf_vmatoa ("x", debug_information [first].loc_offsets [0]));
@@ -4410,8 +4465,7 @@ display_debug_loc (struct dwarf_section *section, void *file)
                 == debug_information [i].loc_offsets [j])
            continue;
          has_frame_base = debug_information [i].have_frame_base [j];
-         /* DWARF sections under Mach-O have non-zero addresses.  */
-         offset = debug_information [i].loc_offsets [j] - section->address;
+         offset = debug_information [i].loc_offsets [j];
          next = section_begin + offset;
          base_address = debug_information [i].base_address;
 
@@ -4819,8 +4873,7 @@ display_debug_ranges (struct dwarf_section *section,
   qsort (range_entries, num_range_list, sizeof (*range_entries),
         range_entry_compar);
 
-  /* DWARF sections under Mach-O have non-zero addresses.  */
-  if (dwarf_check != 0 && range_entries[0].ranges_offset != section->address)
+  if (dwarf_check != 0 && range_entries[0].ranges_offset != 0)
     warn (_("Range lists in %s section start at 0x%lx\n"),
          section->name, range_entries[0].ranges_offset);
 
@@ -4838,8 +4891,7 @@ display_debug_ranges (struct dwarf_section *section,
 
       pointer_size = debug_info_p->pointer_size;
 
-      /* DWARF sections under Mach-O have non-zero addresses.  */
-      offset = range_entry->ranges_offset - section->address;
+      offset = range_entry->ranges_offset;
       next = section_begin + offset;
       base_address = debug_info_p->base_address;
 
@@ -5777,12 +5829,16 @@ display_debug_frames (struct dwarf_section *section,
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_remember_state\n");
              rs = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
+              rs->cfa_offset = fc->cfa_offset;
+             rs->cfa_reg = fc->cfa_reg;
+             rs->ra = fc->ra;
+             rs->cfa_exp = fc->cfa_exp;
              rs->ncols = fc->ncols;
              rs->col_type = (short int *) xcmalloc (rs->ncols,
-                                                     sizeof (short int));
-             rs->col_offset = (int *) xcmalloc (rs->ncols, sizeof (int));
-             memcpy (rs->col_type, fc->col_type, rs->ncols);
-             memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int));
+                                                     sizeof (* rs->col_type));
+             rs->col_offset = (int *) xcmalloc (rs->ncols, sizeof (* rs->col_offset));
+             memcpy (rs->col_type, fc->col_type, rs->ncols * sizeof (* fc->col_type));
+             memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (* fc->col_offset));
              rs->next = remembered_state;
              remembered_state = rs;
              break;
@@ -5794,10 +5850,14 @@ display_debug_frames (struct dwarf_section *section,
              if (rs)
                {
                  remembered_state = rs->next;
+                 fc->cfa_offset = rs->cfa_offset;
+                 fc->cfa_reg = rs->cfa_reg;
+                 fc->ra = rs->ra;
+                 fc->cfa_exp = rs->cfa_exp;
                  frame_need_space (fc, rs->ncols - 1);
-                 memcpy (fc->col_type, rs->col_type, rs->ncols);
+                 memcpy (fc->col_type, rs->col_type, rs->ncols * sizeof (* rs->col_type));
                  memcpy (fc->col_offset, rs->col_offset,
-                         rs->ncols * sizeof (int));
+                         rs->ncols * sizeof (* rs->col_offset));
                  free (rs->col_type);
                  free (rs->col_offset);
                  free (rs);
@@ -6140,38 +6200,9 @@ display_gdb_index (struct dwarf_section *section,
              else
                printf ("%c%lu", num_cus > 1 ? '\t' : ' ', (unsigned long) cu);
 
-             switch (kind)
-               {
-               case GDB_INDEX_SYMBOL_KIND_NONE:
-                 printf (_(" [no symbol information]"));
-                 break;
-               case GDB_INDEX_SYMBOL_KIND_TYPE:
-                 printf (is_static
-                         ? _(" [static type]")
-                         : _(" [global type]"));
-                 break;
-               case GDB_INDEX_SYMBOL_KIND_VARIABLE:
-                 printf (is_static
-                         ? _(" [static variable]")
-                         : _(" [global variable]"));
-                 break;
-               case GDB_INDEX_SYMBOL_KIND_FUNCTION:
-                 printf (is_static
-                         ? _(" [static function]")
-                         : _(" [global function]"));
-                 break;
-               case GDB_INDEX_SYMBOL_KIND_OTHER:
-                 printf (is_static
-                         ? _(" [static other]")
-                         : _(" [global other]"));
-                 break;
-               default:
-                 printf (is_static
-                         ? _(" [static unknown: %d]")
-                         : _(" [global unknown: %d]"),
-                         kind);
-                 break;
-               }
+             printf (" [%s, %s]",
+                     is_static ? _("static") : _("global"),
+                     get_gdb_index_symbol_kind_name (kind));
              if (num_cus > 1)
                printf ("\n");
            }
@@ -6795,6 +6826,8 @@ struct dwarf_section_display debug_displays[] =
     display_debug_lines,    &do_debug_lines,   1 },
   { { ".debug_pubnames",    ".zdebug_pubnames",        NULL, NULL, 0, 0, 0 },
     display_debug_pubnames, &do_debug_pubnames,        0 },
+  { { ".debug_gnu_pubnames", ".zdebug_gnu_pubnames", NULL, NULL, 0, 0, 0 },
+    display_debug_gnu_pubnames, &do_debug_pubnames, 0 },
   { { ".eh_frame",         "",                 NULL, NULL, 0, 0, 0 },
     display_debug_frames,   &do_debug_frames,  1 },
   { { ".debug_macinfo",            ".zdebug_macinfo",  NULL, NULL, 0, 0, 0 },
@@ -6807,6 +6840,8 @@ struct dwarf_section_display debug_displays[] =
     display_debug_loc,     &do_debug_loc,      1 },
   { { ".debug_pubtypes",    ".zdebug_pubtypes",        NULL, NULL, 0, 0, 0 },
     display_debug_pubnames, &do_debug_pubtypes,        0 },
+  { { ".debug_gnu_pubtypes", ".zdebug_gnu_pubtypes", NULL, NULL, 0, 0, 0 },
+    display_debug_gnu_pubnames, &do_debug_pubtypes, 0 },
   { { ".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, 0 },