diff options
author | Fred Fish <fnf@specifix.com> | 2005-05-23 17:44:55 +0000 |
---|---|---|
committer | Fred Fish <fnf@specifix.com> | 2005-05-23 17:44:55 +0000 |
commit | 4ab527b0538fcb65673a93dc775c39a2e7ccb6d7 (patch) | |
tree | 10216a538b0538a2d537617d800ed08d565bb44f /bfd/dwarf2.c | |
parent | caa0503690d27cbcd6fbc1a09caa44ba9f49e29f (diff) | |
download | ppe42-binutils-4ab527b0538fcb65673a93dc775c39a2e7ccb6d7.tar.gz ppe42-binutils-4ab527b0538fcb65673a93dc775c39a2e7ccb6d7.zip |
Approved by nickc@redhat.com
2005-05-23 Fred Fish <fnf@specifixinc.com>
* dwarf2.c (struct dwarf2_debug): Add inliner_chain member.
(struct funcinfo): Add caller_func, caller_file, caller_line.
tag, and nesting_level members.
(lookup_address_in_function_table): Change first passed parameter
from "struct funcinfo *" to "struct comp_unit *".
(lookup_address_in_function_table): Dereference unit to find function
table.
(lookup_address_in_function_table): Traverse the function list to
create a chain of inlined functions back to the first non inlined
function.
(scan_unit_for_functions): Remember tag and nesting level. Handle
DW_AT_call_file and DW_AT_call_line.
(comp_unit_find_nearest_line): Adjust lookup_address_in_function_table
call to pass unit pointer instead of function table pointer. For
inlined functions, save pointer to the inliner chain.
(_bfd_dwarf2_find_nearest_line): Initialize inliner_chain to NULL.
(_bfd_dwarf2_find_inliner_info): New function that returns information
from the inliner chain after a call to bfd_find_nearest_line.
* bfd.c (bfd_find_inliner_info): Define using BFD_SEND.
* targets.c (BFD_JUMP_TABLE_SYMBOLS): Add entry for
NAME##_find_inliner_info.
(bfd_target): Add _bfd_find_inliner_info.
* bfd-in2.h: Regenerate.
* libbfd-in.h (_bfd_nosymbols_find_inliner_info): Define as
macro that always returns bfd_false.
(_bfd_dwarf2_find_inliner_info): Declare.
* libbfd.h: Regenerate.
* elf32-arm.c (elf32_arm_find_inliner_info): New function
that calls _bfd_dwarf2_find_inliner_info.
(bfd_elf32_find_inliner_info): Define to elf32_arm_find_inliner_info.
* elfxx-mips.c (_bfd_mips_elf_find_inliner_info): New function
that calls _bfd_dwarf2_find_inliner_info.
* elfxx-mips.h (_bfd_mips_elf_find_inliner_info): Declare.
* elfn32-mips.c (bfd_elf32_find_inliner_info): Define to
_bfd_mips_elf_find_inliner_info.
* elf64-mips.c (bfd_elf64_find_inliner_info): Ditto.
* elf32-mips.c (bfd_elf32_find_inliner_info): Ditto.
* elf.c (_bfd_elf_find_inliner_info): New function that calls
_bfd_dwarf2_find_inliner_info.
* elf-bfd.h (_bfd_elf_find_inliner_info): Declare.
* elfxx-target.h (bfd_elfNN_find_inliner_info): Define to
_bfd_elf_find_inliner_info.
* coffgen.c (coff_find_inliner_info): New function that
calls _bfd_dwarf2_find_inliner_info.
* libcoff-in.h (coff_find_inliner_info): Declare.
* libcoff.h: Regenerate.
* coff-rs6000.c (rs6000coff_vec): Add coff_find_inliner_info.
(pmac_xcoff_vec) Ditto.
* coff64-rs6000.c (rs6000coff64_vec): Ditto.
(aix5coff64_vec): Ditto.
* aout-target.h (MY_find_inliner_info): Define as
_bfd_nosymbols_find_inliner_info.
* aout-tic30.c (MY_find_inliner_info): Ditto.
* binary.c (binary_find_inliner_info): Ditto.
* i386msdos.c (msdos_find_inliner_info): Ditto.
* ihex.c (ihex_find_inliner_info): Ditto.
* libaout.h (aout_32_find_inliner_info): Ditto.
* libecoff.h (_bfd_ecoff_find_inliner_info): Ditto.
* mach-o.c (bfd_mach_o_find_inliner_info): Ditto.
* mmo.c (mmo_find_inliner_info): Ditto.
* nlm-target.h (nlm_find_inliner_info): Ditto.
* pef.c (bfd_pef_find_inliner_info): Ditto.
* ppcboot.c (ppcboot_find_inliner_info): Ditto.
* srec.c (srec_find_inliner_info): Ditto.
* tekhex.c (tekhex_find_inliner_info): Ditto.
* versados.c (versados_find_inliner_info): Ditto.
* xsym.c (bfd_sym_find_inliner_info): Ditto.
* ieee.c (ieee_find_inliner_info): New function that always
returns FALSE.
* oasys.c (oasys_find_inliner_info): Ditto.
* vms.c (vms_find_inliner_info): Ditto.
Diffstat (limited to 'bfd/dwarf2.c')
-rw-r--r-- | bfd/dwarf2.c | 84 |
1 files changed, 80 insertions, 4 deletions
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index 365758a2c4..32f0b4443d 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -118,6 +118,12 @@ struct dwarf2_debug /* Length of the loaded .debug_ranges section. */ unsigned long dwarf_ranges_size; + + /* If the most recent call to bfd_find_nearest_line was given an + address in an inlined function, preserve a pointer into the + calling chain for subsequent calls to bfd_find_inliner_info to + use. */ + struct funcinfo *inliner_chain; }; struct arange @@ -680,9 +686,19 @@ struct line_info_table struct line_info* lcl_head; /* local head; used in 'add_line_info' */ }; +/* Remember some information about each function. If the function is + inlined (DW_TAG_inlined_subroutine) it may have two additional + attributes, DW_AT_call_file and DW_AT_call_line, which specify the + source code location where this function was inlined. */ + struct funcinfo { - struct funcinfo *prev_func; + struct funcinfo *prev_func; /* Pointer to previous function in list of all functions */ + struct funcinfo *caller_func; /* Pointer to function one scope higher */ + char *caller_file; /* Source location file name where caller_func inlines this func */ + int caller_line; /* Source location line number where caller_func inlines this func */ + int tag; + int nesting_level; char *name; struct arange arange; }; @@ -1340,7 +1356,7 @@ read_debug_ranges (struct comp_unit *unit) depending upon them being ordered in TABLE by increasing range. */ static bfd_boolean -lookup_address_in_function_table (struct funcinfo *table, +lookup_address_in_function_table (struct comp_unit *unit, bfd_vma addr, struct funcinfo **function_ptr, const char **functionname_ptr) @@ -1349,7 +1365,7 @@ lookup_address_in_function_table (struct funcinfo *table, struct funcinfo* best_fit = NULL; struct arange *arange; - for (each_func = table; + for (each_func = unit->function_table; each_func; each_func = each_func->prev_func) { @@ -1368,8 +1384,28 @@ lookup_address_in_function_table (struct funcinfo *table, if (best_fit) { + struct funcinfo* curr_func = best_fit; + *functionname_ptr = best_fit->name; *function_ptr = best_fit; + + /* If we found a match and it is a function that was inlined, + traverse the function list looking for the function at the + next higher scope and save a pointer to it for future use. + Note that because of the way the DWARF info is generated, and + the way we build the function list, the first function at the + next higher level is the one we want. */ + + for (each_func = best_fit -> prev_func; + each_func && (curr_func->tag == DW_TAG_inlined_subroutine); + each_func = each_func->prev_func) + { + if (each_func->nesting_level < curr_func->nesting_level) + { + curr_func->caller_func = each_func; + curr_func = each_func; + } + } return TRUE; } else @@ -1508,6 +1544,8 @@ scan_unit_for_functions (struct comp_unit *unit) { bfd_size_type amt = sizeof (struct funcinfo); func = bfd_zalloc (abfd, amt); + func->tag = abbrev->tag; + func->nesting_level = nesting_level; func->prev_func = unit->function_table; unit->function_table = func; } @@ -1522,6 +1560,14 @@ scan_unit_for_functions (struct comp_unit *unit) { switch (attr.name) { + case DW_AT_call_file: + func->caller_file = concat_filename (unit->line_table, attr.u.val); + break; + + case DW_AT_call_line: + func->caller_line = attr.u.val; + break; + case DW_AT_abstract_origin: func->name = find_abstract_instance_name (unit, attr.u.val); break; @@ -1796,8 +1842,10 @@ comp_unit_find_nearest_line (struct comp_unit *unit, } function = NULL; - func_p = lookup_address_in_function_table (unit->function_table, addr, + func_p = lookup_address_in_function_table (unit, addr, &function, functionname_ptr); + if (func_p && (function->tag == DW_TAG_inlined_subroutine)) + stash->inliner_chain = function; line_p = lookup_address_in_line_info_table (unit->line_table, addr, function, filename_ptr, linenumber_ptr); @@ -1954,6 +2002,8 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd, if (! stash->info_ptr) return FALSE; + stash->inliner_chain = NULL; + /* Check the previously read comp. units first. */ for (each = stash->all_comp_units; each; each = each->next_unit) if (comp_unit_contains_address (each, addr)) @@ -2047,6 +2097,32 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd, return FALSE; } +bfd_boolean +_bfd_dwarf2_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED, + const char **filename_ptr, + const char **functionname_ptr, + unsigned int *linenumber_ptr, + void **pinfo) +{ + struct dwarf2_debug *stash; + + stash = *pinfo; + if (stash) + { + struct funcinfo *func = stash->inliner_chain; + if (func && func->caller_func) + { + *filename_ptr = func->caller_file; + *functionname_ptr = func->caller_func->name; + *linenumber_ptr = func->caller_line; + stash->inliner_chain = func->caller_func; + return (TRUE); + } + } + + return (FALSE); +} + void _bfd_dwarf2_cleanup_debug_info (bfd *abfd) { |