bfd/
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 6 Jun 2005 14:28:31 +0000 (14:28 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 6 Jun 2005 14:28:31 +0000 (14:28 +0000)
2005-06-06  H.J. Lu  <hongjiu.lu@intel.com>

PR 990
* bfd.c (bfd_find_line): New.

* dwarf2.c (comp_unit): Add variable_table.
(funcinfo): Add file, line, and sec.
(varinfo): New.
(lookup_symbol_in_function_table): New.
(lookup_symbol_in_variable_table): New.
(scan_unit_for_functions): Renamed to ...
(scan_unit_for_symbols): This. Handle DW_TAG_entry_point and
DW_TAG_variable.
(comp_unit_find_nearest_line): Updated.
(comp_unit_find_line): New.
(_bfd_dwarf2_find_line): New.

* elf-bfd.h (_bfd_elf_find_line): New.
(_bfd_generic_find_line): New. Defined.

* elf.c (_bfd_elf_find_line): New.

* libbfd-in.h (_bfd_dwarf2_find_line): New.
(_bfd_generic_find_line): New.

* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.

* libbfd.c (_bfd_generic_find_line): New.

* targets.c (BFD_JUMP_TABLE_SYMBOLS): Initialize _bfd_find_line
with _bfd_generic_find_line.
(bfd_target): Add _bfd_find_line.

binutils/

2005-06-06  H.J. Lu  <hongjiu.lu@intel.com>

PR 990
* nm.c (print_symbol): Call bfd_find_line before
bfd_find_nearest_line.

12 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/bfd.c
bfd/dwarf2.c
bfd/elf-bfd.h
bfd/elf.c
bfd/libbfd-in.h
bfd/libbfd.c
bfd/libbfd.h
bfd/targets.c
binutils/ChangeLog
binutils/nm.c

index 2aef89f0b7bca0464cddddf1187c4c556a93f677..39626c1a108754d773c585f980f9d6f9c0324516 100644 (file)
@@ -1,3 +1,37 @@
+2005-06-06  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR 990
+       * bfd.c (bfd_find_line): New.
+
+       * dwarf2.c (comp_unit): Add variable_table.
+       (funcinfo): Add file, line, and sec.
+       (varinfo): New.
+       (lookup_symbol_in_function_table): New.
+       (lookup_symbol_in_variable_table): New.
+       (scan_unit_for_functions): Renamed to ...
+       (scan_unit_for_symbols): This. Handle DW_TAG_entry_point and
+       DW_TAG_variable.
+       (comp_unit_find_nearest_line): Updated.
+       (comp_unit_find_line): New.
+       (_bfd_dwarf2_find_line): New.
+
+       * elf-bfd.h (_bfd_elf_find_line): New.
+       (_bfd_generic_find_line): New. Defined.
+
+       * elf.c (_bfd_elf_find_line): New.
+
+       * libbfd-in.h (_bfd_dwarf2_find_line): New.
+       (_bfd_generic_find_line): New.
+
+       * bfd-in2.h: Regenerated.
+       * libbfd.h: Likewise.
+
+       * libbfd.c (_bfd_generic_find_line): New.
+
+       * targets.c (BFD_JUMP_TABLE_SYMBOLS): Initialize _bfd_find_line
+       with _bfd_generic_find_line.
+       (bfd_target): Add _bfd_find_line.
+
 2005-06-06  H.J. Lu  <hongjiu.lu@intel.com>
 
        * dwarf2.c (decode_line_info): Properly set low_pc.
index f4b82b8bb228ba769dd36de38314d6ff57c4a33b..93d86688cca89727f1523ef0edb62ec5edf1bf9a 100644 (file)
@@ -4307,6 +4307,10 @@ bfd_boolean bfd_set_private_flags (bfd *abfd, flagword flags);
        BFD_SEND (abfd, _bfd_find_nearest_line, \
                  (abfd, sec, syms, off, file, func, line))
 
+#define bfd_find_line(abfd, syms, sym, file, line) \
+       BFD_SEND (abfd, _bfd_find_line, \
+                 (abfd, syms, sym, file, line))
+
 #define bfd_find_inliner_info(abfd, file, func, line) \
        BFD_SEND (abfd, _bfd_find_inliner_info, \
                  (abfd, file, func, line))
@@ -4647,6 +4651,7 @@ typedef struct bfd_target
   NAME##_bfd_is_target_special_symbol, \
   NAME##_get_lineno, \
   NAME##_find_nearest_line, \
+  _bfd_generic_find_line, \
   NAME##_find_inliner_info, \
   NAME##_bfd_make_debug_symbol, \
   NAME##_read_minisymbols, \
@@ -4669,6 +4674,9 @@ typedef struct bfd_target
   bfd_boolean (*_bfd_find_nearest_line)
     (bfd *, struct bfd_section *, struct bfd_symbol **, bfd_vma,
      const char **, const char **, unsigned int *);
+  bfd_boolean (*_bfd_find_line)
+    (bfd *, struct bfd_symbol **, struct bfd_symbol *,
+     const char **, unsigned int *);
   bfd_boolean (*_bfd_find_inliner_info)
     (bfd *, const char **, const char **, unsigned int *);
  /* Back-door to allow format-aware applications to create debug symbols
index f62411b7f27ff12c962d2b5bdde238da37306311..908d79471f68f311ea99baaed73d0a513934c8b7 100644 (file)
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -1161,6 +1161,10 @@ DESCRIPTION
 .       BFD_SEND (abfd, _bfd_find_nearest_line, \
 .                 (abfd, sec, syms, off, file, func, line))
 .
+.#define bfd_find_line(abfd, syms, sym, file, line) \
+.       BFD_SEND (abfd, _bfd_find_line, \
+.                 (abfd, syms, sym, file, line))
+.
 .#define bfd_find_inliner_info(abfd, file, func, line) \
 .       BFD_SEND (abfd, _bfd_find_inliner_info, \
 .                 (abfd, file, func, line))
index 1b08f283916e6a3fabbc8a6e372db0996608cf2b..410a51e84b00a5b2867074b89428408c0e69ac0c 100644 (file)
@@ -182,6 +182,9 @@ struct comp_unit
   /* A list of the functions found in this comp. unit.  */
   struct funcinfo *function_table;
 
+  /* A list of the variables found in this comp. unit.  */
+  struct varinfo *variable_table;
+
   /* Pointer to dwarf2_debug structure.  */
   struct dwarf2_debug *stash;
 
@@ -697,10 +700,29 @@ struct funcinfo
   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 */
   int tag;
   int nesting_level;
   char *name;
   struct arange arange;
+  asection *sec;                       /* Where the symbol is defined */
+};
+
+struct varinfo
+{
+  /* Pointer to previous variable in list of all variables */
+  struct varinfo *prev_var;
+  /* Source location file name */
+  char *file;
+  /* Source location line number */
+  int line;
+  int tag;
+  char *name;
+  /* Where the symbol is defined */
+  asection *sec;
+  /* Is this a stack variable? */
+  unsigned int stack: 1;
 };
 
 /* Adds a new entry to the line_info list in the line_info_table, ensuring
@@ -1424,6 +1446,84 @@ lookup_address_in_function_table (struct comp_unit *unit,
     }
 }
 
+/* If SYM at ADDR is within function table of UNIT, set FILENAME_PTR
+   and LINENUMBER_PTR, and return TRUE.  */
+
+static bfd_boolean
+lookup_symbol_in_function_table (struct comp_unit *unit,
+                                asymbol *sym,
+                                bfd_vma addr,
+                                const char **filename_ptr,
+                                unsigned int *linenumber_ptr)
+{
+  struct funcinfo* each_func;
+  struct funcinfo* best_fit = NULL;
+  struct arange *arange;
+  const char *name = bfd_asymbol_name (sym);
+  asection *sec = bfd_get_section (sym);
+
+  for (each_func = unit->function_table;
+       each_func;
+       each_func = each_func->prev_func)
+    {
+      for (arange = &each_func->arange;
+          arange;
+          arange = arange->next)
+       {
+         if ((!each_func->sec || each_func->sec == sec)
+             && addr >= arange->low
+             && addr < arange->high
+             && strcmp (name, each_func->name) == 0
+             && (!best_fit
+                 || ((arange->high - arange->low)
+                     < (best_fit->arange.high - best_fit->arange.low))))
+           best_fit = each_func;
+       }
+    }
+
+  if (best_fit)
+    {
+      best_fit->sec = sec;
+      *filename_ptr = best_fit->file;
+      *linenumber_ptr = best_fit->line;
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/* Variable table functions.  */
+
+/* If SYM is within variable table of UNIT, set FILENAME_PTR and
+   LINENUMBER_PTR, and return TRUE.  */
+
+static bfd_boolean
+lookup_symbol_in_variable_table (struct comp_unit *unit,
+                                asymbol *sym,
+                                const char **filename_ptr,
+                                unsigned int *linenumber_ptr)
+{
+  const char *name = bfd_asymbol_name (sym);
+  asection *sec = bfd_get_section (sym);
+  struct varinfo* each;
+
+  for (each = unit->variable_table; each; each = each->prev_var)
+    if (each->stack == 0
+       && (!each->sec || each->sec == sec)
+       && strcmp (name, each->name) == 0)
+      break;
+
+  if (each)
+    {
+      each->sec = sec;
+      *filename_ptr = each->file;
+      *linenumber_ptr = each->line;
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
 static char *
 find_abstract_instance_name (struct comp_unit *unit, bfd_uint64_t die_ref)
 {
@@ -1513,10 +1613,10 @@ read_rangelist (struct comp_unit *unit, struct arange *arange, bfd_uint64_t offs
 /* DWARF2 Compilation unit functions.  */
 
 /* Scan over each die in a comp. unit looking for functions to add
-   to the function table.  */
+   to the function table and variables to the variable table.  */
 
 static bfd_boolean
-scan_unit_for_functions (struct comp_unit *unit)
+scan_unit_for_symbols (struct comp_unit *unit)
 {
   bfd *abfd = unit->abfd;
   bfd_byte *info_ptr = unit->first_child_die_ptr;
@@ -1528,6 +1628,7 @@ scan_unit_for_functions (struct comp_unit *unit)
       struct abbrev_info *abbrev;
       struct attribute attr;
       struct funcinfo *func;
+      struct varinfo *var;
       bfd_vma low_pc = 0;
       bfd_vma high_pc = 0;
 
@@ -1549,7 +1650,9 @@ scan_unit_for_functions (struct comp_unit *unit)
          return FALSE;
        }
 
+      var = NULL;
       if (abbrev->tag == DW_TAG_subprogram
+         || abbrev->tag == DW_TAG_entry_point
          || abbrev->tag == DW_TAG_inlined_subroutine)
        {
          bfd_size_type amt = sizeof (struct funcinfo);
@@ -1560,7 +1663,18 @@ scan_unit_for_functions (struct comp_unit *unit)
          unit->function_table = func;
        }
       else
-       func = NULL;
+       {
+         func = NULL;
+         if (abbrev->tag == DW_TAG_variable)
+           {
+             bfd_size_type amt = sizeof (struct varinfo);
+             var = bfd_zalloc (abfd, amt);
+             var->tag = abbrev->tag;
+             var->stack = 1;
+             var->prev_var = unit->variable_table;
+             unit->variable_table = var;
+           }
+       }
 
       for (i = 0; i < abbrev->num_attrs; ++i)
        {
@@ -1604,6 +1718,60 @@ scan_unit_for_functions (struct comp_unit *unit)
                  read_rangelist (unit, &func->arange, attr.u.val);
                  break;
 
+               case DW_AT_decl_file:
+                 func->file = concat_filename (unit->line_table,
+                                               attr.u.val);
+                 break;
+
+               case DW_AT_decl_line:
+                 func->line = attr.u.val;
+                 break;
+
+               default:
+                 break;
+               }
+           }
+         else if (var)
+           {
+             switch (attr.name)
+               {
+               case DW_AT_name:
+                 var->name = attr.u.str;
+                 break;
+
+               case DW_AT_decl_file:
+                 var->file = concat_filename (unit->line_table,
+                                              attr.u.val);
+                 break;
+
+               case DW_AT_decl_line:
+                 var->line = attr.u.val;
+                 break;
+
+               case DW_AT_external:
+                 if (attr.u.val != 0)
+                   var->stack = 0;
+                 break;
+
+               case DW_AT_location:
+                 if (var->stack)
+                   {
+                     switch (attr.form)
+                       {
+                       case DW_FORM_block:
+                       case DW_FORM_block1:
+                       case DW_FORM_block2:
+                       case DW_FORM_block4:
+                         if (*attr.u.blk->data == DW_OP_addr)
+                           var->stack = 0;
+                         break;
+
+                       default:
+                         break;
+                       }
+                   }
+                 break;
+
                default:
                  break;
                }
@@ -1844,7 +2012,7 @@ comp_unit_find_nearest_line (struct comp_unit *unit,
        }
 
       if (unit->first_child_die_ptr < unit->end_ptr
-         && ! scan_unit_for_functions (unit))
+         && ! scan_unit_for_symbols (unit))
        {
          unit->error = 1;
          return FALSE;
@@ -1862,6 +2030,58 @@ comp_unit_find_nearest_line (struct comp_unit *unit,
   return line_p || func_p;
 }
 
+/* If UNIT contains SYM at ADDR, set the output parameters to the
+   values for the line containing SYM.  The output parameters,
+   FILENAME_PTR, and LINENUMBER_PTR, are pointers to the objects to be
+   filled in.
+
+   Return TRUE if UNIT contains SYM, and no errors were encountered;
+   FALSE otherwise.  */
+
+static bfd_boolean
+comp_unit_find_line (struct comp_unit *unit,
+                    asymbol *sym,
+                    bfd_vma addr,
+                    const char **filename_ptr,
+                    unsigned int *linenumber_ptr,
+                    struct dwarf2_debug *stash)
+{
+  if (unit->error)
+    return FALSE;
+
+  if (! unit->line_table)
+    {
+      if (! unit->stmtlist)
+       {
+         unit->error = 1;
+         return FALSE;
+       }
+
+      unit->line_table = decode_line_info (unit, stash);
+
+      if (! unit->line_table)
+       {
+         unit->error = 1;
+         return FALSE;
+       }
+
+      if (unit->first_child_die_ptr < unit->end_ptr
+         && ! scan_unit_for_symbols (unit))
+       {
+         unit->error = 1;
+         return FALSE;
+       }
+    }
+
+  if (sym->flags & BSF_FUNCTION)
+    return lookup_symbol_in_function_table (unit, sym, addr,
+                                           filename_ptr,
+                                           linenumber_ptr);
+  else
+    return lookup_symbol_in_variable_table (unit, sym, filename_ptr,
+                                           linenumber_ptr);
+}
+
 /* Locate a section in a BFD containing debugging info.  The search starts
    from the section after AFTER_SEC, or from the first section in the BFD if
    AFTER_SEC is NULL.  The search works by examining the names of the
@@ -2107,6 +2327,210 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
   return FALSE;
 }
 
+/* The DWARF2 version of find_line.  Return TRUE if the line is found
+   without error.  */
+
+bfd_boolean
+_bfd_dwarf2_find_line (bfd *abfd,
+                      asymbol **symbols,
+                      asymbol *symbol,
+                      const char **filename_ptr,
+                      unsigned int *linenumber_ptr,
+                      unsigned int addr_size,
+                      void **pinfo)
+{
+  /* Read each compilation unit from the section .debug_info, and check
+     to see if it contains the address we are searching for.  If yes,
+     lookup the address, and return the line number info.  If no, go
+     on to the next compilation unit.
+
+     We keep a list of all the previously read compilation units, and
+     a pointer to the next un-read compilation unit.  Check the
+     previously read units before reading more.  */
+  struct dwarf2_debug *stash;
+
+  /* What address are we looking for?  */
+  bfd_vma addr;
+
+  struct comp_unit* each;
+
+  asection *section;
+
+  bfd_boolean found;
+
+  section = bfd_get_section (symbol);
+
+  addr = symbol->value;
+  if (section->output_section)
+    addr += section->output_section->vma + section->output_offset;
+  else
+    addr += section->vma;
+
+  *filename_ptr = NULL;
+  stash = *pinfo;
+  *filename_ptr = NULL;
+  *linenumber_ptr = 0;
+
+  if (! stash)
+    {
+      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;
+
+      msec = find_debug_info (abfd, NULL);
+      if (! msec)
+       /* 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;
+
+      /* 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
+        passes - in the first pass we just accumulate the section sizes.
+        In the second pass we read in the section's contents.  The allows
+        us to avoid reallocing the data as we add sections to the stash.  */
+      for (total_size = 0; msec; msec = find_debug_info (abfd, msec))
+       total_size += msec->size;
+
+      stash->info_ptr = bfd_alloc (abfd, total_size);
+      if (stash->info_ptr == NULL)
+       return FALSE;
+
+      stash->info_ptr_end = stash->info_ptr;
+
+      for (msec = find_debug_info (abfd, NULL);
+          msec;
+          msec = find_debug_info (abfd, msec))
+       {
+         bfd_size_type size;
+         bfd_size_type start;
+
+         size = msec->size;
+         if (size == 0)
+           continue;
+
+         start = stash->info_ptr_end - stash->info_ptr;
+
+         if ((bfd_simple_get_relocated_section_contents
+              (abfd, msec, stash->info_ptr + start, symbols)) == NULL)
+           continue;
+
+         stash->info_ptr_end = stash->info_ptr + start + size;
+       }
+
+      BFD_ASSERT (stash->info_ptr_end == stash->info_ptr + total_size);
+
+      stash->sec = find_debug_info (abfd, NULL);
+      stash->sec_info_ptr = stash->info_ptr;
+      stash->syms = symbols;
+    }
+
+  /* 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;
+
+  stash->inliner_chain = NULL;
+
+  /* Check the previously read comp. units first.  */
+  for (each = stash->all_comp_units; each; each = each->next_unit)
+    if ((symbol->flags & BSF_FUNCTION) == 0
+       || comp_unit_contains_address (each, addr))
+      {
+       found = comp_unit_find_line (each, symbol, addr, filename_ptr,
+                                    linenumber_ptr, stash);
+       if (found)
+         return found;
+      }
+
+  /* The DWARF2 spec says that the initial length field, and the
+     offset of the abbreviation table, should both be 4-byte values.
+     However, some compilers do things differently.  */
+  if (addr_size == 0)
+    addr_size = 4;
+  BFD_ASSERT (addr_size == 4 || addr_size == 8);
+
+  /* Read each remaining comp. units checking each as they are read.  */
+  while (stash->info_ptr < stash->info_ptr_end)
+    {
+      bfd_vma length;
+      unsigned int offset_size = addr_size;
+      bfd_byte *info_ptr_unit = stash->info_ptr;
+
+      length = read_4_bytes (abfd, stash->info_ptr);
+      /* A 0xffffff length is the DWARF3 way of indicating we use
+        64-bit offsets, instead of 32-bit offsets.  */
+      if (length == 0xffffffff)
+       {
+         offset_size = 8;
+         length = read_8_bytes (abfd, stash->info_ptr + 4);
+         stash->info_ptr += 12;
+       }
+      /* A zero length is the IRIX way of indicating 64-bit offsets,
+        mostly because the 64-bit length will generally fit in 32
+        bits, and the endianness helps.  */
+      else if (length == 0)
+       {
+         offset_size = 8;
+         length = read_4_bytes (abfd, stash->info_ptr + 4);
+         stash->info_ptr += 8;
+       }
+      /* In the absence of the hints above, we assume addr_size-sized
+        offsets, for backward-compatibility with pre-DWARF3 64-bit
+        platforms.  */
+      else if (addr_size == 8)
+       {
+         length = read_8_bytes (abfd, stash->info_ptr);
+         stash->info_ptr += 8;
+       }
+      else
+       stash->info_ptr += 4;
+
+      if (length > 0)
+       {
+         each = parse_comp_unit (abfd, stash, length, info_ptr_unit,
+                                 offset_size);
+         stash->info_ptr += length;
+
+         if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr)
+             == stash->sec->size)
+           {
+             stash->sec = find_debug_info (abfd, stash->sec);
+             stash->sec_info_ptr = stash->info_ptr;
+           }
+
+         if (each)
+           {
+             each->next_unit = stash->all_comp_units;
+             stash->all_comp_units = each;
+
+             /* DW_AT_low_pc and DW_AT_high_pc are optional for
+                compilation units.  If we don't have them (i.e.,
+                unit->high == 0), we need to consult the line info
+                table to see if a compilation unit contains the given
+                address.  */
+             found = (((symbol->flags & BSF_FUNCTION) == 0
+                       || each->arange.high <= 0
+                       || comp_unit_contains_address (each, addr))
+                      && comp_unit_find_line (each, symbol, addr,
+                                              filename_ptr,
+                                              linenumber_ptr,
+                                              stash));
+             if (found)
+               return TRUE;
+           }
+       }
+    }
+
+  return FALSE;
+}
+
 bfd_boolean
 _bfd_dwarf2_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED,
                               const char **filename_ptr,
index 53f2845be9e892acdd833d668385d293b371f6aa..7c758910f42e460962ada4572f45093411755403 100644 (file)
@@ -1488,6 +1488,9 @@ extern bfd_boolean _bfd_elf_set_arch_mach
 extern bfd_boolean _bfd_elf_find_nearest_line
   (bfd *, asection *, asymbol **, bfd_vma, const char **, const char **,
    unsigned int *);
+extern bfd_boolean _bfd_elf_find_line
+  (bfd *, asymbol **, asymbol *, const char **, unsigned int *);
+#define _bfd_generic_find_line _bfd_elf_find_line
 extern bfd_boolean _bfd_elf_find_inliner_info
   (bfd *, const char **, const char **, unsigned int *);
 #define _bfd_elf_read_minisymbols _bfd_generic_read_minisymbols
index 4ff1d256ce1ae49a6a1903b255c82e9a836140e8..189e099fed6b90488cf4ebb5c010ca00fb9ff4c9 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -6672,6 +6672,17 @@ _bfd_elf_find_nearest_line (bfd *abfd,
   return TRUE;
 }
 
+/* Find the line for a symbol.  */
+
+bfd_boolean
+_bfd_elf_find_line (bfd *abfd, asymbol **symbols, asymbol *symbol,
+                   const char **filename_ptr, unsigned int *line_ptr)
+{
+  return _bfd_dwarf2_find_line (abfd, symbols, symbol,
+                               filename_ptr, line_ptr, 0,
+                               &elf_tdata (abfd)->dwarf2_find_line_info);
+}
+
 /* After a call to bfd_find_nearest_line, successive calls to
    bfd_find_inliner_info can be used to get source information about
    each level of function inlining that terminated at the address
index 84236f9d570c17438a3eb067fa0e6e8021b1e6fb..2c690a4bcc3920f0e710df0c9c76ce9c3b1bc636 100644 (file)
@@ -428,6 +428,14 @@ extern bfd_boolean _bfd_dwarf2_find_nearest_line
   (bfd *, asection *, asymbol **, bfd_vma, const char **, const char **,
    unsigned int *, unsigned int, void **);
 
+/* Find the line using DWARF 2 debugging information.  */
+extern bfd_boolean _bfd_dwarf2_find_line
+  (bfd *, asymbol **, asymbol *, const char **,
+   unsigned int *, unsigned int, void **);
+
+bfd_boolean _bfd_generic_find_line
+  (bfd *, asymbol **, asymbol *, const char **, unsigned int *);
+
 /* Find inliner info after calling bfd_find_nearest_line. */
 extern bfd_boolean _bfd_dwarf2_find_inliner_info
   (bfd *, const char **, const char **, unsigned int *, void **);
index c66a570e2fc5eb7333de34041f5f3fc266329bca..92f0089898cc7b5412b9945e8428a7a54ed9fbea 100644 (file)
@@ -918,3 +918,13 @@ read_signed_leb128 (bfd *abfd ATTRIBUTE_UNUSED,
   *bytes_read_ptr = num_read;
   return result;
 }
+
+bfd_boolean
+_bfd_generic_find_line (bfd *abfd ATTRIBUTE_UNUSED,
+                      asymbol **symbols ATTRIBUTE_UNUSED,
+                      asymbol *symbol ATTRIBUTE_UNUSED,
+                      const char **filename_ptr ATTRIBUTE_UNUSED,
+                      unsigned int *linenumber_ptr ATTRIBUTE_UNUSED)
+{
+  return FALSE;
+}
index f2d51efb9e1db376bd202c519e703cba12300586..a318744fc8e593b292d52140991366ff4174428f 100644 (file)
@@ -433,6 +433,14 @@ extern bfd_boolean _bfd_dwarf2_find_nearest_line
   (bfd *, asection *, asymbol **, bfd_vma, const char **, const char **,
    unsigned int *, unsigned int, void **);
 
+/* Find the line using DWARF 2 debugging information.  */
+extern bfd_boolean _bfd_dwarf2_find_line
+  (bfd *, asymbol **, asymbol *, const char **,
+   unsigned int *, unsigned int, void **);
+
+bfd_boolean _bfd_generic_find_line
+  (bfd *, asymbol **, asymbol *, const char **, unsigned int *);
+
 /* Find inliner info after calling bfd_find_nearest_line. */
 extern bfd_boolean _bfd_dwarf2_find_inliner_info
   (bfd *, const char **, const char **, unsigned int *, void **);
index 50b3eeb50033a9ae241f07dd7b52611a4e64b233..3bfde1b02fdd0d0eaedafa75c23dd69aca3817ba 100644 (file)
@@ -349,6 +349,7 @@ BFD_JUMP_TABLE macros.
 .  NAME##_bfd_is_target_special_symbol, \
 .  NAME##_get_lineno, \
 .  NAME##_find_nearest_line, \
+.  _bfd_generic_find_line, \
 .  NAME##_find_inliner_info, \
 .  NAME##_bfd_make_debug_symbol, \
 .  NAME##_read_minisymbols, \
@@ -371,6 +372,9 @@ BFD_JUMP_TABLE macros.
 .  bfd_boolean (*_bfd_find_nearest_line)
 .    (bfd *, struct bfd_section *, struct bfd_symbol **, bfd_vma,
 .     const char **, const char **, unsigned int *);
+.  bfd_boolean (*_bfd_find_line)
+.    (bfd *, struct bfd_symbol **, struct bfd_symbol *,
+.     const char **, unsigned int *);
 .  bfd_boolean (*_bfd_find_inliner_info)
 .    (bfd *, const char **, const char **, unsigned int *);
 . {* Back-door to allow format-aware applications to create debug symbols
index 7b939007ee8ce56148350c65b92d2842173f5a77..8018ed92484381fb402b4b09d2a494df42ff2d45 100644 (file)
@@ -1,3 +1,9 @@
+2005-06-06  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR 990
+       * nm.c (print_symbol): Call bfd_find_line before
+       bfd_find_nearest_line.
+
 2005-06-06  Alan Modra  <amodra@bigpond.net.au>
 
        * NEWS: Mention new powerpc ld support.
index 511e6d34755236bf3a43ddf94ccac966fb96978c..999a6db7105a17ea1dffda80a07ba195342d0385 100644 (file)
@@ -905,9 +905,10 @@ print_symbol (bfd *abfd, asymbol *sym, bfd_vma ssize, bfd *archive_bfd)
        }
       else if (bfd_get_section (sym)->owner == abfd)
        {
-         if (bfd_find_nearest_line (abfd, bfd_get_section (sym), syms,
-                                    sym->value, &filename, &functionname,
-                                    &lineno)
+         if ((bfd_find_line (abfd, syms, sym, &filename, &lineno)
+              || bfd_find_nearest_line (abfd, bfd_get_section (sym),
+                                        syms, sym->value, &filename,
+                                        &functionname, &lineno))
              && filename != NULL
              && lineno != 0)
            printf ("\t%s:%u", filename, lineno);