2006-03-05 H.J. Lu <hongjiu.lu@intel.com>
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 6 Mar 2006 01:36:52 +0000 (01:36 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 6 Mar 2006 01:36:52 +0000 (01:36 +0000)
    Alan Modra  <amodra@bigpond.net.au>

PR binutils/2338
* dwarf2.c (loadable_section): New struct.
(dwarf2_debug): Add loadable_section_count and
loadable_sections.
(new_line_sorts_after): New.
(add_line_info): Use new_line_sorts_after to compare line
addresses.
(check_function_name): Removed.
(unset_sections): New.
(place_sections): New.
(_bfd_dwarf2_find_nearest_line): Updated. Call place_sections
and unset_sections on relocatable files.
(_bfd_dwarf2_find_line): Likewise.

bfd/ChangeLog
bfd/dwarf2.c

index e52fdfb..35185fa 100644 (file)
@@ -1,3 +1,20 @@
+2006-03-05  H.J. Lu  <hongjiu.lu@intel.com>
+           Alan Modra  <amodra@bigpond.net.au>
+
+       PR binutils/2338
+       * dwarf2.c (loadable_section): New struct.
+       (dwarf2_debug): Add loadable_section_count and
+       loadable_sections.
+       (new_line_sorts_after): New.
+       (add_line_info): Use new_line_sorts_after to compare line
+       addresses.
+       (check_function_name): Removed.
+       (unset_sections): New.
+       (place_sections): New.
+       (_bfd_dwarf2_find_nearest_line): Updated. Call place_sections
+       and unset_sections on relocatable files.
+       (_bfd_dwarf2_find_line): Likewise.
+
 2006-03-03  Nick Clifton  <nickc@redhat.com>
 
        * cpu-avr.c: Update to ISO-C90 formatting.
index f9cff9b..dc41c42 100644 (file)
@@ -74,6 +74,12 @@ struct dwarf_block
   bfd_byte *data;
 };
 
+struct loadable_section
+{
+  asection *section;
+  bfd_vma adj_vma;
+};
+
 struct dwarf2_debug
 {
   /* A list of all previously read comp_units.  */
@@ -124,6 +130,12 @@ struct dwarf2_debug
      calling chain for subsequent calls to bfd_find_inliner_info to
      use. */
   struct funcinfo *inliner_chain;
+
+  /* Number of loadable sections.  */
+  unsigned int loadable_section_count;
+
+  /* Array of loadable sections.  */
+  struct loadable_section *loadable_sections;
 };
 
 struct arange
@@ -744,6 +756,17 @@ struct varinfo
   unsigned int stack: 1;
 };
 
+/* Return TRUE if NEW_LINE should sort after LINE.  */
+
+static inline bfd_boolean
+new_line_sorts_after (struct line_info *new_line, struct line_info *line)
+{
+  return (new_line->address > line->address
+         || (new_line->address == line->address
+             && new_line->end_sequence < line->end_sequence));
+}
+
+
 /* Adds a new entry to the line_info list in the line_info_table, ensuring
    that the list is sorted.  Note that the line_info list is sorted from
    highest to lowest VMA (with possible duplicates); that is,
@@ -760,6 +783,21 @@ add_line_info (struct line_info_table *table,
   bfd_size_type amt = sizeof (struct line_info);
   struct line_info* info = bfd_alloc (table->abfd, amt);
 
+  /* Set member data of 'info'.  */
+  info->address = address;
+  info->line = line;
+  info->column = column;
+  info->end_sequence = end_sequence;
+
+  if (filename && filename[0])
+    {
+      info->filename = bfd_alloc (table->abfd, strlen (filename) + 1);
+      if (info->filename)
+       strcpy (info->filename, filename);
+    }
+  else
+    info->filename = NULL;
+
   /* Find the correct location for 'info'.  Normally we will receive
      new line_info data 1) in order and 2) with increasing VMAs.
      However some compilers break the rules (cf. decode_line_info) and
@@ -777,7 +815,7 @@ add_line_info (struct line_info_table *table,
 
   while (1)
     if (!table->last_line
-       || address >= table->last_line->address)
+       || new_line_sorts_after (info, table->last_line))
       {
        /* Normal case: add 'info' to the beginning of the list */
        info->prev_line = table->last_line;
@@ -789,7 +827,7 @@ add_line_info (struct line_info_table *table,
        break;
       }
     else if (!table->lcl_head->prev_line
-            && table->lcl_head->address > address)
+            && !new_line_sorts_after (info, table->lcl_head))
       {
        /* Abnormal but easy: lcl_head is 1) at the *end* of the line
           list and 2) the head of 'info'.  */
@@ -798,8 +836,8 @@ add_line_info (struct line_info_table *table,
        break;
       }
     else if (table->lcl_head->prev_line
-            && table->lcl_head->address > address
-            && address >= table->lcl_head->prev_line->address)
+            && !new_line_sorts_after (info, table->lcl_head)
+            && new_line_sorts_after (info, table->lcl_head->prev_line))
       {
        /* Abnormal but easy: lcl_head is 1) in the *middle* of the line
           list and 2) the head of 'info'.  */
@@ -816,7 +854,8 @@ add_line_info (struct line_info_table *table,
 
        while (li1)
          {
-           if (li2->address > address && address >= li1->address)
+           if (!new_line_sorts_after (info, li2)
+               && new_line_sorts_after (info, li1))
              break;
 
            li2 = li1; /* always non-NULL */
@@ -824,21 +863,6 @@ add_line_info (struct line_info_table *table,
          }
        table->lcl_head = li2;
       }
-
-  /* Set member data of 'info'.  */
-  info->address = address;
-  info->line = line;
-  info->column = column;
-  info->end_sequence = end_sequence;
-
-  if (filename && filename[0])
-    {
-      info->filename = bfd_alloc (table->abfd, strlen (filename) + 1);
-      if (info->filename)
-       strcpy (info->filename, filename);
-    }
-  else
-    info->filename = NULL;
 }
 
 /* Extract a fully qualified filename from a line info table.
@@ -2179,28 +2203,91 @@ find_debug_info (bfd *abfd, asection *after_sec)
   return NULL;
 }
 
-/* Return TRUE if there is no mismatch bewteen function FUNC and
-   section SECTION from symbol table SYMBOLS in ABFD.  */
+/* Unset vmas for loadable sections in STASH.  */
+
+static void
+unset_sections (struct dwarf2_debug *stash)
+{
+  unsigned int i;
+  struct loadable_section *p;
+
+  i = stash->loadable_section_count;
+  p = stash->loadable_sections;
+  for (; i > 0; i--, p++)
+    p->section->vma = 0;
+}
+
+/* Set unique vmas for loadable sections in ABFD and save vmas in
+   STASH for unset_sections.  */
 
 static bfd_boolean
-check_function_name (bfd *abfd, asection *section, asymbol **symbols,
-                    const char *func)
+place_sections (bfd *abfd, struct dwarf2_debug *stash)
 {
-  /* Mismatch can only happen when we have 2 functions with the same
-     address. It can only occur in a relocatable file.  */
-  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
-      && func != NULL
-      && section != NULL
-      && symbols != NULL)
+  struct loadable_section *p;
+  unsigned int i;
+
+  if (stash->loadable_section_count != 0)
     {
-      asymbol **p;
+      i = stash->loadable_section_count;
+      p = stash->loadable_sections;
+      for (; i > 0; i--, p++)
+       p->section->vma = p->adj_vma;
+    }
+  else
+    {
+      asection *sect;
+      bfd_vma last_vma = 0;
+      bfd_size_type amt;
+      struct loadable_section *p;
 
-      for (p = symbols; *p != NULL; p++)
+      i = 0;
+      for (sect = abfd->sections; sect != NULL; sect = sect->next)
        {
-         if (((*p)->flags & BSF_FUNCTION) != 0
-             && (*p)->name != NULL
-             && strcmp ((*p)->name, func) == 0)
-           return (*p)->section == section;
+         bfd_size_type sz;
+
+         if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0)
+           continue;
+
+         sz = sect->rawsize ? sect->rawsize : sect->size;
+         if (sz == 0)
+           continue;
+
+         i++;
+       }
+
+      amt = i * sizeof (struct loadable_section);
+      p = (struct loadable_section *) bfd_zalloc (abfd, amt);
+      if (! p)
+       return FALSE;
+
+      stash->loadable_sections = p;
+      stash->loadable_section_count = i;
+
+      for (sect = abfd->sections; sect != NULL; sect = sect->next)
+       {
+         bfd_size_type sz;
+
+         if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0)
+           continue;
+
+         sz = sect->rawsize ? sect->rawsize : sect->size;
+         if (sz == 0)
+           continue;
+
+         p->section = sect;
+         if (last_vma != 0)
+           {
+             /* Align the new address to the current section
+                alignment.  */
+             last_vma = ((last_vma
+                          + ~((bfd_vma) -1 << sect->alignment_power))
+                         & ((bfd_vma) -1 << sect->alignment_power));
+             sect->vma = last_vma;
+           }
+         p->adj_vma = sect->vma;
+         last_vma += sect->vma + sz;
+
+         p++;
        }
     }
 
@@ -2239,7 +2326,27 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
 
   struct comp_unit* each;
 
+  bfd_vma found = FALSE;
+
   stash = *pinfo;
+
+  if (! stash)
+    {
+      bfd_size_type amt = sizeof (struct dwarf2_debug);
+
+      stash = bfd_zalloc (abfd, amt);
+      if (! stash)
+       return FALSE;
+    }
+
+  /* In a relocatable file, 2 functions may have the same address.
+     We change the section vma so that they won't overlap.  */
+  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+    {
+      if (! place_sections (abfd, stash))
+       return FALSE;
+    }
+
   addr = offset;
   if (section->output_section)
     addr += section->output_section->vma + section->output_offset;
@@ -2256,15 +2363,10 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
     addr_size = 4;
   BFD_ASSERT (addr_size == 4 || addr_size == 8);
 
-  if (! stash)
+  if (! *pinfo)
     {
       bfd_size_type total_size;
       asection *msec;
-      bfd_size_type amt = sizeof (struct dwarf2_debug);
-
-      stash = bfd_zalloc (abfd, amt);
-      if (! stash)
-       return FALSE;
 
       *pinfo = stash;
 
@@ -2273,7 +2375,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
        /* No dwarf2 info.  Note that at this point the stash
           has been allocated, but contains zeros, this lets
           future calls to this function fail quicker.  */
-        return FALSE;
+       goto done;
 
       /* There can be more than one DWARF2 info section in a BFD these days.
         Read them all in and produce one large stash.  We do this in two
@@ -2285,7 +2387,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
 
       stash->info_ptr = bfd_alloc (abfd, total_size);
       if (stash->info_ptr == NULL)
-       return FALSE;
+       goto done;
 
       stash->info_ptr_end = stash->info_ptr;
 
@@ -2319,7 +2421,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
   /* A null info_ptr indicates that there is no dwarf2 info
      (or that an error occured while setting up the stash).  */
   if (! stash->info_ptr)
-    return FALSE;
+    goto done;
 
   stash->inliner_chain = NULL;
 
@@ -2328,10 +2430,11 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
     if (comp_unit_contains_address (each, addr)
        && comp_unit_find_nearest_line (each, addr, filename_ptr,
                                        functionname_ptr,
-                                       linenumber_ptr, stash)
-       && check_function_name (abfd, section, symbols,
-                               *functionname_ptr))
-      return TRUE;
+                                       linenumber_ptr, stash))
+      {
+       found = TRUE;
+       goto done;
+      }
 
   /* Read each remaining comp. units checking each as they are read.  */
   while (stash->info_ptr < stash->info_ptr_end)
@@ -2398,15 +2501,20 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
                                                  filename_ptr,
                                                  functionname_ptr,
                                                  linenumber_ptr,
-                                                 stash)
-                 && check_function_name (abfd, section, symbols,
-                                         *functionname_ptr))
-               return TRUE;
+                                                 stash))
+               {
+                 found = TRUE;
+                 goto done;
+               }
            }
        }
     }
 
-  return FALSE;
+done:
+  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+    unset_sections (stash);
+
+  return found;
 }
 
 /* The DWARF2 version of find_line.  Return TRUE if the line is found
@@ -2438,10 +2546,29 @@ _bfd_dwarf2_find_line (bfd *abfd,
 
   asection *section;
 
-  bfd_boolean found;
+  bfd_boolean found = FALSE;
 
   section = bfd_get_section (symbol);
 
+  stash = *pinfo;
+
+  if (! stash)
+    {
+      bfd_size_type amt = sizeof (struct dwarf2_debug);
+
+      stash = bfd_zalloc (abfd, amt);
+      if (! stash)
+       return FALSE;
+    }
+
+  /* In a relocatable file, 2 functions may have the same address.
+     We change the section vma so that they won't overlap.  */
+  if (!stash && (abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+    {
+      if (! place_sections (abfd, stash))
+       return FALSE;
+    }
+
   addr = symbol->value;
   if (section->output_section)
     addr += section->output_section->vma + section->output_offset;
@@ -2449,19 +2576,13 @@ _bfd_dwarf2_find_line (bfd *abfd,
     addr += section->vma;
 
   *filename_ptr = NULL;
-  stash = *pinfo;
   *filename_ptr = NULL;
   *linenumber_ptr = 0;
 
-  if (! stash)
+  if (! *pinfo)
     {
       bfd_size_type total_size;
       asection *msec;
-      bfd_size_type amt = sizeof (struct dwarf2_debug);
-
-      stash = bfd_zalloc (abfd, amt);
-      if (! stash)
-       return FALSE;
 
       *pinfo = stash;
 
@@ -2470,7 +2591,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
        /* No dwarf2 info.  Note that at this point the stash
           has been allocated, but contains zeros, this lets
           future calls to this function fail quicker.  */
-        return FALSE;
+       goto done;
 
       /* There can be more than one DWARF2 info section in a BFD these days.
         Read them all in and produce one large stash.  We do this in two
@@ -2482,7 +2603,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
 
       stash->info_ptr = bfd_alloc (abfd, total_size);
       if (stash->info_ptr == NULL)
-       return FALSE;
+       goto done;
 
       stash->info_ptr_end = stash->info_ptr;
 
@@ -2516,7 +2637,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
   /* A null info_ptr indicates that there is no dwarf2 info
      (or that an error occured while setting up the stash).  */
   if (! stash->info_ptr)
-    return FALSE;
+    goto done;
 
   stash->inliner_chain = NULL;
 
@@ -2528,7 +2649,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
        found = comp_unit_find_line (each, symbol, addr, filename_ptr,
                                     linenumber_ptr, stash);
        if (found)
-         return found;
+         goto done;
       }
 
   /* The DWARF2 spec says that the initial length field, and the
@@ -2605,12 +2726,16 @@ _bfd_dwarf2_find_line (bfd *abfd,
                                               linenumber_ptr,
                                               stash));
              if (found)
-               return TRUE;
+               goto done;
            }
        }
     }
 
-  return FALSE;
+done:
+  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+    unset_sections (stash);
+
+  return found;
 }
 
 bfd_boolean