summaryrefslogtreecommitdiff
path: root/bfd/dwarf2.c
diff options
context:
space:
mode:
authorFred Fish <fnf@specifix.com>2005-05-23 17:44:55 +0000
committerFred Fish <fnf@specifix.com>2005-05-23 17:44:55 +0000
commit4ab527b0538fcb65673a93dc775c39a2e7ccb6d7 (patch)
tree10216a538b0538a2d537617d800ed08d565bb44f /bfd/dwarf2.c
parentcaa0503690d27cbcd6fbc1a09caa44ba9f49e29f (diff)
downloadbinutils-gdb-4ab527b0538fcb65673a93dc775c39a2e7ccb6d7.tar.gz
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.c84
1 files changed, 80 insertions, 4 deletions
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 365758a2c49..32f0b4443d0 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)
{