Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / dwarf1.c
index 5d6c1e359e512e05fce58af9d02a7897167439c0..7ff80f336a7ac409d77d3ca17e04f5bcffd573ab 100644 (file)
@@ -1,6 +1,5 @@
 /* DWARF 1 find nearest line (_bfd_dwarf1_find_nearest_line).
 /* DWARF 1 find nearest line (_bfd_dwarf1_find_nearest_line).
-   Copyright 1998, 1999, 2000, 2001, 2002, 2004, 2005
-   Free Software Foundation, Inc.
+   Copyright (C) 1998-2020 Free Software Foundation, Inc.
 
    Written by Gavin Romig-Koch of Cygnus Solutions (gavin@cygnus.com).
 
 
    Written by Gavin Romig-Koch of Cygnus Solutions (gavin@cygnus.com).
 
@@ -8,7 +7,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or (at
+   the Free Software Foundation; either version 3 of the License, or (at
    your option) any later version.
 
    This program is distributed in the hope that it will be useful, but
    your option) any later version.
 
    This program is distributed in the hope that it will be useful, but
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 
-#include "bfd.h"
 #include "sysdep.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libiberty.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "libiberty.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
@@ -34,24 +34,27 @@ struct dwarf1_debug
   /* The bfd we are working with.  */
   bfd* abfd;
 
   /* The bfd we are working with.  */
   bfd* abfd;
 
+  /* Pointer to the symbol table.  */
+  asymbol** syms;
+
   /* List of already parsed compilation units.  */
   struct dwarf1_unit* lastUnit;
 
   /* The buffer for the .debug section.
      Zero indicates that the .debug section failed to load.  */
   /* List of already parsed compilation units.  */
   struct dwarf1_unit* lastUnit;
 
   /* The buffer for the .debug section.
      Zero indicates that the .debug section failed to load.  */
-  char* debug_section;
+  bfd_byte *debug_section;
 
   /* Pointer to the end of the .debug_info section memory buffer.  */
 
   /* Pointer to the end of the .debug_info section memory buffer.  */
-  char* debug_section_end;
+  bfd_byte *debug_section_end;
 
   /* The buffer for the .line section.  */
 
   /* The buffer for the .line section.  */
-  char* line_section;
+  bfd_byte *line_section;
 
   /* End of that buffer.  */
 
   /* End of that buffer.  */
-  char* line_section_end;
+  bfd_byte *line_section_end;
 
   /* The current or next unread die within the .debug section.  */
 
   /* The current or next unread die within the .debug section.  */
-  char* currentDie;
+  bfd_byte *currentDie;
 };
 
 /* One dwarf1_unit for each parsed compilation unit die.  */
 };
 
 /* One dwarf1_unit for each parsed compilation unit die.  */
@@ -62,7 +65,7 @@ struct dwarf1_unit
   struct dwarf1_unit* prev;
 
   /* Name of the compilation unit.  */
   struct dwarf1_unit* prev;
 
   /* Name of the compilation unit.  */
-  charname;
+  char *name;
 
   /* The highest and lowest address used in the compilation unit.  */
   unsigned long low_pc;
 
   /* The highest and lowest address used in the compilation unit.  */
   unsigned long low_pc;
@@ -75,7 +78,7 @@ struct dwarf1_unit
   unsigned long stmt_list_offset;
 
   /* If non-zero, a pointer to the first child of this unit.  */
   unsigned long stmt_list_offset;
 
   /* If non-zero, a pointer to the first child of this unit.  */
-  char* first_child;
+  bfd_byte *first_child;
 
   /* How many line entries?  */
   unsigned long line_count;
 
   /* How many line entries?  */
   unsigned long line_count;
@@ -137,11 +140,14 @@ struct linenumber
 static struct dwarf1_unit*
 alloc_dwarf1_unit (struct dwarf1_debug* stash)
 {
 static struct dwarf1_unit*
 alloc_dwarf1_unit (struct dwarf1_debug* stash)
 {
-  bfd_size_type amt = sizeof (struct dwarf1_unit);
+  size_t amt = sizeof (struct dwarf1_unit);
 
 
-  struct dwarf1_unit* x = bfd_zalloc (stash->abfd, amt);
-  x->prev = stash->lastUnit;
-  stash->lastUnit = x;
+  struct dwarf1_unit* x = (struct dwarf1_unit *) bfd_zalloc (stash->abfd, amt);
+  if (x)
+    {
+      x->prev = stash->lastUnit;
+      stash->lastUnit = x;
+    }
 
   return x;
 }
 
   return x;
 }
@@ -152,11 +158,14 @@ alloc_dwarf1_unit (struct dwarf1_debug* stash)
 static struct dwarf1_func *
 alloc_dwarf1_func (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
 {
 static struct dwarf1_func *
 alloc_dwarf1_func (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
 {
-  bfd_size_type amt = sizeof (struct dwarf1_func);
+  size_t amt = sizeof (struct dwarf1_func);
 
 
-  struct dwarf1_func* x = bfd_zalloc (stash->abfd, amt);
-  x->prev = aUnit->func_list;
-  aUnit->func_list = x;
+  struct dwarf1_func* x = (struct dwarf1_func *) bfd_zalloc (stash->abfd, amt);
+  if (x)
+    {
+      x->prev = aUnit->func_list;
+      aUnit->func_list = x;
+    }
 
   return x;
 }
 
   return x;
 }
@@ -169,22 +178,25 @@ alloc_dwarf1_func (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
    Return FALSE if the die is invalidly formatted; TRUE otherwise.  */
 
 static bfd_boolean
    Return FALSE if the die is invalidly formatted; TRUE otherwise.  */
 
 static bfd_boolean
-parse_die (bfd *             abfd,
+parse_die (bfd *            abfd,
           struct die_info * aDieInfo,
           struct die_info * aDieInfo,
-          char *            aDiePtr,
-          char *            aDiePtrEnd)
+          bfd_byte *        aDiePtr,
+          bfd_byte *        aDiePtrEnd)
 {
 {
-  char* this_die = aDiePtr;
-  char* xptr = this_die;
+  bfd_byte *this_die = aDiePtr;
+  bfd_byte *xptr = this_die;
 
   memset (aDieInfo, 0, sizeof (* aDieInfo));
 
   /* First comes the length.  */
 
   memset (aDieInfo, 0, sizeof (* aDieInfo));
 
   /* First comes the length.  */
-  aDieInfo->length = bfd_get_32 (abfd, (bfd_byte *) xptr);
+  if (xptr + 4 > aDiePtrEnd)
+    return FALSE;
+  aDieInfo->length = bfd_get_32 (abfd, xptr);
   xptr += 4;
   if (aDieInfo->length == 0
   xptr += 4;
   if (aDieInfo->length == 0
-      || (this_die + aDieInfo->length) >= aDiePtrEnd)
+      || this_die + aDieInfo->length > aDiePtrEnd)
     return FALSE;
     return FALSE;
+  aDiePtrEnd = this_die + aDieInfo->length;
   if (aDieInfo->length < 6)
     {
       /* Just padding bytes.  */
   if (aDieInfo->length < 6)
     {
       /* Just padding bytes.  */
@@ -193,18 +205,21 @@ parse_die (bfd *             abfd,
     }
 
   /* Then the tag.  */
     }
 
   /* Then the tag.  */
-  aDieInfo->tag = bfd_get_16 (abfd, (bfd_byte *) xptr);
+  if (xptr + 2 > aDiePtrEnd)
+    return FALSE;
+  aDieInfo->tag = bfd_get_16 (abfd, xptr);
   xptr += 2;
 
   /* Then the attributes.  */
   xptr += 2;
 
   /* Then the attributes.  */
-  while (xptr < (this_die + aDieInfo->length))
+  while (xptr + 2 <= aDiePtrEnd)
     {
     {
+      unsigned int   block_len;
       unsigned short attr;
 
       /* Parse the attribute based on its form.  This section
       unsigned short attr;
 
       /* Parse the attribute based on its form.  This section
-         must handle all dwarf1 forms, but need only handle the
+        must handle all dwarf1 forms, but need only handle the
         actual attributes that we care about.  */
         actual attributes that we care about.  */
-      attr = bfd_get_16 (abfd, (bfd_byte *) xptr);
+      attr = bfd_get_16 (abfd, xptr);
       xptr += 2;
 
       switch (FORM_FROM_ATTR (attr))
       xptr += 2;
 
       switch (FORM_FROM_ATTR (attr))
@@ -214,12 +229,15 @@ parse_die (bfd *             abfd,
          break;
        case FORM_DATA4:
        case FORM_REF:
          break;
        case FORM_DATA4:
        case FORM_REF:
-         if (attr == AT_sibling)
-           aDieInfo->sibling = bfd_get_32 (abfd, (bfd_byte *) xptr);
-         else if (attr == AT_stmt_list)
+         if (xptr + 4 <= aDiePtrEnd)
            {
            {
-             aDieInfo->stmt_list_offset = bfd_get_32 (abfd, (bfd_byte *) xptr);
-             aDieInfo->has_stmt_list = 1;
+             if (attr == AT_sibling)
+               aDieInfo->sibling = bfd_get_32 (abfd, xptr);
+             else if (attr == AT_stmt_list)
+               {
+                 aDieInfo->stmt_list_offset = bfd_get_32 (abfd, xptr);
+                 aDieInfo->has_stmt_list = 1;
+               }
            }
          xptr += 4;
          break;
            }
          xptr += 4;
          break;
@@ -227,22 +245,41 @@ parse_die (bfd *             abfd,
          xptr += 8;
          break;
        case FORM_ADDR:
          xptr += 8;
          break;
        case FORM_ADDR:
-         if (attr == AT_low_pc)
-           aDieInfo->low_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
-         else if (attr == AT_high_pc)
-           aDieInfo->high_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
+         if (xptr + 4 <= aDiePtrEnd)
+           {
+             if (attr == AT_low_pc)
+               aDieInfo->low_pc = bfd_get_32 (abfd, xptr);
+             else if (attr == AT_high_pc)
+               aDieInfo->high_pc = bfd_get_32 (abfd, xptr);
+           }
          xptr += 4;
          break;
        case FORM_BLOCK2:
          xptr += 4;
          break;
        case FORM_BLOCK2:
-         xptr += 2 + bfd_get_16 (abfd, (bfd_byte *) xptr);
+         if (xptr + 2 <= aDiePtrEnd)
+           {
+             block_len = bfd_get_16 (abfd, xptr);
+             if (xptr + block_len > aDiePtrEnd
+                 || xptr + block_len < xptr)
+               return FALSE;
+             xptr += block_len;
+           }
+         xptr += 2;
          break;
        case FORM_BLOCK4:
          break;
        case FORM_BLOCK4:
-         xptr += 4 + bfd_get_32 (abfd, (bfd_byte *) xptr);
+         if (xptr + 4 <= aDiePtrEnd)
+           {
+             block_len = bfd_get_32 (abfd, xptr);
+             if (xptr + block_len > aDiePtrEnd
+                 || xptr + block_len < xptr)
+               return FALSE;
+             xptr += block_len;
+           }
+         xptr += 4;
          break;
        case FORM_STRING:
          if (attr == AT_name)
          break;
        case FORM_STRING:
          if (attr == AT_name)
-           aDieInfo->name = xptr;
-         xptr += strlen (xptr) + 1;
+           aDieInfo->name = (char *) xptr;
+         xptr += strnlen ((char *) xptr, aDiePtrEnd - xptr) + 1;
          break;
        }
     }
          break;
        }
     }
@@ -257,7 +294,7 @@ parse_die (bfd *             abfd,
 static bfd_boolean
 parse_line_table (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
 {
 static bfd_boolean
 parse_line_table (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
 {
-  char* xptr;
+  bfd_byte *xptr;
 
   /* Load the ".line" section from the bfd if we haven't already.  */
   if (stash->line_section == 0)
 
   /* Load the ".line" section from the bfd if we haven't already.  */
   if (stash->line_section == 0)
@@ -270,26 +307,21 @@ parse_line_table (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
        return FALSE;
 
       size = msec->rawsize ? msec->rawsize : msec->size;
        return FALSE;
 
       size = msec->rawsize ? msec->rawsize : msec->size;
-      stash->line_section = bfd_alloc (stash->abfd, size);
+      stash->line_section
+       = bfd_simple_get_relocated_section_contents
+       (stash->abfd, msec, NULL, stash->syms);
 
       if (! stash->line_section)
        return FALSE;
 
 
       if (! stash->line_section)
        return FALSE;
 
-      if (! bfd_get_section_contents (stash->abfd, msec, stash->line_section,
-                                     0, size))
-       {
-         stash->line_section = 0;
-         return FALSE;
-       }
-
       stash->line_section_end = stash->line_section + size;
     }
 
   xptr = stash->line_section + aUnit->stmt_list_offset;
       stash->line_section_end = stash->line_section + size;
     }
 
   xptr = stash->line_section + aUnit->stmt_list_offset;
-  if (xptr < stash->line_section_end)
+  if (xptr + 8 <= stash->line_section_end)
     {
       unsigned long eachLine;
     {
       unsigned long eachLine;
-      char *tblend;
+      bfd_byte *tblend;
       unsigned long base;
       bfd_size_type amt;
 
       unsigned long base;
       bfd_size_type amt;
 
@@ -307,10 +339,18 @@ parse_line_table (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
 
       /* Allocate an array for the entries.  */
       amt = sizeof (struct linenumber) * aUnit->line_count;
 
       /* Allocate an array for the entries.  */
       amt = sizeof (struct linenumber) * aUnit->line_count;
-      aUnit->linenumber_table = bfd_alloc (stash->abfd, amt);
+      aUnit->linenumber_table = (struct linenumber *) bfd_alloc (stash->abfd,
+                                                                amt);
+      if (!aUnit->linenumber_table)
+       return FALSE;
 
       for (eachLine = 0; eachLine < aUnit->line_count; eachLine++)
        {
 
       for (eachLine = 0; eachLine < aUnit->line_count; eachLine++)
        {
+         if (xptr + 10 > stash->line_section_end)
+           {
+             aUnit->line_count = eachLine;
+             break;
+           }
          /* A line number.  */
          aUnit->linenumber_table[eachLine].linenumber
            = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
          /* A line number.  */
          aUnit->linenumber_table[eachLine].linenumber
            = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
@@ -337,11 +377,11 @@ parse_line_table (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
 static bfd_boolean
 parse_functions_in_unit (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
 {
 static bfd_boolean
 parse_functions_in_unit (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
 {
-  char* eachDie;
+  bfd_byte *eachDie;
 
   if (aUnit->first_child)
     for (eachDie = aUnit->first_child;
 
   if (aUnit->first_child)
     for (eachDie = aUnit->first_child;
-        eachDie < stash->debug_section_end;
+        eachDie < stash->debug_section_end;
         )
       {
        struct die_info eachDieInfo;
         )
       {
        struct die_info eachDieInfo;
@@ -356,6 +396,8 @@ parse_functions_in_unit (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
            || eachDieInfo.tag == TAG_entry_point)
          {
            struct dwarf1_func* aFunc = alloc_dwarf1_func (stash,aUnit);
            || eachDieInfo.tag == TAG_entry_point)
          {
            struct dwarf1_func* aFunc = alloc_dwarf1_func (stash,aUnit);
+           if (!aFunc)
+             return FALSE;
 
            aFunc->name = eachDieInfo.name;
            aFunc->low_pc = eachDieInfo.low_pc;
 
            aFunc->name = eachDieInfo.name;
            aFunc->low_pc = eachDieInfo.low_pc;
@@ -440,8 +482,8 @@ dwarf1_unit_find_nearest_line (struct dwarf1_debug* stash,
 
 bfd_boolean
 _bfd_dwarf1_find_nearest_line (bfd *abfd,
 
 bfd_boolean
 _bfd_dwarf1_find_nearest_line (bfd *abfd,
+                              asymbol **symbols,
                               asection *section,
                               asection *section,
-                              asymbol **symbols ATTRIBUTE_UNUSED,
                               bfd_vma offset,
                               const char **filename_ptr,
                               const char **functionname_ptr,
                               bfd_vma offset,
                               const char **filename_ptr,
                               const char **functionname_ptr,
@@ -464,7 +506,7 @@ _bfd_dwarf1_find_nearest_line (bfd *abfd,
       bfd_size_type size = sizeof (struct dwarf1_debug);
 
       stash = elf_tdata (abfd)->dwarf1_find_line_info
       bfd_size_type size = sizeof (struct dwarf1_debug);
 
       stash = elf_tdata (abfd)->dwarf1_find_line_info
-       = bfd_zalloc (abfd, size);
+       = (struct dwarf1_debug *) bfd_zalloc (abfd, size);
 
       if (! stash)
        return FALSE;
 
       if (! stash)
        return FALSE;
@@ -477,21 +519,17 @@ _bfd_dwarf1_find_nearest_line (bfd *abfd,
        return FALSE;
 
       size = msec->rawsize ? msec->rawsize : msec->size;
        return FALSE;
 
       size = msec->rawsize ? msec->rawsize : msec->size;
-      stash->debug_section = bfd_alloc (abfd, size);
+      stash->debug_section
+       = bfd_simple_get_relocated_section_contents (abfd, msec, NULL,
+                                                    symbols);
 
       if (! stash->debug_section)
        return FALSE;
 
 
       if (! stash->debug_section)
        return FALSE;
 
-      if (! bfd_get_section_contents (abfd, msec, stash->debug_section,
-                                     0, size))
-       {
-         stash->debug_section = 0;
-         return FALSE;
-       }
-
       stash->debug_section_end = stash->debug_section + size;
       stash->currentDie = stash->debug_section;
       stash->abfd = abfd;
       stash->debug_section_end = stash->debug_section + size;
       stash->currentDie = stash->debug_section;
       stash->abfd = abfd;
+      stash->syms = symbols;
     }
 
   /* A null debug_section indicates that there was no dwarf1 info
     }
 
   /* A null debug_section indicates that there was no dwarf1 info
@@ -521,6 +559,8 @@ _bfd_dwarf1_find_nearest_line (bfd *abfd,
        {
          struct dwarf1_unit* aUnit
            = alloc_dwarf1_unit (stash);
        {
          struct dwarf1_unit* aUnit
            = alloc_dwarf1_unit (stash);
+         if (!aUnit)
+           return FALSE;
 
          aUnit->name = aDieInfo.name;
          aUnit->low_pc = aDieInfo.low_pc;
 
          aUnit->name = aDieInfo.name;
          aUnit->low_pc = aDieInfo.low_pc;
@@ -532,9 +572,9 @@ _bfd_dwarf1_find_nearest_line (bfd *abfd,
             not it's sibling.  */
          if (aDieInfo.sibling
              && stash->currentDie + aDieInfo.length
             not it's sibling.  */
          if (aDieInfo.sibling
              && stash->currentDie + aDieInfo.length
-                    < stash->debug_section_end
+                   < stash->debug_section_end
              && stash->currentDie + aDieInfo.length
              && stash->currentDie + aDieInfo.length
-                   != stash->debug_section + aDieInfo.sibling)
+                   != stash->debug_section + aDieInfo.sibling)
            aUnit->first_child = stash->currentDie + aDieInfo.length;
          else
            aUnit->first_child = 0;
            aUnit->first_child = stash->currentDie + aDieInfo.length;
          else
            aUnit->first_child = 0;
This page took 0.032899 seconds and 4 git commands to generate.