* elf32-i386.c (elf_i386_grok_prstatus): New function.
[deliverable/binutils-gdb.git] / bfd / dwarf2.c
index 7c8ddfdb0d4c3af8fefba1d88792fdba9dea11fa..4be6acfe2665cce759e4f32e21338fcbabdd40ff 100644 (file)
@@ -1,5 +1,6 @@
 /* DWARF 2 support.
-   Copyright 1994, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
 
    Adapted from gdb/dwarf2read.c by Gavin Koch of Cygnus Solutions
    (gavin@cygnus.com).
@@ -75,7 +76,7 @@ struct attribute
 #define DW_SND(attr)       ((attr)->u.snd)
 #define DW_ADDR(attr)     ((attr)->u.addr)
 
-/* Blocks are a bunch of untyped bytes. */
+/* Blocks are a bunch of untyped bytes.  */
 struct dwarf_block
 {
   unsigned int size;
@@ -95,6 +96,14 @@ struct dwarf2_debug
   /* Pointer to the end of the .debug_info section memory buffer.  */
   char* info_ptr_end;
 
+  /* Pointer to the section and address of the beginning of the
+     section.  */
+  asection* sec;
+  char* sec_info_ptr;
+
+  /* Pointer to the symbol table.  */
+  asymbol** syms;
+
   /* Pointer to the .debug_abbrev section loaded into memory.  */
   char* dwarf_abbrev_buffer;
 
@@ -144,7 +153,7 @@ struct comp_unit
 
   /* True if there is a line number table associated with this comp. unit.  */
   int stmtlist;
-  
+
   /* The offset into .debug_line of the line number table.  */
   unsigned long line_offset;
 
@@ -158,14 +167,80 @@ struct comp_unit
   struct line_info_table* line_table;
 
   /* A list of the functions found in this comp. unit.  */
-  struct funcinfo* function_table; 
+  struct funcinfo* function_table;
 
   /* Address size for this unit - from unit header.  */
   unsigned char addr_size;
 };
 
-/* VERBATIM 
-   The following function up to the END VERBATIM mark are 
+/* This data structure holds the information of an abbrev.  */
+struct abbrev_info
+{
+  unsigned int number;         /* Number identifying abbrev.  */
+  enum dwarf_tag tag;          /* DWARF tag.  */
+  int has_children;            /* Boolean.  */
+  unsigned int num_attrs;      /* Number of attributes.  */
+  struct attr_abbrev *attrs;   /* An array of attribute descriptions.  */
+  struct abbrev_info *next;    /* Next in chain.  */
+};
+
+struct attr_abbrev
+{
+  enum dwarf_attribute name;
+  enum dwarf_form form;
+};
+
+#ifndef ABBREV_HASH_SIZE
+#define ABBREV_HASH_SIZE 121
+#endif
+#ifndef ATTR_ALLOC_CHUNK
+#define ATTR_ALLOC_CHUNK 4
+#endif
+
+static unsigned int read_1_byte PARAMS ((bfd *, char *));
+static int read_1_signed_byte PARAMS ((bfd *, char *));
+static unsigned int read_2_bytes PARAMS ((bfd *, char *));
+static unsigned int read_4_bytes PARAMS ((bfd *, char *));
+static unsigned int read_8_bytes PARAMS ((bfd *, char *));
+static char *read_n_bytes PARAMS ((bfd *, char *, unsigned int));
+static char *read_string PARAMS ((bfd *, char *, unsigned int *));
+static unsigned int read_unsigned_leb128
+  PARAMS ((bfd *, char *, unsigned int *));
+static int read_signed_leb128
+  PARAMS ((bfd *, char *, unsigned int *));
+static bfd_vma read_address PARAMS ((struct comp_unit *, char *));
+static struct abbrev_info *lookup_abbrev
+  PARAMS ((unsigned int, struct abbrev_info **));
+static struct abbrev_info **read_abbrevs
+  PARAMS ((bfd *, unsigned int, struct dwarf2_debug *));
+static char *read_attribute
+  PARAMS ((struct attribute *, struct attr_abbrev *,
+          struct comp_unit *, char *));
+static void add_line_info
+  PARAMS ((struct line_info_table *, bfd_vma, char *,
+          unsigned int, unsigned int, int));
+static char *concat_filename PARAMS ((struct line_info_table *, unsigned int));
+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 *));
+static boolean lookup_address_in_function_table
+  PARAMS ((struct funcinfo *, bfd_vma, 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**));
+static struct comp_unit *parse_comp_unit
+  PARAMS ((bfd *, struct dwarf2_debug *, bfd_vma, unsigned int));
+static boolean comp_unit_contains_address
+  PARAMS ((struct comp_unit *, bfd_vma));
+static boolean comp_unit_find_nearest_line
+  PARAMS ((struct comp_unit *, bfd_vma, const char **, const char **,
+          unsigned int *, struct dwarf2_debug *));
+static asection *find_debug_info PARAMS ((bfd *, asection *));
+
+/* VERBATIM
+   The following function up to the END VERBATIM mark are
    copied directly from dwarf2read.c.  */
 
 /* Read dwarf information from a buffer.  */
@@ -260,7 +335,7 @@ read_string (abfd, buf, bytes_read_ptr)
       *bytes_read_ptr = 1;
       return NULL;
     }
-  
+
   *bytes_read_ptr = strlen (buf) + 1;
   return buf;
 }
@@ -279,7 +354,7 @@ read_unsigned_leb128 (abfd, buf, bytes_read_ptr)
   result   = 0;
   shift    = 0;
   num_read = 0;
-  
+
   do
     {
       byte = bfd_get_8 (abfd, (bfd_byte *) buf);
@@ -289,9 +364,9 @@ read_unsigned_leb128 (abfd, buf, bytes_read_ptr)
       shift += 7;
     }
   while (byte & 0x80);
-  
+
   * bytes_read_ptr = num_read;
-  
+
   return result;
 }
 
@@ -319,12 +394,12 @@ read_signed_leb128 (abfd, buf, bytes_read_ptr)
       shift += 7;
     }
   while (byte & 0x80);
-  
+
   if ((shift < 32) && (byte & 0x40))
     result |= -(1 << shift);
 
   * bytes_read_ptr = num_read;
-  
+
   return result;
 }
 
@@ -348,30 +423,6 @@ read_address (unit, buf)
     }
 }
 
-/* This data structure holds the information of an abbrev. */
-struct abbrev_info
-{
-  unsigned int number;         /* Number identifying abbrev.  */
-  enum dwarf_tag tag;          /* DWARF tag.  */
-  int has_children;            /* Boolean.  */
-  unsigned int num_attrs;      /* Number of attributes.  */
-  struct attr_abbrev *attrs;   /* An array of attribute descriptions.  */
-  struct abbrev_info *next;    /* Next in chain.  */
-};
-
-struct attr_abbrev
-{
-  enum dwarf_attribute name;
-  enum dwarf_form form;
-};
-
-#ifndef ABBREV_HASH_SIZE
-#define ABBREV_HASH_SIZE 121
-#endif
-#ifndef ATTR_ALLOC_CHUNK
-#define ATTR_ALLOC_CHUNK 4
-#endif
-
 /* Lookup an abbrev_info structure in the abbrev hash table.  */
 
 static struct abbrev_info *
@@ -392,7 +443,7 @@ lookup_abbrev (number,abbrevs)
       else
        abbrev = abbrev->next;
     }
-  
+
   return NULL;
 }
 
@@ -402,18 +453,16 @@ lookup_abbrev (number,abbrevs)
    in a hash table.  */
 
 static struct abbrev_info**
-read_abbrevs (abfd, offset)
+read_abbrevs (abfd, offset, stash)
      bfd * abfd;
      unsigned int offset;
+     struct dwarf2_debug *stash;
 {
   struct abbrev_info **abbrevs;
   char *abbrev_ptr;
   struct abbrev_info *cur_abbrev;
   unsigned int abbrev_number, bytes_read, abbrev_name;
   unsigned int abbrev_form, hash_number;
-  struct dwarf2_debug *stash;
-
-  stash = elf_tdata(abfd)->dwarf2_find_line_info;
 
   if (! stash->dwarf_abbrev_buffer)
     {
@@ -426,27 +475,27 @@ read_abbrevs (abfd, offset)
          bfd_set_error (bfd_error_bad_value);
          return 0;
        }
-      
+
       stash->dwarf_abbrev_size = msec->_raw_size;
       stash->dwarf_abbrev_buffer = (char*) bfd_alloc (abfd, stash->dwarf_abbrev_size);
       if (! stash->dwarf_abbrev_buffer)
          return 0;
-      
-      if (! bfd_get_section_contents (abfd, msec, 
+
+      if (! bfd_get_section_contents (abfd, msec,
                                      stash->dwarf_abbrev_buffer, 0,
                                      stash->dwarf_abbrev_size))
        return 0;
     }
 
-  if (offset > stash->dwarf_abbrev_size)
+  if (offset >= stash->dwarf_abbrev_size)
     {
-      (*_bfd_error_handler) (_("Dwarf Error: Abbrev offset (%u) bigger than abbrev size (%u)."), 
+      (*_bfd_error_handler) (_("Dwarf Error: Abbrev offset (%u) greater than or equal to abbrev size (%u)."),
                             offset, stash->dwarf_abbrev_size );
       bfd_set_error (bfd_error_bad_value);
       return 0;
     }
 
-  abbrevs = (struct abbrev_info**) bfd_zalloc (abfd, sizeof(struct abbrev_info*) * ABBREV_HASH_SIZE);
+  abbrevs = (struct abbrev_info**) bfd_zalloc (abfd, sizeof (struct abbrev_info*) * ABBREV_HASH_SIZE);
 
   abbrev_ptr = stash->dwarf_abbrev_buffer + offset;
   abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
@@ -469,7 +518,7 @@ read_abbrevs (abfd, offset)
       abbrev_ptr += bytes_read;
       abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
       abbrev_ptr += bytes_read;
-      
+
       while (abbrev_name)
        {
          if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0)
@@ -481,7 +530,7 @@ read_abbrevs (abfd, offset)
              if (! cur_abbrev->attrs)
                return 0;
            }
-         
+
          cur_abbrev->attrs[cur_abbrev->num_attrs].name = abbrev_name;
          cur_abbrev->attrs[cur_abbrev->num_attrs++].form = abbrev_form;
          abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
@@ -528,7 +577,7 @@ read_attribute (attr, abbrev, unit, info_ptr)
 
   attr->name = abbrev->name;
   attr->form = abbrev->form;
-  
+
   switch (abbrev->form)
     {
     case DW_FORM_addr:
@@ -664,7 +713,7 @@ struct line_info_table
   struct line_info* last_line;
 };
 
-static void 
+static void
 add_line_info (table, address, filename, line, column, end_sequence)
      struct line_info_table* table;
      bfd_vma address;
@@ -701,7 +750,7 @@ concat_filename (table, file)
     }
 
   filename = table->files[file - 1].name;
-  if (*filename == '/')
+  if (IS_ABSOLUTE_PATH(filename))
     return filename;
 
   else
@@ -723,7 +772,7 @@ arange_add (unit, low_pc, high_pc)
 
   /* First see if we can cheaply extend an existing range.  */
   arange = &unit->arange;
-  
+
   do
     {
       if (low_pc == arange->high)
@@ -761,11 +810,11 @@ arange_add (unit, low_pc, high_pc)
 /* Decode the line number information for UNIT.  */
 
 static struct line_info_table*
-decode_line_info (unit)
+decode_line_info (unit, stash)
      struct comp_unit *unit;
+     struct dwarf2_debug *stash;
 {
   bfd *abfd = unit->abfd;
-  struct dwarf2_debug *stash;
   struct line_info_table* table;
   char *line_ptr;
   char *line_end;
@@ -774,8 +823,6 @@ decode_line_info (unit)
   char *cur_file, *cur_dir;
   unsigned char op_code, extended_op, adj_opcode;
 
-  stash = elf_tdata (abfd)->dwarf2_find_line_info;
-
   if (! stash->dwarf_line_buffer)
     {
       asection *msec;
@@ -787,13 +834,13 @@ decode_line_info (unit)
          bfd_set_error (bfd_error_bad_value);
          return 0;
        }
-      
+
       stash->dwarf_line_size = msec->_raw_size;
       stash->dwarf_line_buffer = (char *) bfd_alloc (abfd, stash->dwarf_line_size);
       if (! stash->dwarf_line_buffer)
        return 0;
 
-      if (! bfd_get_section_contents (abfd, msec, 
+      if (! bfd_get_section_contents (abfd, msec,
                                      stash->dwarf_line_buffer, 0,
                                      stash->dwarf_line_size))
        return 0;
@@ -807,13 +854,13 @@ decode_line_info (unit)
      below.  */
   if (unit->line_offset >= stash->dwarf_line_size)
     {
-      (*_bfd_error_handler) (_("Dwarf Error: Line offset (%u) bigger than line size (%u)."),
+      (*_bfd_error_handler) (_("Dwarf Error: Line offset (%u) greater than or equal to line size (%u)."),
                             unit->line_offset, stash->dwarf_line_size);
       bfd_set_error (bfd_error_bad_value);
       return 0;
     }
 
-  table = (struct line_info_table*) bfd_alloc (abfd, 
+  table = (struct line_info_table*) bfd_alloc (abfd,
                                               sizeof (struct line_info_table));
   table->abfd = abfd;
   table->comp_dir = unit->comp_dir;
@@ -851,7 +898,7 @@ decode_line_info (unit)
     bfd_alloc (abfd, lh.opcode_base * sizeof (unsigned char));
 
   lh.standard_opcode_lengths[0] = 1;
-  
+
   for (i = 1; i < lh.opcode_base; ++i)
     {
       lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
@@ -862,7 +909,7 @@ decode_line_info (unit)
   while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
     {
       line_ptr += bytes_read;
-      
+
       if ((table->num_dirs % DIR_ALLOC_CHUNK) == 0)
        {
          table->dirs = (char **)
@@ -871,17 +918,17 @@ decode_line_info (unit)
          if (! table->dirs)
            return 0;
        }
-      
+
       table->dirs[table->num_dirs++] = cur_dir;
     }
-  
+
   line_ptr += bytes_read;
 
   /* Read file name table.  */
   while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
     {
       line_ptr += bytes_read;
-      
+
       if ((table->num_files % FILE_ALLOC_CHUNK) == 0)
        {
          table->files = (struct fileinfo *)
@@ -891,7 +938,7 @@ decode_line_info (unit)
          if (! table->files)
            return 0;
        }
-      
+
       table->files[table->num_files].name = cur_file;
       table->files[table->num_files].dir =
        read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
@@ -904,7 +951,7 @@ decode_line_info (unit)
       line_ptr += bytes_read;
       table->num_files++;
     }
-  
+
   line_ptr += bytes_read;
 
   /* Read the statement sequences until there's nothing left.  */
@@ -925,7 +972,7 @@ decode_line_info (unit)
        {
          op_code = read_1_byte (abfd, line_ptr);
          line_ptr += 1;
-         
+
          switch (op_code)
            {
            case DW_LNS_extended_op:
@@ -1051,9 +1098,9 @@ decode_line_info (unit)
    LINENUMBER_PTR, are pointers to the objects to be filled in.  */
 
 static boolean
-lookup_address_in_line_info_table (table, 
+lookup_address_in_line_info_table (table,
                                   addr,
-                                  filename_ptr, 
+                                  filename_ptr,
                                   linenumber_ptr)
      struct line_info_table* table;
      bfd_vma addr;
@@ -1062,7 +1109,7 @@ lookup_address_in_line_info_table (table,
 {
   struct line_info* next_line = table->last_line;
   struct line_info* each_line;
-  
+
   if (!next_line)
     return false;
 
@@ -1080,10 +1127,10 @@ lookup_address_in_line_info_table (table,
       next_line = each_line;
       each_line = each_line->prev_line;
     }
-  
+
   return false;
 }
-  
+
 /* Function table functions.  */
 
 struct funcinfo
@@ -1094,10 +1141,10 @@ struct funcinfo
   bfd_vma high;
 };
 
-/* If ADDR is within TABLE, set FUNCTIONNAME_PTR, and return true. */
+/* If ADDR is within TABLE, set FUNCTIONNAME_PTR, and return true.  */
 
 static boolean
-lookup_address_in_function_table (table, 
+lookup_address_in_function_table (table,
                                  addr,
                                  functionname_ptr)
      struct funcinfo* table;
@@ -1116,7 +1163,7 @@ lookup_address_in_function_table (table,
          return true;
        }
     }
-  
+
   return false;
 }
 
@@ -1149,16 +1196,16 @@ scan_unit_for_functions (unit)
          nesting_level--;
          continue;
        }
-      
+
       abbrev = lookup_abbrev (abbrev_number,unit->abbrevs);
       if (! abbrev)
        {
-         (*_bfd_error_handler) (_("Dwarf Error: Could not find abbrev number %d."), 
+         (*_bfd_error_handler) (_("Dwarf Error: Could not find abbrev number %d."),
                             abbrev_number);
          bfd_set_error (bfd_error_bad_value);
          return false;
        }
-      
+
       if (abbrev->tag == DW_TAG_subprogram)
        {
          func = (struct funcinfo*) bfd_zalloc (abfd, sizeof (struct funcinfo));
@@ -1167,24 +1214,24 @@ scan_unit_for_functions (unit)
        }
       else
        func = NULL;
-  
+
       for (i = 0; i < abbrev->num_attrs; ++i)
        {
          info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr);
-         
+
          if (func)
            {
              switch (attr.name)
                {
                case DW_AT_name:
-                 
+
                  name = DW_STRING (&attr);
 
                  /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name.  */
                  if (func->name == NULL)
                    func->name = DW_STRING (&attr);
                  break;
-                 
+
                case DW_AT_MIPS_linkage_name:
                  func->name = DW_STRING (&attr);
                  break;
@@ -1208,7 +1255,7 @@ scan_unit_for_functions (unit)
                case DW_AT_name:
                  name = DW_STRING (&attr);
                  break;
-                 
+
                default:
                  break;
                }
@@ -1222,6 +1269,60 @@ scan_unit_for_functions (unit)
   return true;
 }
 
+/* Look for a RELA relocation to be applied on OFFSET of section SEC,
+   and return the addend if such a relocation is found.  Since this is
+   only used to find relocations referring to the .debug_abbrev
+   section, we make sure the relocation refers to this section, but
+   this is not strictly necessary, and it can probably be safely
+   removed if needed.  However, it is important to note that this
+   function only returns the addend, it doesn't serve the purpose of
+   applying a generic relocation.
+
+   If no suitable relocation is found, or if it is not a real RELA
+   relocation, this function returns 0.  */
+
+static bfd_vma
+find_rela_addend (abfd, sec, offset, syms)
+     bfd* abfd;
+     asection* sec;
+     bfd_size_type offset;
+     asymbol** syms;
+{
+  long reloc_size = bfd_get_reloc_upper_bound (abfd, sec);
+  arelent **relocs = NULL;
+  long reloc_count, relc;
+
+  if (reloc_size <= 0)
+    return 0;
+
+  relocs = (arelent **) bfd_malloc ((size_t) reloc_size);
+  if (relocs == NULL)
+    return 0;
+
+  reloc_count = bfd_canonicalize_reloc (abfd, sec, relocs, syms);
+
+  if (reloc_count <= 0)
+    {
+      free (relocs);
+      return 0;
+    }
+
+  for (relc = 0; relc < reloc_count; relc++)
+    if (relocs[relc]->address == offset
+       && (*relocs[relc]->sym_ptr_ptr)->flags & BSF_SECTION_SYM
+       && strcmp ((*relocs[relc]->sym_ptr_ptr)->name,
+                  ".debug_abbrev") == 0)
+      {
+       bfd_vma addend = (relocs[relc]->howto->partial_inplace
+                         ? 0 : relocs[relc]->addend);
+       free (relocs);
+       return addend;
+      }
+  
+  free (relocs);
+  return 0;
+}
+
 /* Parse a DWARF2 compilation unit starting at INFO_PTR.  This
    includes the compilation unit header that proceeds the DIE's, but
    does not include the length field that preceeds each compilation
@@ -1233,10 +1334,10 @@ scan_unit_for_functions (unit)
    to get to the line number information for the compilation unit.  */
 
 static struct comp_unit *
-parse_comp_unit (abfd, info_ptr, end_ptr, abbrev_length)
+parse_comp_unit (abfd, stash, unit_length, abbrev_length)
      bfd* abfd;
-     char* info_ptr;
-     char* end_ptr;
+     struct dwarf2_debug *stash;
+     bfd_vma unit_length;
      unsigned int abbrev_length;
 {
   struct comp_unit* unit;
@@ -1250,6 +1351,9 @@ parse_comp_unit (abfd, info_ptr, end_ptr, abbrev_length)
   struct abbrev_info *abbrev;
   struct attribute attr;
 
+  char *info_ptr = stash->info_ptr;
+  char *end_ptr = info_ptr + unit_length;
+
   version = read_2_bytes (abfd, info_ptr);
   info_ptr += 2;
   BFD_ASSERT (abbrev_length == 0
@@ -1259,6 +1363,13 @@ parse_comp_unit (abfd, info_ptr, end_ptr, abbrev_length)
     abbrev_offset = read_4_bytes (abfd, info_ptr);
   else if (abbrev_length == 8)
     abbrev_offset = read_8_bytes (abfd, info_ptr);
+  /* The abbrev offset is generally a relocation pointing to
+     .debug_abbrev+offset.  On RELA targets, we have to find the
+     relocation and extract the addend to obtain the actual
+     abbrev_offset, so do it here.  */
+  abbrev_offset += find_rela_addend (abfd, stash->sec,
+                                    info_ptr - stash->sec_info_ptr,
+                                    stash->syms);
   info_ptr += abbrev_length;
   addr_size = read_1_byte (abfd, info_ptr);
   info_ptr += 1;
@@ -1287,7 +1398,7 @@ parse_comp_unit (abfd, info_ptr, end_ptr, abbrev_length)
     }
 
   /* Read the abbrevs for this compilation unit into a table.  */
-  abbrevs = read_abbrevs (abfd, abbrev_offset);
+  abbrevs = read_abbrevs (abfd, abbrev_offset, stash);
   if (! abbrevs)
       return 0;
 
@@ -1309,10 +1420,10 @@ parse_comp_unit (abfd, info_ptr, end_ptr, abbrev_length)
       bfd_set_error (bfd_error_bad_value);
       return 0;
     }
-  
+
   unit = (struct comp_unit*) bfd_zalloc (abfd, sizeof (struct comp_unit));
   unit->abfd = abfd;
-  unit->addr_size = addr_size; 
+  unit->addr_size = addr_size;
   unit->abbrevs = abbrevs;
   unit->end_ptr = end_ptr;
 
@@ -1386,30 +1497,32 @@ comp_unit_contains_address (unit, addr)
       arange = arange->next;
     }
   while (arange);
-  
+
   return 0;
 }
 
 /* If UNIT contains ADDR, set the output parameters to the values for
    the line containing ADDR.  The output parameters, FILENAME_PTR,
    FUNCTIONNAME_PTR, and LINENUMBER_PTR, are pointers to the objects
-   to be filled in.  
+   to be filled in.
 
    Return true of UNIT contains ADDR, and no errors were encountered;
    false otherwise.  */
 
 static boolean
 comp_unit_find_nearest_line (unit, addr,
-                            filename_ptr, functionname_ptr, linenumber_ptr)
+                            filename_ptr, functionname_ptr, linenumber_ptr,
+                            stash)
      struct comp_unit* unit;
      bfd_vma addr;
      const char **filename_ptr;
      const char **functionname_ptr;
      unsigned int *linenumber_ptr;
+     struct dwarf2_debug *stash;
 {
   boolean line_p;
   boolean func_p;
-  
+
   if (unit->error)
     return false;
 
@@ -1420,15 +1533,15 @@ comp_unit_find_nearest_line (unit, addr,
          unit->error = 1;
          return false;
        }
-  
-      unit->line_table = decode_line_info (unit);
+
+      unit->line_table = decode_line_info (unit, stash);
 
       if (! unit->line_table)
        {
          unit->error = 1;
          return false;
        }
-      
+
       if (! scan_unit_for_functions (unit))
        {
          unit->error = 1;
@@ -1438,9 +1551,9 @@ comp_unit_find_nearest_line (unit, addr,
 
   line_p = lookup_address_in_line_info_table (unit->line_table,
                                              addr,
-                                             filename_ptr, 
+                                             filename_ptr,
                                              linenumber_ptr);
-  func_p = lookup_address_in_function_table (unit->function_table, 
+  func_p = lookup_address_in_function_table (unit->function_table,
                                             addr,
                                             functionname_ptr);
   return line_p || func_p;
@@ -1493,31 +1606,32 @@ boolean
 _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
                               filename_ptr, functionname_ptr,
                               linenumber_ptr,
-                              addr_size)
+                              addr_size, pinfo)
      bfd *abfd;
      asection *section;
-     asymbol **symbols ATTRIBUTE_UNUSED;
+     asymbol **symbols;
      bfd_vma offset;
      const char **filename_ptr;
      const char **functionname_ptr;
      unsigned int *linenumber_ptr;
      unsigned int addr_size;
+     PTR *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.  
+     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 
+     a pointer to the next un-read compilation unit.  Check the
      previously read units before reading more.  */
-  struct dwarf2_debug *stash = elf_tdata (abfd)->dwarf2_find_line_info;
+  struct dwarf2_debug *stash = (struct dwarf2_debug *) *pinfo;
 
   /* What address are we looking for?  */
   bfd_vma addr = offset + section->vma;
 
   struct comp_unit* each;
-  
+
   *filename_ptr = NULL;
   *functionname_ptr = NULL;
   *linenumber_ptr = 0;
@@ -1528,23 +1642,25 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
   if (addr_size == 0)
     addr_size = 4;
   BFD_ASSERT (addr_size == 4 || addr_size == 8);
-    
+
   if (! stash)
     {
       unsigned long total_size;
       asection *msec;
 
-      stash = elf_tdata (abfd)->dwarf2_find_line_info =
+      stash =
        (struct dwarf2_debug*) bfd_zalloc (abfd, sizeof (struct dwarf2_debug));
       if (! stash)
        return false;
 
+      *pinfo = (PTR) 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;
+        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
@@ -1553,7 +1669,7 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
         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->_raw_size;
-      
+
       stash->info_ptr = (char *) bfd_alloc (abfd, total_size);
       if (stash->info_ptr == NULL)
        return false;
@@ -1579,7 +1695,11 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
          stash->info_ptr_end = stash->info_ptr + start + size;
        }
 
-      BFD_ASSERT (stash->info_ptr_end = stash->info_ptr + total_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;
     }
 
   /* FIXME: There is a problem with the contents of the
@@ -1590,14 +1710,14 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
      relocs.  There is a similar problem when the .debug_line
      section is processed as well (e.g., there may be relocs
      against the operand of the DW_LNE_set_address operator).
-     
+
      Unfortunately getting hold of the reloc information is hard...
-     
+
      For now, this means that disassembling object files (as
      opposed to fully executables) does not always work as well as
      we would like.  */
-  
-  /* A null info_ptr indicates that there is no dwarf2 info 
+
+  /* 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;
@@ -1605,8 +1725,9 @@ _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 (comp_unit_contains_address (each, addr))
-      return comp_unit_find_nearest_line (each, addr, filename_ptr, 
-                                         functionname_ptr, linenumber_ptr);
+      return comp_unit_find_nearest_line (each, addr, filename_ptr,
+                                         functionname_ptr, linenumber_ptr,
+                                         stash);
 
   /* Read each remaining comp. units checking each as they are read.  */
   while (stash->info_ptr < stash->info_ptr_end)
@@ -1623,11 +1744,16 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
 
       if (length > 0)
         {
-         each = parse_comp_unit (abfd, stash->info_ptr, 
-                                 stash->info_ptr + length,
-                                 addr_size);
+         each = parse_comp_unit (abfd, stash, length, addr_size);
          stash->info_ptr += length;
 
+         if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr)
+             == stash->sec->_raw_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;
@@ -1644,14 +1770,16 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
                    return comp_unit_find_nearest_line (each, addr,
                                                       filename_ptr,
                                                       functionname_ptr,
-                                                      linenumber_ptr);
+                                                      linenumber_ptr,
+                                                      stash);
                }
              else
                {
                  found = comp_unit_find_nearest_line (each, addr,
                                                       filename_ptr,
                                                       functionname_ptr,
-                                                      linenumber_ptr);
+                                                      linenumber_ptr,
+                                                      stash);
                  if (found)
                    return true;
                }
This page took 0.033952 seconds and 4 git commands to generate.