1 |
/* DWARF 1 find nearest line (_bfd_dwarf1_find_nearest_line). |
/* DWARF 1 find nearest line (_bfd_dwarf1_find_nearest_line). |
2 |
Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |
Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. |
3 |
|
|
4 |
Written by Gavin Romig-Koch of Cygnus Solutions (gavin@cygnus.com). |
Written by Gavin Romig-Koch of Cygnus Solutions (gavin@cygnus.com). |
5 |
|
|
126 |
/* Find the form of an attr, from the attr field. */ |
/* Find the form of an attr, from the attr field. */ |
127 |
#define FORM_FROM_ATTR(attr) ((attr) & 0xF) /* Implicitly specified */ |
#define FORM_FROM_ATTR(attr) ((attr) & 0xF) /* Implicitly specified */ |
128 |
|
|
129 |
static struct dwarf1_unit *alloc_dwarf1_unit PARAMS ((struct dwarf1_debug *)); |
static struct dwarf1_unit *alloc_dwarf1_unit |
130 |
|
PARAMS ((struct dwarf1_debug *)); |
131 |
static struct dwarf1_func *alloc_dwarf1_func |
static struct dwarf1_func *alloc_dwarf1_func |
132 |
PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *)); |
PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *)); |
133 |
static boolean parse_die PARAMS ((bfd *, struct die_info *, char *, char *)); |
static bfd_boolean parse_die |
134 |
static boolean parse_line_table |
PARAMS ((bfd *, struct die_info *, char *, char *)); |
135 |
|
static bfd_boolean parse_line_table |
136 |
PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *)); |
PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *)); |
137 |
static boolean parse_functions_in_unit |
static bfd_boolean parse_functions_in_unit |
138 |
PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *)); |
PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *)); |
139 |
static boolean dwarf1_unit_find_nearest_line |
static bfd_boolean dwarf1_unit_find_nearest_line |
140 |
PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *, unsigned long, |
PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *, unsigned long, |
141 |
const char **, const char **, unsigned int *)); |
const char **, const char **, unsigned int *)); |
142 |
|
|
178 |
'abfd' must be the bfd from which the section that 'aDiePtr' |
'abfd' must be the bfd from which the section that 'aDiePtr' |
179 |
points to was pulled from. |
points to was pulled from. |
180 |
|
|
181 |
Return false if the die is invalidly formatted; true otherwise. */ |
Return FALSE if the die is invalidly formatted; TRUE otherwise. */ |
182 |
|
|
183 |
static boolean |
static bfd_boolean |
184 |
parse_die (abfd, aDieInfo, aDiePtr, aDiePtrEnd) |
parse_die (abfd, aDieInfo, aDiePtr, aDiePtrEnd) |
185 |
bfd* abfd; |
bfd* abfd; |
186 |
struct die_info* aDieInfo; |
struct die_info* aDieInfo; |
197 |
xptr += 4; |
xptr += 4; |
198 |
if (aDieInfo->length == 0 |
if (aDieInfo->length == 0 |
199 |
|| (this_die + aDieInfo->length) >= aDiePtrEnd) |
|| (this_die + aDieInfo->length) >= aDiePtrEnd) |
200 |
return false; |
return FALSE; |
201 |
if (aDieInfo->length < 6) |
if (aDieInfo->length < 6) |
202 |
{ |
{ |
203 |
/* Just padding bytes. */ |
/* Just padding bytes. */ |
204 |
aDieInfo->tag = TAG_padding; |
aDieInfo->tag = TAG_padding; |
205 |
return true; |
return TRUE; |
206 |
} |
} |
207 |
|
|
208 |
/* Then the tag. */ |
/* Then the tag. */ |
261 |
} |
} |
262 |
} |
} |
263 |
|
|
264 |
return true; |
return TRUE; |
265 |
} |
} |
266 |
|
|
267 |
/* Parse a dwarf1 line number table for 'aUnit->stmt_list_offset' |
/* Parse a dwarf1 line number table for 'aUnit->stmt_list_offset' |
268 |
into 'aUnit->linenumber_table'. Return false if an error |
into 'aUnit->linenumber_table'. Return FALSE if an error |
269 |
occurs; true otherwise. */ |
occurs; TRUE otherwise. */ |
270 |
|
|
271 |
static boolean |
static bfd_boolean |
272 |
parse_line_table (stash, aUnit) |
parse_line_table (stash, aUnit) |
273 |
struct dwarf1_debug* stash; |
struct dwarf1_debug* stash; |
274 |
struct dwarf1_unit* aUnit; |
struct dwarf1_unit* aUnit; |
283 |
|
|
284 |
msec = bfd_get_section_by_name (stash->abfd, ".line"); |
msec = bfd_get_section_by_name (stash->abfd, ".line"); |
285 |
if (! msec) |
if (! msec) |
286 |
return false; |
return FALSE; |
287 |
|
|
288 |
size = bfd_get_section_size_before_reloc (msec); |
size = msec->rawsize ? msec->rawsize : msec->size; |
289 |
stash->line_section = (char *) bfd_alloc (stash->abfd, size); |
stash->line_section = (char *) bfd_alloc (stash->abfd, size); |
290 |
|
|
291 |
if (! stash->line_section) |
if (! stash->line_section) |
292 |
return false; |
return FALSE; |
293 |
|
|
294 |
if (! bfd_get_section_contents (stash->abfd, msec, stash->line_section, |
if (! bfd_get_section_contents (stash->abfd, msec, stash->line_section, |
295 |
(bfd_vma) 0, size)) |
0, size)) |
296 |
{ |
{ |
297 |
stash->line_section = 0; |
stash->line_section = 0; |
298 |
return false; |
return FALSE; |
299 |
} |
} |
300 |
|
|
301 |
stash->line_section_end = stash->line_section + size; |
stash->line_section_end = stash->line_section + size; |
343 |
} |
} |
344 |
} |
} |
345 |
|
|
346 |
return true; |
return TRUE; |
347 |
} |
} |
348 |
|
|
349 |
/* Parse each function die in a compilation unit 'aUnit'. |
/* Parse each function die in a compilation unit 'aUnit'. |
350 |
The first child die of 'aUnit' should be in 'aUnit->first_child', |
The first child die of 'aUnit' should be in 'aUnit->first_child', |
351 |
the result is placed in 'aUnit->func_list'. |
the result is placed in 'aUnit->func_list'. |
352 |
Return false if error; true otherwise. */ |
Return FALSE if error; TRUE otherwise. */ |
353 |
|
|
354 |
static boolean |
static bfd_boolean |
355 |
parse_functions_in_unit (stash, aUnit) |
parse_functions_in_unit (stash, aUnit) |
356 |
struct dwarf1_debug* stash; |
struct dwarf1_debug* stash; |
357 |
struct dwarf1_unit* aUnit; |
struct dwarf1_unit* aUnit; |
367 |
|
|
368 |
if (! parse_die (stash->abfd, &eachDieInfo, eachDie, |
if (! parse_die (stash->abfd, &eachDieInfo, eachDie, |
369 |
stash->debug_section_end)) |
stash->debug_section_end)) |
370 |
return false; |
return FALSE; |
371 |
|
|
372 |
if (eachDieInfo.tag == TAG_global_subroutine |
if (eachDieInfo.tag == TAG_global_subroutine |
373 |
|| eachDieInfo.tag == TAG_subroutine |
|| eachDieInfo.tag == TAG_subroutine |
388 |
break; |
break; |
389 |
} |
} |
390 |
|
|
391 |
return true; |
return TRUE; |
392 |
} |
} |
393 |
|
|
394 |
/* Find the nearest line to 'addr' in 'aUnit'. |
/* Find the nearest line to 'addr' in 'aUnit'. |
395 |
Return whether we found the line (or a function) without error. */ |
Return whether we found the line (or a function) without error. */ |
396 |
|
|
397 |
static boolean |
static bfd_boolean |
398 |
dwarf1_unit_find_nearest_line (stash, aUnit, addr, |
dwarf1_unit_find_nearest_line (stash, aUnit, addr, |
399 |
filename_ptr, functionname_ptr, |
filename_ptr, functionname_ptr, |
400 |
linenumber_ptr) |
linenumber_ptr) |
405 |
const char **functionname_ptr; |
const char **functionname_ptr; |
406 |
unsigned int *linenumber_ptr; |
unsigned int *linenumber_ptr; |
407 |
{ |
{ |
408 |
int line_p = false; |
int line_p = FALSE; |
409 |
int func_p = false; |
int func_p = FALSE; |
410 |
|
|
411 |
if (aUnit->low_pc <= addr && addr < aUnit->high_pc) |
if (aUnit->low_pc <= addr && addr < aUnit->high_pc) |
412 |
{ |
{ |
418 |
if (! aUnit->linenumber_table) |
if (! aUnit->linenumber_table) |
419 |
{ |
{ |
420 |
if (! parse_line_table (stash, aUnit)) |
if (! parse_line_table (stash, aUnit)) |
421 |
return false; |
return FALSE; |
422 |
} |
} |
423 |
|
|
424 |
if (! aUnit->func_list) |
if (! aUnit->func_list) |
425 |
{ |
{ |
426 |
if (! parse_functions_in_unit (stash, aUnit)) |
if (! parse_functions_in_unit (stash, aUnit)) |
427 |
return false; |
return FALSE; |
428 |
} |
} |
429 |
|
|
430 |
for (i = 0; i < aUnit->line_count; i++) |
for (i = 0; i < aUnit->line_count; i++) |
434 |
{ |
{ |
435 |
*filename_ptr = aUnit->name; |
*filename_ptr = aUnit->name; |
436 |
*linenumber_ptr = aUnit->linenumber_table[i].linenumber; |
*linenumber_ptr = aUnit->linenumber_table[i].linenumber; |
437 |
line_p = true; |
line_p = TRUE; |
438 |
break; |
break; |
439 |
} |
} |
440 |
} |
} |
447 |
&& addr < eachFunc->high_pc) |
&& addr < eachFunc->high_pc) |
448 |
{ |
{ |
449 |
*functionname_ptr = eachFunc->name; |
*functionname_ptr = eachFunc->name; |
450 |
func_p = true; |
func_p = TRUE; |
451 |
break; |
break; |
452 |
} |
} |
453 |
} |
} |
458 |
} |
} |
459 |
|
|
460 |
/* The DWARF 1 version of find_nearest line. |
/* The DWARF 1 version of find_nearest line. |
461 |
Return true if the line is found without error. */ |
Return TRUE if the line is found without error. */ |
462 |
|
|
463 |
boolean |
bfd_boolean |
464 |
_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, |
_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, |
465 |
filename_ptr, functionname_ptr, linenumber_ptr) |
filename_ptr, functionname_ptr, linenumber_ptr) |
466 |
bfd *abfd; |
bfd *abfd; |
491 |
= (struct dwarf1_debug *) bfd_zalloc (abfd, size); |
= (struct dwarf1_debug *) bfd_zalloc (abfd, size); |
492 |
|
|
493 |
if (! stash) |
if (! stash) |
494 |
return false; |
return FALSE; |
495 |
|
|
496 |
msec = bfd_get_section_by_name (abfd, ".debug"); |
msec = bfd_get_section_by_name (abfd, ".debug"); |
497 |
if (! msec) |
if (! msec) |
499 |
/* No dwarf1 info. Note that at this point the stash |
/* No dwarf1 info. Note that at this point the stash |
500 |
has been allocated, but contains zeros, this lets |
has been allocated, but contains zeros, this lets |
501 |
future calls to this function fail quicker. */ |
future calls to this function fail quicker. */ |
502 |
return false; |
return FALSE; |
503 |
} |
} |
504 |
|
|
505 |
size = bfd_get_section_size_before_reloc (msec); |
size = msec->rawsize ? msec->rawsize : msec->size; |
506 |
stash->debug_section = (char *) bfd_alloc (abfd, size); |
stash->debug_section = (char *) bfd_alloc (abfd, size); |
507 |
|
|
508 |
if (! stash->debug_section) |
if (! stash->debug_section) |
509 |
return false; |
return FALSE; |
510 |
|
|
511 |
if (! bfd_get_section_contents (abfd, msec, stash->debug_section, |
if (! bfd_get_section_contents (abfd, msec, stash->debug_section, |
512 |
(bfd_vma) 0, size)) |
0, size)) |
513 |
{ |
{ |
514 |
stash->debug_section = 0; |
stash->debug_section = 0; |
515 |
return false; |
return FALSE; |
516 |
} |
} |
517 |
|
|
518 |
stash->debug_section_end = stash->debug_section + size; |
stash->debug_section_end = stash->debug_section + size; |
524 |
or that an error occured while setting up the stash. */ |
or that an error occured while setting up the stash. */ |
525 |
|
|
526 |
if (! stash->debug_section) |
if (! stash->debug_section) |
527 |
return false; |
return FALSE; |
528 |
|
|
529 |
/* Look at the previously parsed units to see if any contain |
/* Look at the previously parsed units to see if any contain |
530 |
the addr. */ |
the addr. */ |
543 |
|
|
544 |
if (! parse_die (stash->abfd, &aDieInfo, stash->currentDie, |
if (! parse_die (stash->abfd, &aDieInfo, stash->currentDie, |
545 |
stash->debug_section_end)) |
stash->debug_section_end)) |
546 |
return false; |
return FALSE; |
547 |
|
|
548 |
if (aDieInfo.tag == TAG_compile_unit) |
if (aDieInfo.tag == TAG_compile_unit) |
549 |
{ |
{ |
580 |
stash->currentDie += aDieInfo.length; |
stash->currentDie += aDieInfo.length; |
581 |
} |
} |
582 |
|
|
583 |
return false; |
return FALSE; |
584 |
} |
} |
585 |
|
|
586 |
/* EOF */ |
/* EOF */ |