X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fdwarf1.c;h=1fd21e32ede5120061a2d2179129e1d89ebbc1dd;hb=44b27f959abf267fc9ec228f4131c932597b01d4;hp=b9033a518eb6c4577350c9baa6524dbbd29e5754;hpb=53e09e0aaf3d13e4b893744e2fe79edde7edfd20;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/dwarf1.c b/bfd/dwarf1.c index b9033a518e..1fd21e32ed 100644 --- a/bfd/dwarf1.c +++ b/bfd/dwarf1.c @@ -1,6 +1,5 @@ /* 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-2019 Free Software Foundation, Inc. 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 - 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 @@ -18,10 +17,11 @@ 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 02110-1301, USA. */ + 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" @@ -34,24 +34,27 @@ 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. */ @@ -62,7 +65,7 @@ struct dwarf1_unit 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; @@ -75,7 +78,7 @@ struct dwarf1_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; @@ -139,9 +142,12 @@ alloc_dwarf1_unit (struct dwarf1_debug* stash) { bfd_size_type 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; } @@ -154,9 +160,12 @@ alloc_dwarf1_func (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit) { bfd_size_type 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; } @@ -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 -parse_die (bfd * abfd, +parse_die (bfd * abfd, 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. */ - 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 - || (this_die + aDieInfo->length) >= aDiePtrEnd) + || this_die + aDieInfo->length > aDiePtrEnd) return FALSE; + aDiePtrEnd = this_die + aDieInfo->length; if (aDieInfo->length < 6) { /* Just padding bytes. */ @@ -193,18 +205,21 @@ parse_die (bfd * abfd, } /* 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)) @@ -214,12 +229,15 @@ parse_die (bfd * abfd, 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; @@ -227,22 +245,41 @@ parse_die (bfd * abfd, 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; } } @@ -257,7 +294,7 @@ parse_die (bfd * abfd, 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) @@ -270,26 +307,21 @@ parse_line_table (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit) 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 (! 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; - 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; @@ -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; - 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++) { + 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); @@ -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) { - char* eachDie; + bfd_byte *eachDie; if (aUnit->first_child) for (eachDie = aUnit->first_child; - eachDie < stash->debug_section_end; + eachDie < stash->debug_section_end; ) { 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); + if (!aFunc) + return FALSE; 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, + asymbol **symbols, asection *section, - asymbol **symbols ATTRIBUTE_UNUSED, 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_zalloc (abfd, size); + = (struct dwarf1_debug *) bfd_zalloc (abfd, size); if (! stash) return FALSE; @@ -477,21 +519,17 @@ _bfd_dwarf1_find_nearest_line (bfd *abfd, 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 (! 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->syms = symbols; } /* 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); + if (!aUnit) + return FALSE; 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 - < 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;