2002-03-20 Daniel Jacobowitz <drow@mvista.com>
authorDaniel Jacobowitz <drow@false.org>
Wed, 20 Mar 2002 19:15:30 +0000 (19:15 +0000)
committerDaniel Jacobowitz <drow@false.org>
Wed, 20 Mar 2002 19:15:30 +0000 (19:15 +0000)
        * dwarf2.c (struct funcinfo): Move up.
        (lookup_address_in_function_table): New argument function_ptr.
        Set it.
        (lookup_address_in_line_table): New argument function.  If function
        is non-NULL, use it to handle ``addr'' before the first line note of
        the function.
        (comp_unit_find_nearest_line): Update and swap calls to
        lookup_address_in_function_table and lookup_address_in_line_table.
        * syms.c (_bfd_stab_section_find_nearest_line): Use the first
        N_SLINE encountered if we see an N_FUN before any N_SLINE.

bfd/ChangeLog
bfd/dwarf2.c
bfd/syms.c

index 13dc43b..d559557 100644 (file)
@@ -1,3 +1,16 @@
+2002-03-20  Daniel Jacobowitz  <drow@mvista.com>
+
+       * dwarf2.c (struct funcinfo): Move up.
+       (lookup_address_in_function_table): New argument function_ptr.
+       Set it.
+       (lookup_address_in_line_table): New argument function.  If function
+       is non-NULL, use it to handle ``addr'' before the first line note of
+       the function.
+       (comp_unit_find_nearest_line): Update and swap calls to
+       lookup_address_in_function_table and lookup_address_in_line_table.
+       * syms.c (_bfd_stab_section_find_nearest_line): Use the first
+       N_SLINE encountered if we see an N_FUN before any N_SLINE.
+
 2002-03-20  Tom Rix  <trix@redhat.com>
 
        * coff-rs6000.c (_bfd_xcoff_stat_arch_elt): Renamed from 
index 550f005..f129e0b 100644 (file)
@@ -240,9 +240,10 @@ static void arange_add PARAMS ((struct comp_unit *, bfd_vma, bfd_vma));
 static struct line_info_table *decode_line_info
   PARAMS ((struct comp_unit *, struct dwarf2_debug *));
 static boolean lookup_address_in_line_info_table
-  PARAMS ((struct line_info_table *, bfd_vma, const char **, unsigned int *));
+  PARAMS ((struct line_info_table *, bfd_vma, struct funcinfo *,
+          const char **, unsigned int *));
 static boolean lookup_address_in_function_table
-  PARAMS ((struct funcinfo *, bfd_vma, const char **));
+  PARAMS ((struct funcinfo *, bfd_vma, struct funcinfo **, const char **));
 static boolean scan_unit_for_functions PARAMS ((struct comp_unit *));
 static bfd_vma find_rela_addend
   PARAMS ((bfd *, asection *, bfd_size_type, asymbol**));
@@ -808,6 +809,14 @@ struct line_info_table
   struct line_info* last_line;
 };
 
+struct funcinfo
+{
+  struct funcinfo *prev_func;
+  char* name;
+  bfd_vma low;
+  bfd_vma high;
+};
+
 static void
 add_line_info (table, address, filename, line, column, end_sequence)
      struct line_info_table* table;
@@ -1215,10 +1224,12 @@ decode_line_info (unit, stash)
 static boolean
 lookup_address_in_line_info_table (table,
                                   addr,
+                                  function,
                                   filename_ptr,
                                   linenumber_ptr)
      struct line_info_table* table;
      bfd_vma addr;
+     struct funcinfo *function;
      const char **filename_ptr;
      unsigned int *linenumber_ptr;
 {
@@ -1235,35 +1246,53 @@ lookup_address_in_line_info_table (table,
       if (!each_line->end_sequence
          && addr >= each_line->address && addr < next_line->address)
        {
-         *filename_ptr = each_line->filename;
-         *linenumber_ptr = each_line->line;
+         /* If this line appears to span functions, and addr is in the
+            later function, return the first line of that function instead
+            of the last line of the earlier one.  This check is for GCC
+            2.95, which emits the first line number for a function late.  */
+         if (function != NULL
+             && each_line->address < function->low
+             && next_line->address > function->low)
+           {
+             *filename_ptr = next_line->filename;
+             *linenumber_ptr = next_line->line;
+           }
+         else
+           {
+             *filename_ptr = each_line->filename;
+             *linenumber_ptr = each_line->line;
+           }
          return true;
        }
       next_line = each_line;
       each_line = each_line->prev_line;
     }
 
+  /* At this point each_line is NULL but next_line is not.  If we found the
+     containing function in this compilation unit, return the first line we
+     have a number for.  This is also for compatibility with GCC 2.95.  */
+  if (function != NULL)
+    {
+      *filename_ptr = next_line->filename;
+      *linenumber_ptr = next_line->line;
+      return true;
+    }
+
   return false;
 }
 
 /* Function table functions.  */
 
-struct funcinfo
-{
-  struct funcinfo *prev_func;
-  char* name;
-  bfd_vma low;
-  bfd_vma high;
-};
-
 /* If ADDR is within TABLE, set FUNCTIONNAME_PTR, and return true.  */
 
 static boolean
 lookup_address_in_function_table (table,
                                  addr,
+                                 function_ptr,
                                  functionname_ptr)
      struct funcinfo* table;
      bfd_vma addr;
+     struct funcinfo** function_ptr;
      const char **functionname_ptr;
 {
   struct funcinfo* each_func;
@@ -1275,6 +1304,7 @@ lookup_address_in_function_table (table,
       if (addr >= each_func->low && addr < each_func->high)
        {
          *functionname_ptr = each_func->name;
+         *function_ptr = each_func;
          return true;
        }
     }
@@ -1636,6 +1666,7 @@ comp_unit_find_nearest_line (unit, addr,
 {
   boolean line_p;
   boolean func_p;
+  struct funcinfo *function;
 
   if (unit->error)
     return false;
@@ -1664,13 +1695,16 @@ comp_unit_find_nearest_line (unit, addr,
        }
     }
 
+  function = NULL;
+  func_p = lookup_address_in_function_table (unit->function_table,
+                                            addr,
+                                            &function,
+                                            functionname_ptr);
   line_p = lookup_address_in_line_info_table (unit->line_table,
                                              addr,
+                                             function,
                                              filename_ptr,
                                              linenumber_ptr);
-  func_p = lookup_address_in_function_table (unit->function_table,
-                                            addr,
-                                            functionname_ptr);
   return line_p || func_p;
 }
 
index f0ffaa5..4309c0d 100644 (file)
@@ -1238,9 +1238,11 @@ _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, pfound,
 
   for (; stab < (indexentry+1)->stab; stab += STABSIZE)
     {
-      boolean done;
+      boolean done, saw_line, saw_func;
       bfd_vma val;
 
+      saw_line = false;
+      saw_func = false;
       done = false;
 
       switch (stab[TYPEOFF])
@@ -1261,7 +1263,11 @@ _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, pfound,
          /* A line number.  The value is relative to the start of the
              current function.  */
          val = indexentry->val + bfd_get_32 (abfd, stab + VALOFF);
-         if (val <= offset)
+         /* If this line starts before our desired offset, or if it's
+            the first line we've been able to find, use it.  The
+            !saw_line check works around a bug in GCC 2.95.3, which emits
+            the first N_SLINE late.  */
+         if (!saw_line || val <= offset)
            {
              *pline = bfd_get_16 (abfd, stab + DESCOFF);
 
@@ -1274,11 +1280,14 @@ _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, pfound,
            }
          if (val > offset)
            done = true;
+         saw_line = true;
          break;
 
        case N_FUN:
        case N_SO:
-         done = true;
+         if (saw_func || saw_line)
+           done = true;
+         saw_func = true;
          break;
        }