X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fdwarf1.c;h=65319861a1c0a06a6702ef042e24b6d160664471;hb=6eb69eab2909778dc96bdb5dbb83d7756bee4601;hp=cbcc26b003560d94c3d0e70d1e744d6ae6aa26a3;hpb=252b5132c753830d5fd56823373aed85f2a0db63;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/dwarf1.c b/bfd/dwarf1.c index cbcc26b003..65319861a1 100644 --- a/bfd/dwarf1.c +++ b/bfd/dwarf1.c @@ -1,7 +1,7 @@ /* DWARF 1 find nearest line (_bfd_dwarf1_find_nearest_line). - Copyright 1998 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001 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. @@ -26,122 +26,128 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "elf-bfd.h" #include "elf/dwarf.h" -/* dwarf1_debug is the starting point for all dwarf1 info. */ +/* dwarf1_debug is the starting point for all dwarf1 info. */ struct dwarf1_debug { - /* The bfd we are working with. */ + /* The bfd we are working with. */ bfd* abfd; - /* List of already parsed compilation units. */ + /* 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. */ + /* The buffer for the .debug section. + Zero indicates that the .debug section failed to load. */ char* 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; - /* The buffer for the .line section. */ + /* The buffer for the .line section. */ char* line_section; - /* End of that buffer. */ + /* End of that buffer. */ char* 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; }; -/* One dwarf1_unit for each parsed compilation unit die. */ +/* One dwarf1_unit for each parsed compilation unit die. */ struct dwarf1_unit { - /* Linked starting from stash->lastUnit. */ + /* Linked starting from stash->lastUnit. */ struct dwarf1_unit* prev; - /* Name of the compilation unit. */ + /* Name of the compilation unit. */ char* name; - /* The highest and lowest address used in the compilation unit. */ + /* 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? */ int has_stmt_list; - /* If any, the offset of the line number table in the .line section. */ + /* 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. */ + /* If non-zero, a pointer to the first child of this unit. */ char* first_child; /* How many line entries? */ unsigned long line_count; - /* The decoded line number table (line_count entries). */ + /* The decoded line number table (line_count entries). */ struct linenumber* linenumber_table; - /* The list of functions in this unit. */ + /* The list of functions in this unit. */ struct dwarf1_func* func_list; }; - - /* One dwarf1_func for each parsed function die. */ struct dwarf1_func { - /* Linked starting from aUnit->func_list. */ + /* Linked starting from aUnit->func_list. */ struct dwarf1_func* prev; - - /* Name of function. */ + + /* Name of function. */ char* name; - - /* The highest and lowest address used in the compilation unit. */ + + /* The highest and lowest address used in the compilation unit. */ unsigned long low_pc; unsigned long high_pc; }; - -/* Used to return info about a parsed die. */ +/* Used to return info about a parsed die. */ struct die_info { unsigned long length; unsigned long sibling; unsigned long low_pc; unsigned long high_pc; unsigned long stmt_list_offset; - - char* name; - + + char* name; + int has_stmt_list; unsigned short tag; }; - -/* Parsed line number information. */ +/* Parsed line number information. */ struct linenumber { - /* First address in the line. */ + /* First address in the line. */ unsigned long addr; - /* The line number. */ + /* The line number. */ unsigned long linenumber; }; - -/* Find the form of an attr, from the attr field. */ +/* 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 *, 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 *)); /* Return a newly allocated dwarf1_unit. It should be cleared and - then attached into the 'stash' at 'stash->lastUnit'. */ + then attached into the 'stash' at 'stash->lastUnit'. */ static struct dwarf1_unit* alloc_dwarf1_unit (stash) struct dwarf1_debug* stash; { - struct dwarf1_unit* x = - (struct dwarf1_unit*) bfd_alloc (stash->abfd, - sizeof (struct dwarf1_unit)); + bfd_size_type amt = sizeof (struct dwarf1_unit); + + struct dwarf1_unit* x = (struct dwarf1_unit*) bfd_zalloc (stash->abfd, amt); x->prev = stash->lastUnit; stash->lastUnit = x; @@ -149,66 +155,70 @@ alloc_dwarf1_unit (stash) } /* Return a newly allocated dwarf1_func. It must be cleared and - attached into 'aUnit' at 'aUnit->func_list'. */ + attached into 'aUnit' at 'aUnit->func_list'. */ static struct dwarf1_func* alloc_dwarf1_func (stash, aUnit) struct dwarf1_debug* stash; struct dwarf1_unit* aUnit; { - struct dwarf1_func* x = - (struct dwarf1_func*) bfd_alloc (stash->abfd, - sizeof (struct dwarf1_func)); + bfd_size_type amt = sizeof (struct dwarf1_func); + + struct dwarf1_func* x = (struct dwarf1_func*) bfd_zalloc (stash->abfd, amt); x->prev = aUnit->func_list; aUnit->func_list = x; - + return x; } /* parse_die - parse a Dwarf1 die. Parse the die starting at 'aDiePtr' into 'aDieInfo'. 'abfd' must be the bfd from which the section that 'aDiePtr' - points to was pulled from. + 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) +parse_die (abfd, aDieInfo, aDiePtr, aDiePtrEnd) bfd* abfd; struct die_info* aDieInfo; char* aDiePtr; + char* aDiePtrEnd; { char* this_die = aDiePtr; char* xptr = this_die; - memset (aDieInfo,0,sizeof(*aDieInfo)); + memset (aDieInfo,0,sizeof (*aDieInfo)); - /* First comes the length. */ - aDieInfo->length = bfd_get_32 (abfd, xptr); + /* First comes the length. */ + aDieInfo->length = bfd_get_32 (abfd, (bfd_byte *) xptr); xptr += 4; + if (aDieInfo->length == 0 + || (this_die + aDieInfo->length) >= aDiePtrEnd) + return false; if (aDieInfo->length < 6) { - /* Just padding bytes. */ + /* Just padding bytes. */ aDieInfo->tag = TAG_padding; return true; } - /* Then the tag. */ - aDieInfo->tag = bfd_get_16 (abfd, xptr); + /* Then the tag. */ + aDieInfo->tag = bfd_get_16 (abfd, (bfd_byte *) xptr); xptr += 2; - - /* Then the attributes. */ + + /* Then the attributes. */ while (xptr < (this_die + aDieInfo->length)) { unsigned short attr; - - /* Parse the attribute based on its form. This section + + /* Parse the attribute based on its form. This section 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, xptr); + attr = bfd_get_16 (abfd, (bfd_byte *) xptr); xptr += 2; - + switch (FORM_FROM_ATTR (attr)) { case FORM_DATA2: @@ -217,10 +227,10 @@ parse_die (abfd, aDieInfo, aDiePtr) case FORM_DATA4: case FORM_REF: if (attr == AT_sibling) - aDieInfo->sibling = bfd_get_32 (abfd, xptr); + aDieInfo->sibling = bfd_get_32 (abfd, (bfd_byte *) xptr); else if (attr == AT_stmt_list) { - aDieInfo->stmt_list_offset = bfd_get_32 (abfd, xptr); + aDieInfo->stmt_list_offset = bfd_get_32 (abfd, (bfd_byte *) xptr); aDieInfo->has_stmt_list = 1; } xptr += 4; @@ -230,16 +240,16 @@ parse_die (abfd, aDieInfo, aDiePtr) break; case FORM_ADDR: if (attr == AT_low_pc) - aDieInfo->low_pc = bfd_get_32 (abfd, xptr); + aDieInfo->low_pc = bfd_get_32 (abfd, (bfd_byte *) xptr); else if (attr == AT_high_pc) - aDieInfo->high_pc = bfd_get_32 (abfd, xptr); + aDieInfo->high_pc = bfd_get_32 (abfd, (bfd_byte *) xptr); xptr += 4; break; case FORM_BLOCK2: - xptr += 2 + bfd_get_16 (abfd, xptr); + xptr += 2 + bfd_get_16 (abfd, (bfd_byte *) xptr); break; case FORM_BLOCK4: - xptr += 4 + bfd_get_32 (abfd, xptr); + xptr += 4 + bfd_get_32 (abfd, (bfd_byte *) xptr); break; case FORM_STRING: if (attr == AT_name) @@ -253,9 +263,9 @@ parse_die (abfd, aDieInfo, aDiePtr) } /* 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; @@ -263,23 +273,24 @@ parse_line_table (stash, aUnit) { char* xptr; - /* Load the ".line" section from the bfd if we haven't already. */ + /* 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; - + size = bfd_get_section_size_before_reloc (msec); - stash->line_section = (unsigned char*) bfd_alloc (stash->abfd, size); - + stash->line_section = (char *) bfd_alloc (stash->abfd, size); + if (! stash->line_section) return false; - if (! bfd_get_section_contents (stash->abfd, msec, stash->line_section, 0, size)) + if (! bfd_get_section_contents (stash->abfd, msec, stash->line_section, + (bfd_vma) 0, size)) { stash->line_section = 0; return false; @@ -291,41 +302,41 @@ parse_line_table (stash, aUnit) xptr = stash->line_section + aUnit->stmt_list_offset; if (xptr < stash->line_section_end) { - int eachLine; - - char* tblend; + unsigned long eachLine; + char *tblend; unsigned long base; + bfd_size_type amt; - /* First comes the length. */ - tblend = bfd_get_32 (stash->abfd, xptr) + xptr; + /* First comes the length. */ + tblend = bfd_get_32 (stash->abfd, (bfd_byte *) xptr) + xptr; xptr += 4; - /* Then the base address for each address in the table. */ - base = bfd_get_32 (stash->abfd, xptr); + /* Then the base address for each address in the table. */ + base = bfd_get_32 (stash->abfd, (bfd_byte *) xptr); xptr += 4; /* How many line entrys? 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); - + /* Allocate an array for the entries. */ + amt = sizeof (struct linenumber) * aUnit->line_count; + aUnit->linenumber_table = ((struct linenumber *) + bfd_alloc (stash->abfd, amt)); + for (eachLine = 0; eachLine < aUnit->line_count; eachLine++) { - /* A line number. */ + /* A line number. */ aUnit->linenumber_table[eachLine].linenumber - = bfd_get_32 (stash->abfd, xptr); + = bfd_get_32 (stash->abfd, (bfd_byte *) xptr); xptr += 4; - /* Skip the position within the line. */ + /* Skip the position within the line. */ xptr += 2; - /* And finally the address. */ - aUnit->linenumber_table[eachLine].addr - = base + bfd_get_32 (stash->abfd, xptr); + /* And finally the address. */ + aUnit->linenumber_table[eachLine].addr + = base + bfd_get_32 (stash->abfd, (bfd_byte *) xptr); xptr += 4; } } @@ -336,7 +347,7 @@ parse_line_table (stash, aUnit) /* 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) @@ -351,37 +362,38 @@ parse_functions_in_unit (stash, aUnit) ) { struct die_info eachDieInfo; - - if (! parse_die (stash->abfd, &eachDieInfo, eachDie)) + + if (! parse_die (stash->abfd, &eachDieInfo, eachDie, + stash->debug_section_end)) return false; - + if (eachDieInfo.tag == TAG_global_subroutine || eachDieInfo.tag == TAG_subroutine || eachDieInfo.tag == TAG_inlined_subroutine || eachDieInfo.tag == TAG_entry_point) { struct dwarf1_func* aFunc = alloc_dwarf1_func (stash,aUnit); - + aFunc->name = eachDieInfo.name; aFunc->low_pc = eachDieInfo.low_pc; aFunc->high_pc = eachDieInfo.high_pc; } - + /* Move to next sibling, if none, end loop */ if (eachDieInfo.sibling) eachDie = stash->debug_section + eachDieInfo.sibling; else break; } - + return true; } /* Find the nearest line to 'addr' in 'aUnit'. - Return whether we found the line (or a function) without error. */ + Return whether we found the line (or a function) without error. */ static boolean -dwarf1_unit_find_nearest_line (stash, aUnit, addr, +dwarf1_unit_find_nearest_line (stash, aUnit, addr, filename_ptr, functionname_ptr, linenumber_ptr) struct dwarf1_debug* stash; @@ -398,7 +410,7 @@ dwarf1_unit_find_nearest_line (stash, aUnit, addr, { if (aUnit->has_stmt_list) { - int i; + unsigned long i; struct dwarf1_func* eachFunc; if (! aUnit->linenumber_table) @@ -425,8 +437,8 @@ dwarf1_unit_find_nearest_line (stash, aUnit, addr, } } - for (eachFunc = aUnit->func_list; - eachFunc; + for (eachFunc = aUnit->func_list; + eachFunc; eachFunc = eachFunc->prev) { if (eachFunc->low_pc <= addr @@ -443,18 +455,15 @@ dwarf1_unit_find_nearest_line (stash, aUnit, addr, return line_p || func_p; } - - - /* The DWARF 1 version of find_nearest line. - Return true if the line is found without error. */ + 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; + asymbol **symbols ATTRIBUTE_UNUSED; bfd_vma offset; const char **filename_ptr; const char **functionname_ptr; @@ -465,40 +474,40 @@ _bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, struct dwarf1_unit* eachUnit; /* What address are we looking for? */ - bfd_vma addr = offset + section->vma; + unsigned long addr = (unsigned long)(offset + section->vma); *filename_ptr = NULL; *functionname_ptr = NULL; *linenumber_ptr = 0; - if (! stash) { asection *msec; - unsigned long size; - - stash = elf_tdata (abfd)->dwarf1_find_line_info = - (struct dwarf1_debug*) bfd_zalloc (abfd, sizeof (struct dwarf1_debug)); - + bfd_size_type size = sizeof (struct dwarf1_debug); + + stash = elf_tdata (abfd)->dwarf1_find_line_info + = (struct dwarf1_debug *) bfd_zalloc (abfd, size); + if (! stash) 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. */ + future calls to this function fail quicker. */ return false; } size = bfd_get_section_size_before_reloc (msec); - stash->debug_section = (unsigned char*) bfd_alloc (abfd, size); - + stash->debug_section = (char *) bfd_alloc (abfd, size); + if (! stash->debug_section) return false; - if (! bfd_get_section_contents (abfd, msec, stash->debug_section, 0, size)) + if (! bfd_get_section_contents (abfd, msec, stash->debug_section, + (bfd_vma) 0, size)) { stash->debug_section = 0; return false; @@ -510,20 +519,19 @@ _bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, } /* A null debug_section indicates that there was no dwarf1 info - or that an error occured while setting up the stash. */ + or that an error occured while setting up the stash. */ if (! stash->debug_section) return false; - /* Look at the previously parsed units to see if any contain - the addr. */ + 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, + filename_ptr, + functionname_ptr, linenumber_ptr); } @@ -531,38 +539,39 @@ _bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, { struct die_info aDieInfo; - if (! parse_die (stash->abfd, &aDieInfo, stash->currentDie)) + 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); - + aUnit->name = aDieInfo.name; aUnit->low_pc = aDieInfo.low_pc; aUnit->high_pc = aDieInfo.high_pc; aUnit->has_stmt_list = aDieInfo.has_stmt_list; aUnit->stmt_list_offset = aDieInfo.stmt_list_offset; - + /* A die has a child if it's followed by a die that is - 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->currentDie + aDieInfo.length + && stash->currentDie + aDieInfo.length != stash->debug_section + aDieInfo.sibling) aUnit->first_child = stash->currentDie + aDieInfo.length; else aUnit->first_child = 0; if (aUnit->low_pc <= addr && addr < aUnit->high_pc) - return dwarf1_unit_find_nearest_line (stash, aUnit, addr, - filename_ptr, - functionname_ptr, + return dwarf1_unit_find_nearest_line (stash, aUnit, addr, + filename_ptr, + functionname_ptr, linenumber_ptr); } - + if (aDieInfo.sibling != 0) stash->currentDie = stash->debug_section + aDieInfo.sibling; else @@ -572,5 +581,4 @@ _bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, return false; } - /* EOF */