X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fdwarf1.c;h=1fd21e32ede5120061a2d2179129e1d89ebbc1dd;hb=31175a0d7167ab7f98878076be02dc4330b825bb;hp=80fc242d38110f51a4fff225483a6f4fbb54de7a;hpb=a7b97311da9b9cef66a6aec0e7a17eb2770144b3;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/dwarf1.c b/bfd/dwarf1.c index 80fc242d38..1fd21e32ed 100644 --- a/bfd/dwarf1.c +++ b/bfd/dwarf1.c @@ -1,26 +1,27 @@ /* DWARF 1 find nearest line (_bfd_dwarf1_find_nearest_line). - Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1998-2019 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). -This file is part of BFD. + This file is part of BFD. -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 -your option) any later version. + 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 3 of the License, or (at + your option) any later version. -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. -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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + 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. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libiberty.h" #include "libbfd.h" #include "elf-bfd.h" @@ -28,54 +29,58 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* dwarf1_debug is the starting point for all dwarf1 info. */ -struct dwarf1_debug { - +struct dwarf1_debug +{ /* 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. */ - char* debug_section; + bfd_byte *debug_section; /* 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. */ - char* line_section; + bfd_byte *line_section; /* End of that buffer. */ - char* line_section_end; + bfd_byte *line_section_end; /* The current or next unread die within the .debug section. */ - char* currentDie; + bfd_byte *currentDie; }; /* One dwarf1_unit for each parsed compilation unit die. */ -struct dwarf1_unit { +struct dwarf1_unit +{ /* Linked starting from stash->lastUnit. */ struct dwarf1_unit* prev; /* Name of the compilation unit. */ - char* name; + char *name; /* The highest and lowest address used in the compilation unit. */ unsigned long low_pc; unsigned long high_pc; - /* Does this unit have a statement list? */ + /* Does this unit have a statement list? */ int has_stmt_list; /* If any, the offset of the line number table in the .line section. */ 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? */ + /* How many line entries? */ unsigned long line_count; /* The decoded line number table (line_count entries). */ @@ -87,7 +92,8 @@ struct dwarf1_unit { /* One dwarf1_func for each parsed function die. */ -struct dwarf1_func { +struct dwarf1_func +{ /* Linked starting from aUnit->func_list. */ struct dwarf1_func* prev; @@ -100,7 +106,8 @@ struct dwarf1_func { }; /* Used to return info about a parsed die. */ -struct die_info { +struct die_info +{ unsigned long length; unsigned long sibling; unsigned long low_pc; @@ -115,7 +122,8 @@ struct die_info { }; /* Parsed line number information. */ -struct linenumber { +struct linenumber +{ /* First address in the line. */ unsigned long addr; @@ -124,32 +132,22 @@ struct linenumber { }; /* Find the form of an attr, from the attr field. */ -#define FORM_FROM_ATTR(attr) ((attr) & 0xF) /* Implicitly specified */ - -static struct dwarf1_unit *alloc_dwarf1_unit PARAMS ((struct dwarf1_debug *)); -static struct dwarf1_func *alloc_dwarf1_func - PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *)); -static boolean parse_die PARAMS ((bfd *, struct die_info *, char *)); -static boolean parse_line_table - PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *)); -static boolean parse_functions_in_unit - PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *)); -static boolean dwarf1_unit_find_nearest_line - PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *, unsigned long, - const char **, const char **, unsigned int *)); +#define FORM_FROM_ATTR(attr) ((attr) & 0xF) /* Implicitly specified. */ /* Return a newly allocated dwarf1_unit. It should be cleared and then attached into the 'stash' at 'stash->lastUnit'. */ static struct dwarf1_unit* -alloc_dwarf1_unit (stash) - struct dwarf1_debug* stash; +alloc_dwarf1_unit (struct dwarf1_debug* stash) { - struct dwarf1_unit* x = - (struct dwarf1_unit*) bfd_zalloc (stash->abfd, - sizeof (struct dwarf1_unit)); - x->prev = stash->lastUnit; - stash->lastUnit = x; + bfd_size_type amt = sizeof (struct dwarf1_unit); + + struct dwarf1_unit* x = (struct dwarf1_unit *) bfd_zalloc (stash->abfd, amt); + if (x) + { + x->prev = stash->lastUnit; + stash->lastUnit = x; + } return x; } @@ -157,16 +155,17 @@ alloc_dwarf1_unit (stash) /* Return a newly allocated dwarf1_func. It must be cleared and attached into 'aUnit' at 'aUnit->func_list'. */ -static struct dwarf1_func* -alloc_dwarf1_func (stash, aUnit) - struct dwarf1_debug* stash; - struct dwarf1_unit* aUnit; +static struct dwarf1_func * +alloc_dwarf1_func (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit) { - struct dwarf1_func* x = - (struct dwarf1_func*) bfd_zalloc (stash->abfd, - sizeof (struct dwarf1_func)); - x->prev = aUnit->func_list; - aUnit->func_list = x; + bfd_size_type amt = sizeof (struct dwarf1_func); + + 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; } @@ -176,45 +175,51 @@ alloc_dwarf1_func (stash, aUnit) 'abfd' must be the bfd from which the section that 'aDiePtr' points to was pulled from. - Return false if the die is invalidly formatted; true otherwise. */ + Return FALSE if the die is invalidly formatted; TRUE otherwise. */ -static boolean -parse_die (abfd, aDieInfo, aDiePtr) - bfd* abfd; - struct die_info* aDieInfo; - char* aDiePtr; +static bfd_boolean +parse_die (bfd * abfd, + struct die_info * aDieInfo, + 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)); + 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) - return false; + if (aDieInfo->length == 0 + || this_die + aDieInfo->length > aDiePtrEnd) + return FALSE; + aDiePtrEnd = this_die + aDieInfo->length; if (aDieInfo->length < 6) { /* Just padding bytes. */ aDieInfo->tag = TAG_padding; - return true; + return TRUE; } /* 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. */ - 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 - 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. */ - - attr = bfd_get_16 (abfd, (bfd_byte *) xptr); + attr = bfd_get_16 (abfd, xptr); xptr += 2; switch (FORM_FROM_ATTR (attr)) @@ -224,12 +229,15 @@ parse_die (abfd, aDieInfo, aDiePtr) 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; @@ -237,72 +245,85 @@ parse_die (abfd, aDieInfo, aDiePtr) 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 += 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: - 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) - aDieInfo->name = xptr; - xptr += strlen (xptr) + 1; + aDieInfo->name = (char *) xptr; + xptr += strnlen ((char *) xptr, aDiePtrEnd - xptr) + 1; break; } } - return true; + return TRUE; } /* Parse a dwarf1 line number table for 'aUnit->stmt_list_offset' - into 'aUnit->linenumber_table'. Return false if an error - occurs; true otherwise. */ + into 'aUnit->linenumber_table'. Return FALSE if an error + occurs; TRUE otherwise. */ -static boolean -parse_line_table (stash, aUnit) - 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) { asection *msec; - unsigned long size; + bfd_size_type size; msec = bfd_get_section_by_name (stash->abfd, ".line"); if (! msec) - return false; + return FALSE; - size = bfd_get_section_size_before_reloc (msec); - stash->line_section = (char *) bfd_alloc (stash->abfd, size); + size = msec->rawsize ? msec->rawsize : msec->size; + stash->line_section + = bfd_simple_get_relocated_section_contents + (stash->abfd, msec, NULL, stash->syms); 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; - } + return FALSE; 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; - - char* tblend; + bfd_byte *tblend; unsigned long base; + bfd_size_type amt; /* First comes the length. */ tblend = bfd_get_32 (stash->abfd, (bfd_byte *) xptr) + xptr; @@ -313,16 +334,23 @@ parse_line_table (stash, aUnit) xptr += 4; /* How many line entrys? - 10 = 4 (line number) + 2 (pos in line) + 4 (address in line) */ + 10 = 4 (line number) + 2 (pos in line) + 4 (address in line). */ aUnit->line_count = (tblend - xptr) / 10; /* Allocate an array for the entries. */ - aUnit->linenumber_table = (struct linenumber *) - bfd_alloc (stash->abfd, - sizeof (struct linenumber) * aUnit->line_count); + amt = sizeof (struct linenumber) * aUnit->line_count; + aUnit->linenumber_table = (struct linenumber *) bfd_alloc (stash->abfd, + amt); + if (!aUnit->linenumber_table) + return FALSE; 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); @@ -338,20 +366,18 @@ parse_line_table (stash, aUnit) } } - return true; + return TRUE; } /* Parse each function die in a compilation unit 'aUnit'. The first child die of 'aUnit' should be in 'aUnit->first_child', the result is placed in 'aUnit->func_list'. - Return false if error; true otherwise. */ + Return FALSE if error; TRUE otherwise. */ -static boolean -parse_functions_in_unit (stash, aUnit) - 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; @@ -360,8 +386,9 @@ parse_functions_in_unit (stash, aUnit) { struct die_info eachDieInfo; - if (! parse_die (stash->abfd, &eachDieInfo, eachDie)) - return false; + if (! parse_die (stash->abfd, &eachDieInfo, eachDie, + stash->debug_section_end)) + return FALSE; if (eachDieInfo.tag == TAG_global_subroutine || eachDieInfo.tag == TAG_subroutine @@ -369,6 +396,8 @@ parse_functions_in_unit (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; @@ -382,25 +411,22 @@ parse_functions_in_unit (stash, aUnit) break; } - return true; + return TRUE; } /* Find the nearest line to 'addr' in 'aUnit'. Return whether we found the line (or a function) without error. */ -static boolean -dwarf1_unit_find_nearest_line (stash, aUnit, addr, - filename_ptr, functionname_ptr, - linenumber_ptr) - struct dwarf1_debug* stash; - struct dwarf1_unit* aUnit; - unsigned long addr; - const char **filename_ptr; - const char **functionname_ptr; - unsigned int *linenumber_ptr; +static bfd_boolean +dwarf1_unit_find_nearest_line (struct dwarf1_debug* stash, + struct dwarf1_unit* aUnit, + unsigned long addr, + const char **filename_ptr, + const char **functionname_ptr, + unsigned int *linenumber_ptr) { - int line_p = false; - int func_p = false; + int line_p = FALSE; + int func_p = FALSE; if (aUnit->low_pc <= addr && addr < aUnit->high_pc) { @@ -412,13 +438,13 @@ dwarf1_unit_find_nearest_line (stash, aUnit, addr, if (! aUnit->linenumber_table) { if (! parse_line_table (stash, aUnit)) - return false; + return FALSE; } if (! aUnit->func_list) { if (! parse_functions_in_unit (stash, aUnit)) - return false; + return FALSE; } for (i = 0; i < aUnit->line_count; i++) @@ -428,7 +454,7 @@ dwarf1_unit_find_nearest_line (stash, aUnit, addr, { *filename_ptr = aUnit->name; *linenumber_ptr = aUnit->linenumber_table[i].linenumber; - line_p = true; + line_p = TRUE; break; } } @@ -441,7 +467,7 @@ dwarf1_unit_find_nearest_line (stash, aUnit, addr, && addr < eachFunc->high_pc) { *functionname_ptr = eachFunc->name; - func_p = true; + func_p = TRUE; break; } } @@ -452,18 +478,16 @@ dwarf1_unit_find_nearest_line (stash, aUnit, addr, } /* The DWARF 1 version of find_nearest line. - Return true if the line is found without error. */ - -boolean -_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, - filename_ptr, functionname_ptr, linenumber_ptr) - bfd *abfd; - asection *section; - asymbol **symbols ATTRIBUTE_UNUSED; - bfd_vma offset; - const char **filename_ptr; - const char **functionname_ptr; - unsigned int *linenumber_ptr; + Return TRUE if the line is found without error. */ + +bfd_boolean +_bfd_dwarf1_find_nearest_line (bfd *abfd, + asymbol **symbols, + asection *section, + bfd_vma offset, + const char **filename_ptr, + const char **functionname_ptr, + unsigned int *linenumber_ptr) { struct dwarf1_debug *stash = elf_tdata (abfd)->dwarf1_find_line_info; @@ -479,68 +503,64 @@ _bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, if (! stash) { asection *msec; - unsigned long size; + bfd_size_type size = sizeof (struct dwarf1_debug); - stash = elf_tdata (abfd)->dwarf1_find_line_info = - (struct dwarf1_debug*) bfd_zalloc (abfd, sizeof (struct dwarf1_debug)); + stash = elf_tdata (abfd)->dwarf1_find_line_info + = (struct dwarf1_debug *) bfd_zalloc (abfd, size); if (! stash) - return false; + return FALSE; msec = bfd_get_section_by_name (abfd, ".debug"); if (! msec) - { - /* No dwarf1 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; - } + /* No dwarf1 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; - size = bfd_get_section_size_before_reloc (msec); - stash->debug_section = (char *) bfd_alloc (abfd, size); + size = msec->rawsize ? msec->rawsize : msec->size; + stash->debug_section + = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, + symbols); if (! stash->debug_section) - return false; - - if (! bfd_get_section_contents (abfd, msec, stash->debug_section, 0, size)) - { - stash->debug_section = 0; - return false; - } + return FALSE; 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 or that an error occured while setting up the stash. */ if (! stash->debug_section) - return false; + return FALSE; /* Look at the previously parsed units to see if any contain the addr. */ for (eachUnit = stash->lastUnit; eachUnit; eachUnit = eachUnit->prev) - { - if (eachUnit->low_pc <= addr && addr < eachUnit->high_pc) - return dwarf1_unit_find_nearest_line (stash, eachUnit, addr, - filename_ptr, - functionname_ptr, - linenumber_ptr); - } + if (eachUnit->low_pc <= addr && addr < eachUnit->high_pc) + return dwarf1_unit_find_nearest_line (stash, eachUnit, addr, + filename_ptr, + functionname_ptr, + linenumber_ptr); while (stash->currentDie < stash->debug_section_end) { struct die_info aDieInfo; - if (! parse_die (stash->abfd, &aDieInfo, stash->currentDie)) - return false; + if (! parse_die (stash->abfd, &aDieInfo, stash->currentDie, + stash->debug_section_end)) + return FALSE; if (aDieInfo.tag == TAG_compile_unit) { struct dwarf1_unit* aUnit = alloc_dwarf1_unit (stash); + if (!aUnit) + return FALSE; aUnit->name = aDieInfo.name; aUnit->low_pc = aDieInfo.low_pc; @@ -552,9 +572,9 @@ _bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, not it's sibling. */ if (aDieInfo.sibling && stash->currentDie + aDieInfo.length - < stash->debug_section_end + < stash->debug_section_end && 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; @@ -572,7 +592,5 @@ _bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, stash->currentDie += aDieInfo.length; } - return false; + return FALSE; } - -/* EOF */