David Mosberger <davidm@hpl.hp.com>
authorRichard Henderson <rth@redhat.com>
Sat, 26 Jun 1999 16:05:58 +0000 (16:05 +0000)
committerRichard Henderson <rth@redhat.com>
Sat, 26 Jun 1999 16:05:58 +0000 (16:05 +0000)
        * dwarf2.c (struct arange): New type.
        (struct comp_unit): Replace LOW and HIGH by member ARANGE.
        (arange_add): New function.
        (decode_line_info): Keep track of address ranges that a compilation
        unit covers.
        (comp_unit_contains_address): Return true if address is contained
        in _any_ of the address ranges associated with a compilation unit.
        (_bfd_dwarf2_find_nearest_line): Call comp_unit_find_nearest_line
        on the first comp_unit that contains the address.

bfd/ChangeLog
bfd/dwarf2.c

index 405f110734e663a26fbd1b52307d114a40ce6396..4c3f774bb08da2f7afc6abdbdf8f594c0976629a 100644 (file)
@@ -1,3 +1,15 @@
+1999-06-26  David Mosberger  <davidm@hpl.hp.com>
+
+       * dwarf2.c (struct arange): New type.
+       (struct comp_unit): Replace LOW and HIGH by member ARANGE.
+       (arange_add): New function.
+       (decode_line_info): Keep track of address ranges that a compilation
+       unit covers.
+       (comp_unit_contains_address): Return true if address is contained
+       in _any_ of the address ranges associated with a compilation unit.
+       (_bfd_dwarf2_find_nearest_line): Call comp_unit_find_nearest_line
+       on the first comp_unit that contains the address.
+
 1999-06-26  David Mosberger  <davidm@hpl.hp.com>
 
        * dwarf2.c (struct dwarf2_debug): Add member dwarf_line_buffer.
index 57f5482e735f9fb883b9e0838999dc9fe4b4b7c5..e05dac6cf10da664cd411fe23f5af488cd2858b4 100644 (file)
@@ -104,6 +104,11 @@ struct dwarf2_debug {
   char *dwarf_line_buffer;
 };
 
+struct arange {
+  struct arange *next;
+  bfd_vma low;
+  bfd_vma high;
+};
 
 
 /* A minimal decoding of DWARF2 compilation units.  We only decode
@@ -119,8 +124,7 @@ struct comp_unit {
 
   /* The lowest and higest addresses contained in this compilation
      unit as specified in the compilation unit header. */
-  bfd_vma low;
-  bfd_vma high;
+  struct arange arange;
 
   /* The DW_AT_name attribute (for error messages). */
   char* name;
@@ -705,6 +709,50 @@ concat_filename (table, file)
     }
 }
 
+static void
+arange_add (unit, low_pc, high_pc)
+     struct comp_unit *unit;
+     bfd_vma low_pc;
+     bfd_vma high_pc;
+{
+  struct arange *arange;
+
+  /* first see if we can cheaply extend an existing range: */
+  arange = &unit->arange;
+  do
+    {
+      if (low_pc == arange->high)
+       {
+         arange->high = high_pc;
+         return;
+       }
+      if (high_pc == arange->low)
+       {
+         arange->low = low_pc;
+         return;
+       }
+      arange = arange->next;
+    }
+  while (arange);
+
+  if (unit->arange.high == 0)
+    {
+      /* this is the first address range: store it in unit->arange: */
+      unit->arange.next = 0;
+      unit->arange.low = low_pc;
+      unit->arange.high = high_pc;
+      return;
+    }
+
+  /* need to allocate a new arange and insert it into the arange list: */
+  arange = bfd_zalloc (unit->abfd, sizeof (*arange));
+  arange->low = low_pc;
+  arange->high = high_pc;
+
+  arange->next = unit->arange.next;
+  unit->arange.next = arange;
+}
+
 /* Decode the line number information for UNIT. */
 
 static struct line_info_table*
@@ -723,12 +771,6 @@ decode_line_info (unit)
   unsigned int i, bytes_read;
   char *cur_file, *cur_dir;
   unsigned char op_code, extended_op, adj_opcode;
-#if 0
-  /* This optimization unfortunately does not work well on programs
-     that have multiple sections containing text (such as Linux which
-     uses .text, and .text.init, for example.  */
-  bfd_vma hi_pc = 0, lo_pc = ~ (bfd_vma) 0;
-#endif
 
   stash = elf_tdata (abfd)->dwarf2_find_line_info;
 
@@ -747,11 +789,11 @@ decode_line_info (unit)
       
       size = bfd_get_section_size_before_reloc (msec);
       stash->dwarf_line_buffer = (char *) bfd_alloc (abfd, size);
-      if (! dwarf_line_buffer)
+      if (! stash->dwarf_line_buffer)
        return 0;
 
       if (! bfd_get_section_contents (abfd, msec, 
-                                     dwarf_line_buffer, 0,
+                                     stash->dwarf_line_buffer, 0,
                                      size))
        return 0;
 
@@ -856,7 +898,8 @@ decode_line_info (unit)
       unsigned int column = 0;
       int is_stmt = lh.default_is_stmt;
       int basic_block = 0;
-      int end_sequence = 0;
+      int end_sequence = 0, need_low_pc = 1;
+      bfd_vma low_pc = 0;
 
       /* Decode the table. */
       while (! end_sequence)
@@ -873,7 +916,14 @@ decode_line_info (unit)
                {
                case DW_LNE_end_sequence:
                  end_sequence = 1;
-                 add_line_info (table, address, filename, line, column, end_sequence);
+                 add_line_info (table, address, filename, line, column,
+                                end_sequence);
+                 if (need_low_pc)
+                   {
+                     need_low_pc = 0;
+                     low_pc = address;
+                   }
+                 arange_add (unit, low_pc, address);
                  break;
                case DW_LNE_set_address:
                  address = read_address (unit, line_ptr);
@@ -912,6 +962,11 @@ decode_line_info (unit)
            case DW_LNS_copy:
              add_line_info (table, address, filename, line, column, 0);
              basic_block = 0;
+             if (need_low_pc)
+               {
+                 need_low_pc = 0;
+                 low_pc = address;
+               }
              break;
            case DW_LNS_advance_pc:
              address += lh.minimum_instruction_length
@@ -959,25 +1014,14 @@ decode_line_info (unit)
              /* append row to matrix using current values */
              add_line_info (table, address, filename, line, column, 0);
              basic_block = 1;
+             if (need_low_pc)
+               {
+                 need_low_pc = 0;
+                 low_pc = address;
+               }
            }
-#if 0
-         if (unit->high == 0)
-           {
-             if (address > hi_pc)
-               hi_pc = address;
-             if (address < lo_pc)
-               lo_pc = address;
-           }
-#endif
        }
     }
-#if 0
-  if (unit->high == 0 && hi_pc != 0)
-    {
-      unit->high = hi_pc;
-      unit->low = lo_pc;
-    }
-#endif
 
   return table;
 }
@@ -1275,11 +1319,11 @@ parse_comp_unit (abfd, info_ptr, end_ptr)
          break;
 
        case DW_AT_low_pc:
-         unit->low = DW_ADDR (&attr);
+         unit->arange.low = DW_ADDR (&attr);
          break;
 
        case DW_AT_high_pc:
-         unit->high = DW_ADDR (&attr);
+         unit->arange.high = DW_ADDR (&attr);
          break;
 
        case DW_AT_comp_dir:
@@ -1318,8 +1362,20 @@ comp_unit_contains_address (unit, addr)
      struct comp_unit* unit;
      bfd_vma addr;
 {
-  return ! unit->error
-    && (addr >= unit->low && addr <= unit->high);
+  struct arange *arange;
+
+  if (unit->error)
+    return 0;
+
+  arange = &unit->arange;
+  do
+    {
+      if (addr >= arange->low && addr < arange->high)
+       return 1;
+      arange = arange->next;
+    }
+  while (arange);
+  return 0;
 }
 
 
@@ -1410,8 +1466,6 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
 
   struct comp_unit* each;
   
-  boolean found;
-
   *filename_ptr = NULL;
   *functionname_ptr = NULL;
   *linenumber_ptr = 0;
@@ -1478,31 +1532,16 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
   /* Check the previously read comp. units first. */
 
   for (each = stash->all_comp_units; each; each = each->next_unit)
-    {
-      if (each->high > 0)
-       {
-         if (comp_unit_contains_address (each, addr))
-           return comp_unit_find_nearest_line (each, addr,
-                                               filename_ptr, 
-                                               functionname_ptr, 
-                                               linenumber_ptr);
-       }
-      else
-       {
-         found = comp_unit_find_nearest_line (each, addr,
-                                               filename_ptr, 
-                                               functionname_ptr, 
-                                               linenumber_ptr);
-         if (found)
-           return true;
-       }
-    }
+    if (comp_unit_contains_address (each, addr))
+      return comp_unit_find_nearest_line (each, addr, filename_ptr, 
+                                         functionname_ptr, linenumber_ptr);
 
   /* Read each remaining comp. units checking each as they are read. */
   while (stash->info_ptr < stash->info_ptr_end)
     {
       struct comp_unit* each;
       unsigned int length;
+      boolean found;
 
       length = read_4_bytes (abfd, stash->info_ptr);
       stash->info_ptr += 4;
@@ -1523,7 +1562,7 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
                 unit->high == 0), we need to consult the line info
                 table to see if a compilation unit contains the given
                 address. */
-             if (each->high > 0)
+             if (each->arange.high > 0)
                {
                  if (comp_unit_contains_address (each, addr))
                    return comp_unit_find_nearest_line (each, addr,