* dwarf2.c: Formatting.
authorAlan Modra <amodra@gmail.com>
Wed, 16 May 2012 13:57:11 +0000 (13:57 +0000)
committerAlan Modra <amodra@gmail.com>
Wed, 16 May 2012 13:57:11 +0000 (13:57 +0000)
(arange_add): Pass in unit rather than bfd.  Update callers.
Ignore empty ranges.  Don't ask for cleared memory.
(parse_comp_unit): Only set unit->base_address if processing
DW_TAG_compile_unit.
(find_debug_info): Optimise section lookup.
(place_sections): Use bfd_alloc for stash->adjusted_sections.
(find_line): Match previously parsed comp unit addresses as we
do for newly parsed comp units.

bfd/ChangeLog
bfd/dwarf2.c

index 9db6ed3..760d4d9 100644 (file)
@@ -1,5 +1,17 @@
 2012-05-16  Alan Modra  <amodra@gmail.com>
 
+       * dwarf2.c: Formatting.
+       (arange_add): Pass in unit rather than bfd.  Update callers.
+       Ignore empty ranges.  Don't ask for cleared memory.
+       (parse_comp_unit): Only set unit->base_address if processing
+       DW_TAG_compile_unit.
+       (find_debug_info): Optimise section lookup.
+       (place_sections): Use bfd_alloc for stash->adjusted_sections.
+       (find_line): Match previously parsed comp unit addresses as we
+       do for newly parsed comp units.
+
+2012-05-16  Alan Modra  <amodra@gmail.com>
+
        * archive.c (_bfd_generic_read_ar_hdr_mag):  Ensure sscanf
        stops at end of ar_size field.
 
index f7d5d4a..d31b849 100644 (file)
@@ -405,8 +405,8 @@ create_info_hash_table (bfd *abfd)
 {
   struct info_hash_table *hash_table;
 
-  hash_table = (struct info_hash_table *)
-      bfd_alloc (abfd, sizeof (struct info_hash_table));
+  hash_table = ((struct info_hash_table *)
+               bfd_alloc (abfd, sizeof (struct info_hash_table)));
   if (!hash_table)
     return hash_table;
 
@@ -503,7 +503,7 @@ read_section (bfd *           abfd,
       if (syms)
        {
          *section_buffer
-             = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, syms);
+           = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, syms);
          if (! *section_buffer)
            return FALSE;
        }
@@ -522,7 +522,8 @@ read_section (bfd *           abfd,
      that the client wants.  Validate it here to avoid trouble later.  */
   if (offset != 0 && offset >= *section_size)
     {
-      (*_bfd_error_handler) (_("Dwarf Error: Offset (%lu) greater than or equal to %s size (%lu)."),
+      (*_bfd_error_handler) (_("Dwarf Error: Offset (%lu)"
+                              " greater than or equal to %s size (%lu)."),
                             (long) offset, section_name, *section_size);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
@@ -1014,20 +1015,27 @@ struct line_info_table
 /* Remember some information about each function.  If the function is
    inlined (DW_TAG_inlined_subroutine) it may have two additional
    attributes, DW_AT_call_file and DW_AT_call_line, which specify the
-   source code location where this function was inlined. */
+   source code location where this function was inlined.  */
 
 struct funcinfo
 {
-  struct funcinfo *prev_func;          /* Pointer to previous function in list of all functions */
-  struct funcinfo *caller_func;                /* Pointer to function one scope higher */
-  char *caller_file;                   /* Source location file name where caller_func inlines this func */
-  int caller_line;                     /* Source location line number where caller_func inlines this func */
-  char *file;                          /* Source location file name */
-  int line;                            /* Source location line number */
+  /* Pointer to previous function in list of all functions.  */
+  struct funcinfo *prev_func;
+  /* Pointer to function one scope higher.  */
+  struct funcinfo *caller_func;
+  /* Source location file name where caller_func inlines this func.  */
+  char *caller_file;
+  /* Source location line number where caller_func inlines this func.  */
+  int caller_line;
+  /* Source location file name.  */
+  char *file;
+  /* Source location line number.  */
+  int line;
   int tag;
   char *name;
   struct arange arange;
-  asection *sec;                       /* Where the symbol is defined */
+  /* Where the symbol is defined.  */
+  asection *sec;
 };
 
 struct varinfo
@@ -1248,12 +1256,16 @@ concat_filename (struct line_info_table *table, unsigned int file)
 }
 
 static bfd_boolean
-arange_add (bfd *abfd, struct arange *first_arange,
+arange_add (const struct comp_unit *unit, struct arange *first_arange,
            bfd_vma low_pc, bfd_vma high_pc)
 {
   struct arange *arange;
 
-  /* If the first arange is empty, use it. */
+  /* Ignore empty ranges.  */
+  if (low_pc == high_pc)
+    return TRUE;
+
+  /* If the first arange is empty, use it.  */
   if (first_arange->high == 0)
     {
       first_arange->low = low_pc;
@@ -1281,7 +1293,7 @@ arange_add (bfd *abfd, struct arange *first_arange,
 
   /* Need to allocate a new arange and insert it into the arange list.
      Order isn't significant, so just insert after the first arange. */
-  arange = (struct arange *) bfd_zalloc (abfd, sizeof (*arange));
+  arange = (struct arange *) bfd_alloc (unit->abfd, sizeof (*arange));
   if (arange == NULL)
     return FALSE;
   arange->low = low_pc;
@@ -1582,15 +1594,15 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
              /* Special operand.  */
              adj_opcode = op_code - lh.opcode_base;
              if (lh.maximum_ops_per_insn == 1)
-               address += (adj_opcode / lh.line_range)
-                          * lh.minimum_instruction_length;
+               address += (adj_opcode / lh.line_range
+                           * lh.minimum_instruction_length);
              else
                {
-                 address += ((op_index + (adj_opcode / lh.line_range))
-                             / lh.maximum_ops_per_insn)
-                            * lh.minimum_instruction_length;
-                 op_index = (op_index + (adj_opcode / lh.line_range))
-                            % lh.maximum_ops_per_insn;
+                 address += ((op_index + adj_opcode / lh.line_range)
+                             / lh.maximum_ops_per_insn
+                             * lh.minimum_instruction_length);
+                 op_index = ((op_index + adj_opcode / lh.line_range)
+                             % lh.maximum_ops_per_insn);
                }
              line += lh.line_base + (adj_opcode % lh.line_range);
              /* Append row to matrix using current values.  */
@@ -1605,7 +1617,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
          else switch (op_code)
            {
            case DW_LNS_extended_op:
-              exop_len = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+             exop_len = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
              line_ptr += bytes_read;
              extended_op = read_1_byte (abfd, line_ptr);
              line_ptr += 1;
@@ -1621,7 +1633,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
                    low_pc = address;
                  if (address > high_pc)
                    high_pc = address;
-                 if (!arange_add (unit->abfd, &unit->arange, low_pc, high_pc))
+                 if (!arange_add (unit, &unit->arange, low_pc, high_pc))
                    goto line_fail;
                  break;
                case DW_LNE_set_address:
@@ -1659,11 +1671,12 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
                  (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                  line_ptr += bytes_read;
                  break;
-                case DW_LNE_HP_source_file_correlation:
-                  line_ptr += exop_len - 1;
-                  break;
+               case DW_LNE_HP_source_file_correlation:
+                 line_ptr += exop_len - 1;
+                 break;
                default:
-                 (*_bfd_error_handler) (_("Dwarf Error: mangled line number section."));
+                 (*_bfd_error_handler)
+                   (_("Dwarf Error: mangled line number section."));
                  bfd_set_error (bfd_error_bad_value);
                line_fail:
                  if (filename != NULL)
@@ -1682,15 +1695,15 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
              break;
            case DW_LNS_advance_pc:
              if (lh.maximum_ops_per_insn == 1)
-               address += lh.minimum_instruction_length
-                          * read_unsigned_leb128 (abfd, line_ptr,
-                                                  &bytes_read);
+               address += (lh.minimum_instruction_length
+                           * read_unsigned_leb128 (abfd, line_ptr,
+                                                   &bytes_read));
              else
                {
                  bfd_vma adjust = read_unsigned_leb128 (abfd, line_ptr,
                                                         &bytes_read);
-                 address = ((op_index + adjust) / lh.maximum_ops_per_insn)
-                           * lh.minimum_instruction_length;
+                 address = ((op_index + adjust) / lh.maximum_ops_per_insn
+                            * lh.minimum_instruction_length);
                  op_index = (op_index + adjust) % lh.maximum_ops_per_insn;
                }
              line_ptr += bytes_read;
@@ -1723,13 +1736,14 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
              break;
            case DW_LNS_const_add_pc:
              if (lh.maximum_ops_per_insn == 1)
-               address += lh.minimum_instruction_length
-                          * ((255 - lh.opcode_base) / lh.line_range);
+               address += (lh.minimum_instruction_length
+                           * ((255 - lh.opcode_base) / lh.line_range));
              else
                {
                  bfd_vma adjust = ((255 - lh.opcode_base) / lh.line_range);
-                 address += lh.minimum_instruction_length
-                            * ((op_index + adjust) / lh.maximum_ops_per_insn);
+                 address += (lh.minimum_instruction_length
+                             * ((op_index + adjust)
+                                / lh.maximum_ops_per_insn));
                  op_index = (op_index + adjust) % lh.maximum_ops_per_insn;
                }
              break;
@@ -1855,8 +1869,9 @@ lookup_address_in_function_table (struct comp_unit *unit,
        {
          if (addr >= arange->low && addr < arange->high)
            {
-             if (!best_fit ||
-                 ((arange->high - arange->low) < (best_fit->arange.high - best_fit->arange.low)))
+             if (!best_fit
+                 || (arange->high - arange->low
+                     < best_fit->arange.high - best_fit->arange.low))
                best_fit = each_func;
            }
        }
@@ -1904,8 +1919,8 @@ lookup_symbol_in_function_table (struct comp_unit *unit,
              && each_func->name
              && strcmp (name, each_func->name) == 0
              && (!best_fit
-                 || ((arange->high - arange->low)
-                     < (best_fit->arange.high - best_fit->arange.low))))
+                 || (arange->high - arange->low
+                     < best_fit->arange.high - best_fit->arange.low)))
            best_fit = each_func;
        }
     }
@@ -1990,8 +2005,8 @@ find_abstract_instance_name (struct comp_unit *unit,
       abbrev = lookup_abbrev (abbrev_number, unit->abbrevs);
       if (! abbrev)
        {
-         (*_bfd_error_handler) (_("Dwarf Error: Could not find abbrev number %u."),
-                                abbrev_number);
+         (*_bfd_error_handler)
+           (_("Dwarf Error: Could not find abbrev number %u."), abbrev_number);
          bfd_set_error (bfd_error_bad_value);
        }
       else
@@ -2056,7 +2071,7 @@ read_rangelist (struct comp_unit *unit, struct arange *arange,
        base_address = high_pc;
       else
        {
-         if (!arange_add (unit->abfd, arange,
+         if (!arange_add (unit, arange,
                           base_address + low_pc, base_address + high_pc))
            return FALSE;
        }
@@ -2082,7 +2097,7 @@ scan_unit_for_symbols (struct comp_unit *unit)
      can use to set the caller_func field.  */
   nested_funcs_size = 32;
   nested_funcs = (struct funcinfo **)
-      bfd_malloc (nested_funcs_size * sizeof (struct funcinfo *));
+    bfd_malloc (nested_funcs_size * sizeof (struct funcinfo *));
   if (nested_funcs == NULL)
     return FALSE;
   nested_funcs[nesting_level] = 0;
@@ -2286,7 +2301,7 @@ scan_unit_for_symbols (struct comp_unit *unit)
 
       if (func && high_pc != 0)
        {
-         if (!arange_add (unit->abfd, &func->arange, low_pc, high_pc))
+         if (!arange_add (unit, &func->arange, low_pc, high_pc))
            goto fail;
        }
 
@@ -2300,8 +2315,8 @@ scan_unit_for_symbols (struct comp_unit *unit)
 
              nested_funcs_size *= 2;
              tmp = (struct funcinfo **)
-                 bfd_realloc (nested_funcs,
-                              (nested_funcs_size * sizeof (struct funcinfo *)));
+               bfd_realloc (nested_funcs,
+                            nested_funcs_size * sizeof (struct funcinfo *));
              if (tmp == NULL)
                goto fail;
              nested_funcs = tmp;
@@ -2362,23 +2377,29 @@ parse_comp_unit (struct dwarf2_debug *stash,
 
   if (version != 2 && version != 3 && version != 4)
     {
-      (*_bfd_error_handler) (_("Dwarf Error: found dwarf version '%u', this reader only handles version 2, 3 and 4 information."), version);
+      (*_bfd_error_handler)
+       (_("Dwarf Error: found dwarf version '%u', this reader"
+          " only handles version 2, 3 and 4 information."), version);
       bfd_set_error (bfd_error_bad_value);
       return 0;
     }
 
   if (addr_size > sizeof (bfd_vma))
     {
-      (*_bfd_error_handler) (_("Dwarf Error: found address size '%u', this reader can not handle sizes greater than '%u'."),
-                        addr_size,
-                        (unsigned int) sizeof (bfd_vma));
+      (*_bfd_error_handler)
+       (_("Dwarf Error: found address size '%u', this reader"
+          " can not handle sizes greater than '%u'."),
+        addr_size,
+        (unsigned int) sizeof (bfd_vma));
       bfd_set_error (bfd_error_bad_value);
       return 0;
     }
 
   if (addr_size != 2 && addr_size != 4 && addr_size != 8)
     {
-      (*_bfd_error_handler) ("Dwarf Error: found address size '%u', this reader can only handle address sizes '2', '4' and '8'.", addr_size);
+      (*_bfd_error_handler)
+       ("Dwarf Error: found address size '%u', this reader"
+        " can only handle address sizes '2', '4' and '8'.", addr_size);
       bfd_set_error (bfd_error_bad_value);
       return 0;
     }
@@ -2386,14 +2407,14 @@ parse_comp_unit (struct dwarf2_debug *stash,
   /* Read the abbrevs for this compilation unit into a table.  */
   abbrevs = read_abbrevs (abfd, abbrev_offset, stash);
   if (! abbrevs)
-      return 0;
+    return 0;
 
   abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
   info_ptr += bytes_read;
   if (! abbrev_number)
     {
       (*_bfd_error_handler) (_("Dwarf Error: Bad abbrev number: %u."),
-                        abbrev_number);
+                            abbrev_number);
       bfd_set_error (bfd_error_bad_value);
       return 0;
     }
@@ -2402,7 +2423,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
   if (! abbrev)
     {
       (*_bfd_error_handler) (_("Dwarf Error: Could not find abbrev number %u."),
-                        abbrev_number);
+                            abbrev_number);
       bfd_set_error (bfd_error_bad_value);
       return 0;
     }
@@ -2445,7 +2466,8 @@ parse_comp_unit (struct dwarf2_debug *stash,
          /* If the compilation unit DIE has a DW_AT_low_pc attribute,
             this is the base address to use when reading location
             lists or range lists. */
-         unit->base_address = low_pc;
+         if (abbrev->tag == DW_TAG_compile_unit)
+           unit->base_address = low_pc;
          break;
 
        case DW_AT_high_pc:
@@ -2482,7 +2504,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
     high_pc += low_pc;
   if (high_pc != 0)
     {
-      if (!arange_add (unit->abfd, &unit->arange, low_pc, high_pc))
+      if (!arange_add (unit, &unit->arange, low_pc, high_pc))
        return NULL;
     }
 
@@ -2752,25 +2774,43 @@ static asection *
 find_debug_info (bfd *abfd, const struct dwarf_debug_section *debug_sections,
                  asection *after_sec)
 {
-  asection * msec;
+  asection *msec;
+  const char *look;
+
+  if (after_sec == NULL)
+    {
+      look = debug_sections[debug_info].uncompressed_name;
+      msec = bfd_get_section_by_name (abfd, look);
+      if (msec != NULL)
+       return msec;
 
-  msec = after_sec != NULL ? after_sec->next : abfd->sections;
+      look = debug_sections[debug_info].compressed_name;
+      if (look != NULL)
+       {
+         msec = bfd_get_section_by_name (abfd, look);
+         if (msec != NULL)
+           return msec;
+       }
 
-  while (msec)
+      for (msec = abfd->sections; msec != NULL; msec = msec->next)
+       if (CONST_STRNEQ (msec->name, GNU_LINKONCE_INFO))
+         return msec;
+
+      return NULL;
+    }
+
+  for (msec = after_sec->next; msec != NULL; msec = msec->next)
     {
-      if (strcmp (msec->name,
-                  debug_sections[debug_info].uncompressed_name) == 0)
+      look = debug_sections[debug_info].uncompressed_name;
+      if (strcmp (msec->name, look) == 0)
        return msec;
 
-      if (debug_sections[debug_info].compressed_name != NULL
-          && strcmp (msec->name,
-                     debug_sections[debug_info].compressed_name) == 0)
+      look = debug_sections[debug_info].compressed_name;
+      if (look != NULL && strcmp (msec->name, look) == 0)
        return msec;
 
       if (CONST_STRNEQ (msec->name, GNU_LINKONCE_INFO))
        return msec;
-
-      msec = msec->next;
     }
 
   return NULL;
@@ -2844,7 +2884,7 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash)
        }
 
       amt = i * sizeof (struct adjusted_section);
-      p = (struct adjusted_section *) bfd_zalloc (abfd, amt);
+      p = (struct adjusted_section *) bfd_alloc (abfd, amt);
       if (! p)
        return FALSE;
 
@@ -2938,8 +2978,8 @@ info_hash_lookup_funcinfo (struct info_hash_table *hash_table,
              && addr >= arange->low
              && addr < arange->high
              && (!best_fit
-                 || ((arange->high - arange->low)
-                     < (best_fit->arange.high - best_fit->arange.low))))
+                 || (arange->high - arange->low
+                     < best_fit->arange.high - best_fit->arange.low)))
            best_fit = each_func;
        }
     }
@@ -3359,6 +3399,7 @@ find_line (bfd *abfd,
          /* Check the previously read comp. units first.  */
          for (each = stash->all_comp_units; each; each = each->next_unit)
            if ((symbol->flags & BSF_FUNCTION) == 0
+               || each->arange.high == 0
                || comp_unit_contains_address (each, addr))
              {
                found = comp_unit_find_line (each, symbol, addr, filename_ptr,
@@ -3372,7 +3413,8 @@ find_line (bfd *abfd,
     {
       for (each = stash->all_comp_units; each; each = each->next_unit)
        {
-         found = (comp_unit_contains_address (each, addr)
+         found = ((each->arange.high == 0
+                   || comp_unit_contains_address (each, addr))
                   && comp_unit_find_nearest_line (each, addr,
                                                   filename_ptr,
                                                   functionname_ptr,
@@ -3485,7 +3527,7 @@ find_line (bfd *abfd,
        }
     }
 
-done:
+ done:
   if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
     unset_sections (stash);