#include "sysdep.h"
#include "bfd.h"
#include "libiberty.h"
+#include "demangle.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "dwarf2.h"
#include "hashtab.h"
+#include "splay-tree.h"
/* The data in the .debug_line statement prologue looks like this. */
return &leaf->head;
}
+struct addr_range
+{
+ bfd_byte *start;
+ bfd_byte *end;
+};
+
+/* Return true if address range do intersect. */
+
+static bool
+addr_range_intersects (struct addr_range *r1, struct addr_range *r2)
+{
+ return (r1->start <= r2->start && r2->start < r1->end)
+ || (r1->start <= (r2->end - 1) && (r2->end - 1) < r1->end);
+}
+
+/* Compare function for splay tree of addr_ranges. */
+
+static int
+splay_tree_compare_addr_range (splay_tree_key xa, splay_tree_key xb)
+{
+ struct addr_range *r1 = (struct addr_range *) xa;
+ struct addr_range *r2 = (struct addr_range *) xb;
+
+ if (addr_range_intersects (r1, r2) || addr_range_intersects (r2, r1))
+ return 0;
+ else if (r1->end <= r2->start)
+ return -1;
+ else
+ return 1;
+}
+
+/* Splay tree release function for keys (addr_range). */
+
+static void
+splay_tree_free_addr_range (splay_tree_key key)
+{
+ free ((struct addr_range *)key);
+}
+
struct dwarf2_debug_file
{
/* The actual bfd from which debug info was loaded. Might be
/* Root of a trie to map addresses to compilation units. */
struct trie_node *trie_root;
+
+ /* Splay tree to map info_ptr address to compilation units. */
+ splay_tree comp_unit_tree;
};
struct dwarf2_debug
{
bfd_size_type amt;
asection *msec;
- ufile_ptr filesize;
msec = bfd_get_section_by_name (abfd, section_name);
if (msec == NULL)
return false;
}
- amt = bfd_get_section_limit_octets (abfd, msec);
- filesize = bfd_get_file_size (abfd);
- /* PR 28834: A compressed debug section could well decompress to a size
- larger than the file, so we choose an arbitrary modifier of 10x in
- the test below. If this ever turns out to be insufficient, it can
- be changed by a future update. */
- if (amt >= filesize * 10)
+ if (_bfd_section_size_insane (abfd, msec))
{
/* PR 26946 */
- _bfd_error_handler (_("DWARF error: section %s is larger than 10x its filesize! (0x%lx vs 0x%lx)"),
- section_name, (long) amt, (long) filesize);
- bfd_set_error (bfd_error_bad_value);
+ _bfd_error_handler (_("DWARF error: section %s is too big"),
+ section_name);
return false;
}
+ amt = bfd_get_section_limit_octets (abfd, msec);
*section_size = amt;
/* Paranoia - alloc one extra so that we can make sure a string
section is NUL terminated. */
&file->dwarf_addr_buffer, &file->dwarf_addr_size))
return 0;
- if (_bfd_mul_overflow (idx, unit->offset_size, &offset))
+ if (_bfd_mul_overflow (idx, unit->addr_size, &offset))
return 0;
offset += unit->dwarf_addr_offset;
info_ptr = file->dwarf_addr_buffer + offset;
- if (unit->offset_size == 4)
+ if (unit->addr_size == 4)
return bfd_get_32 (unit->abfd, info_ptr);
- else if (unit->offset_size == 8)
+ else if (unit->addr_size == 8)
return bfd_get_64 (unit->abfd, info_ptr);
else
return 0;
return info_ptr;
}
-/* Return whether DW_AT_name will return the same as DW_AT_linkage_name
- for a function. */
+/* Return mangling style given LANG. */
-static bool
-non_mangled (int lang)
+static int
+mangle_style (int lang)
{
switch (lang)
{
+ case DW_LANG_Ada83:
+ case DW_LANG_Ada95:
+ return DMGL_GNAT;
+
+ case DW_LANG_C_plus_plus:
+ case DW_LANG_C_plus_plus_03:
+ case DW_LANG_C_plus_plus_11:
+ case DW_LANG_C_plus_plus_14:
+ return DMGL_GNU_V3;
+
+ case DW_LANG_Java:
+ return DMGL_JAVA;
+
+ case DW_LANG_D:
+ return DMGL_DLANG;
+
+ case DW_LANG_Rust:
+ case DW_LANG_Rust_old:
+ return DMGL_RUST;
+
default:
- return false;
+ return DMGL_AUTO;
case DW_LANG_C89:
case DW_LANG_C:
- case DW_LANG_Ada83:
case DW_LANG_Cobol74:
case DW_LANG_Cobol85:
case DW_LANG_Fortran77:
case DW_LANG_Pascal83:
- case DW_LANG_C99:
- case DW_LANG_Ada95:
case DW_LANG_PLI:
+ case DW_LANG_C99:
case DW_LANG_UPC:
case DW_LANG_C11:
case DW_LANG_Mips_Assembler:
- return true;
+ case DW_LANG_Upc:
+ case DW_LANG_HP_Basic91:
+ case DW_LANG_HP_IMacro:
+ case DW_LANG_HP_Assembler:
+ return 0;
}
}
unsigned int num_files;
unsigned int num_dirs;
unsigned int num_sequences;
+ bool use_dir_and_file_0;
char * comp_dir;
char ** dirs;
struct fileinfo* files;
bool is_linkage;
const char *name;
struct arange arange;
- /* Where the symbol is defined. */
- asection *sec;
/* The offset of the funcinfo from the start of the unit. */
uint64_t unit_offset;
};
/* The type of this variable. */
int tag;
/* The name of the variable, if it has one. */
- char *name;
+ const char *name;
/* The address of the variable. */
bfd_vma addr;
- /* Where the symbol is defined. */
- asection *sec;
/* Is this a stack variable? */
bool stack;
};
{
char *filename;
- if (table == NULL || file - 1 >= table->num_files)
+ /* Pre DWARF-5 entry 0 in the directory and filename tables was not used.
+ So in order to save space in the tables used here the info for, eg
+ directory 1 is stored in slot 0 of the directory table, directory 2
+ in slot 1 and so on.
+
+ Starting with DWARF-5 the 0'th entry is used so there is a one to one
+ mapping between DWARF slots and internal table entries. */
+ if (! table->use_dir_and_file_0)
{
- /* FILE == 0 means unknown. */
- if (file)
- _bfd_error_handler
- (_("DWARF error: mangled line number section (bad file number)"));
+ /* Pre DWARF-5, FILE == 0 means unknown. */
+ if (file == 0)
+ return strdup ("<unknown>");
+ -- file;
+ }
+
+ if (table == NULL || file >= table->num_files)
+ {
+ _bfd_error_handler
+ (_("DWARF error: mangled line number section (bad file number)"));
return strdup ("<unknown>");
}
- filename = table->files[file - 1].name;
+ filename = table->files[file].name;
+
if (filename == NULL)
return strdup ("<unknown>");
char *name;
size_t len;
- if (table->files[file - 1].dir
+ if (table->files[file].dir
/* PR 17512: file: 0317e960. */
- && table->files[file - 1].dir <= table->num_dirs
+ && table->files[file].dir
+ <= (table->use_dir_and_file_0 ? table->num_dirs - 1 : table->num_dirs)
/* PR 17512: file: 7f3d2e4b. */
&& table->dirs != NULL)
- subdir_name = table->dirs[table->files[file - 1].dir - 1];
+ {
+ if (table->use_dir_and_file_0)
+ subdir_name = table->dirs[table->files[file].dir];
+ else
+ subdir_name = table->dirs[table->files[file].dir - 1];
+ }
if (!subdir_name || !IS_ABSOLUTE_PATH (subdir_name))
dir_name = table->comp_dir;
/* Check whether [low1, high1) can be combined with [low2, high2),
i.e., they touch or overlap. */
-static bool ranges_overlap (bfd_vma low1,
- bfd_vma high1,
- bfd_vma low2,
- bfd_vma high2)
+
+static bool
+ranges_overlap (bfd_vma low1,
+ bfd_vma high1,
+ bfd_vma low2,
+ bfd_vma high2)
{
if (low1 == low2 || high1 == high2)
return true;
/* Insert an address range in the trie mapping addresses to compilation units.
Will return the new trie node (usually the same as is being sent in, but
in case of a leaf-to-interior conversion, or expansion of a leaf, it may be
- different), or NULL on failure.
- */
-static struct trie_node *insert_arange_in_trie(bfd *abfd,
- struct trie_node *trie,
- bfd_vma trie_pc,
- unsigned int trie_pc_bits,
- struct comp_unit *unit,
- bfd_vma low_pc,
- bfd_vma high_pc)
+ different), or NULL on failure. */
+
+static struct trie_node *
+insert_arange_in_trie (bfd *abfd,
+ struct trie_node *trie,
+ bfd_vma trie_pc,
+ unsigned int trie_pc_bits,
+ struct comp_unit *unit,
+ bfd_vma low_pc,
+ bfd_vma high_pc)
{
bfd_vma clamped_low_pc, clamped_high_pc;
int ch, from_ch, to_ch;
return trie;
}
-
static bool
arange_add (struct comp_unit *unit, struct arange *first_arange,
struct trie_node **trie_root, bfd_vma low_pc, bfd_vma high_pc)
}
}
- /* Skip the first "zero entry", which is the compilation dir/file. */
- if (datai != 0)
- if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
- return false;
+ if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
+ return false;
}
*bufp = buf;
if (!read_formatted_entries (unit, &line_ptr, line_end, table,
line_info_add_file_name))
goto fail;
+ table->use_dir_and_file_0 = true;
}
else
{
if (!line_info_add_file_name (table, cur_file, dir, xtime, size))
goto fail;
}
+ table->use_dir_and_file_0 = false;
}
/* Read the statement sequences until there's nothing left. */
/* State machine registers. */
bfd_vma address = 0;
unsigned char op_index = 0;
- char * filename = table->num_files ? concat_filename (table, 1) : NULL;
+ char * filename = NULL;
unsigned int line = 1;
unsigned int column = 0;
unsigned int discriminator = 0;
bfd_vma low_pc = (bfd_vma) -1;
bfd_vma high_pc = 0;
+ if (table->num_files)
+ {
+ if (table->use_dir_and_file_0)
+ filename = concat_filename (table, 0);
+ else
+ filename = concat_filename (table, 1);
+ }
+
/* Decode the table. */
while (!end_sequence && line_ptr < line_end)
{
struct lookup_funcinfo* lookup_funcinfo = NULL;
struct funcinfo* funcinfo = NULL;
struct funcinfo* best_fit = NULL;
- bfd_vma best_fit_len = 0;
+ bfd_vma best_fit_len = (bfd_vma) -1;
bfd_size_type low, high, mid, first;
struct arange *arange;
if (addr < arange->low || addr >= arange->high)
continue;
- if (!best_fit
- || arange->high - arange->low < best_fit_len
+ if (arange->high - arange->low < best_fit_len
/* The following comparison is designed to return the same
match as the previous algorithm for routines which have the
same best fit length. */
const char **filename_ptr,
unsigned int *linenumber_ptr)
{
- struct funcinfo* each_func;
+ struct funcinfo* each;
struct funcinfo* best_fit = NULL;
- bfd_vma best_fit_len = 0;
+ bfd_vma best_fit_len = (bfd_vma) -1;
struct arange *arange;
const char *name = bfd_asymbol_name (sym);
- asection *sec = bfd_asymbol_section (sym);
- for (each_func = unit->function_table;
- each_func;
- each_func = each_func->prev_func)
- {
- for (arange = &each_func->arange;
- arange;
- arange = arange->next)
+ for (each = unit->function_table; each; each = each->prev_func)
+ for (arange = &each->arange; arange; arange = arange->next)
+ if (addr >= arange->low
+ && addr < arange->high
+ && arange->high - arange->low < best_fit_len
+ && each->file
+ && each->name
+ && strstr (name, each->name) != NULL)
{
- if ((!each_func->sec || each_func->sec == sec)
- && addr >= arange->low
- && addr < arange->high
- && each_func->name
- && strcmp (name, each_func->name) == 0
- && (!best_fit
- || arange->high - arange->low < best_fit_len))
- {
- best_fit = each_func;
- best_fit_len = arange->high - arange->low;
- }
+ best_fit = each;
+ best_fit_len = arange->high - arange->low;
}
- }
if (best_fit)
{
- best_fit->sec = sec;
*filename_ptr = best_fit->file;
*linenumber_ptr = best_fit->line;
return true;
}
- else
- return false;
+
+ return false;
}
/* Variable table functions. */
const char **filename_ptr,
unsigned int *linenumber_ptr)
{
- const char *name = bfd_asymbol_name (sym);
- asection *sec = bfd_asymbol_section (sym);
struct varinfo* each;
+ const char *name = bfd_asymbol_name (sym);
for (each = unit->variable_table; each; each = each->prev_var)
- if (! each->stack
+ if (each->addr == addr
+ && !each->stack
&& each->file != NULL
&& each->name != NULL
- && each->addr == addr
- && (!each->sec || each->sec == sec)
- && strcmp (name, each->name) == 0)
+ && strstr (name, each->name) != NULL)
break;
if (each)
{
- each->sec = sec;
*filename_ptr = each->file;
*linenumber_ptr = each->line;
return true;
struct abbrev_info *abbrev;
uint64_t die_ref = attr_ptr->u.val;
struct attribute attr;
- const char *name = NULL;
if (recur_count == 100)
{
else
{
/* Check other CUs to see if they contain the abbrev. */
- struct comp_unit *u;
-
- for (u = unit->prev_unit; u != NULL; u = u->prev_unit)
- if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
- break;
-
- if (u == NULL)
- for (u = unit->next_unit; u != NULL; u = u->next_unit)
- if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
- break;
+ struct comp_unit *u = NULL;
+ struct addr_range range = { info_ptr, info_ptr };
+ splay_tree_node v = splay_tree_lookup (unit->file->comp_unit_tree,
+ (splay_tree_key)&range);
+ if (v != NULL)
+ u = (struct comp_unit *)v->value;
if (attr_ptr->form == DW_FORM_ref_addr)
while (u == NULL)
case DW_AT_name:
/* Prefer DW_AT_MIPS_linkage_name or DW_AT_linkage_name
over DW_AT_name. */
- if (name == NULL && is_str_form (&attr))
+ if (*pname == NULL && is_str_form (&attr))
{
- name = attr.u.str;
- if (non_mangled (unit->lang))
+ *pname = attr.u.str;
+ if (mangle_style (unit->lang) == 0)
*is_linkage = true;
}
break;
case DW_AT_specification:
if (is_int_form (&attr)
&& !find_abstract_instance (unit, &attr, recur_count + 1,
- &name, is_linkage,
+ pname, is_linkage,
filename_ptr, linenumber_ptr))
return false;
break;
non-string forms into these attributes. */
if (is_str_form (&attr))
{
- name = attr.u.str;
+ *pname = attr.u.str;
*is_linkage = true;
}
break;
if (!comp_unit_maybe_decode_line_info (unit))
return false;
if (is_int_form (&attr))
- *filename_ptr = concat_filename (unit->line_table,
- attr.u.val);
+ {
+ free (*filename_ptr);
+ *filename_ptr = concat_filename (unit->line_table,
+ attr.u.val);
+ }
break;
case DW_AT_decl_line:
if (is_int_form (&attr))
}
}
}
- *pname = name;
return true;
}
if (func->name == NULL && is_str_form (&attr))
{
func->name = attr.u.str;
- if (non_mangled (unit->lang))
+ if (mangle_style (unit->lang) == 0)
func->is_linkage = true;
}
break;
case DW_AT_decl_file:
if (is_int_form (&attr))
- func->file = concat_filename (unit->line_table,
- attr.u.val);
+ {
+ free (func->file);
+ func->file = concat_filename (unit->line_table,
+ attr.u.val);
+ }
break;
case DW_AT_decl_line:
case DW_AT_specification:
if (is_int_form (&attr) && attr.u.val)
{
- struct varinfo * spec_var;
-
- spec_var = lookup_var_by_offset (attr.u.val,
- unit->variable_table);
- if (spec_var == NULL)
+ bool is_linkage;
+ if (!find_abstract_instance (unit, &attr, 0,
+ &var->name,
+ &is_linkage,
+ &var->file,
+ &var->line))
{
_bfd_error_handler (_("DWARF error: could not find "
"variable specification "
(unsigned long) attr.u.val);
break;
}
-
- if (var->name == NULL)
- var->name = spec_var->name;
- if (var->file == NULL && spec_var->file != NULL)
- var->file = strdup (spec_var->file);
- if (var->line == 0)
- var->line = spec_var->line;
- if (var->sec == NULL)
- var->sec = spec_var->sec;
}
break;
case DW_AT_decl_file:
if (is_int_form (&attr))
- var->file = concat_filename (unit->line_table,
- attr.u.val);
+ {
+ free (var->file);
+ var->file = concat_filename (unit->line_table,
+ attr.u.val);
+ }
break;
case DW_AT_decl_line:
if (version < 5)
addr_size = read_1_byte (abfd, &info_ptr, end_ptr);
- if (unit_type == DW_UT_type)
+ switch (unit_type)
{
+ case DW_UT_type:
/* Skip type signature. */
info_ptr += 8;
/* Skip type offset. */
info_ptr += offset_size;
+ break;
+
+ case DW_UT_skeleton:
+ /* Skip DWO_id field. */
+ info_ptr += 8;
+ break;
+
+ default:
+ break;
}
if (addr_size > sizeof (bfd_vma))
{
look = debug_sections[debug_info].uncompressed_name;
msec = bfd_get_section_by_name (abfd, look);
- if (msec != NULL)
+ /* Testing SEC_HAS_CONTENTS is an anti-fuzzer measure. Of
+ course debug sections always have contents. */
+ if (msec != NULL && (msec->flags & SEC_HAS_CONTENTS) != 0)
return msec;
look = debug_sections[debug_info].compressed_name;
msec = bfd_get_section_by_name (abfd, look);
- if (msec != NULL)
+ if (msec != NULL && (msec->flags & SEC_HAS_CONTENTS) != 0)
return msec;
for (msec = abfd->sections; msec != NULL; msec = msec->next)
- if (startswith (msec->name, GNU_LINKONCE_INFO))
+ if ((msec->flags & SEC_HAS_CONTENTS) != 0
+ && startswith (msec->name, GNU_LINKONCE_INFO))
return msec;
return NULL;
for (msec = after_sec->next; msec != NULL; msec = msec->next)
{
+ if ((msec->flags & SEC_HAS_CONTENTS) == 0)
+ continue;
+
look = debug_sections[debug_info].uncompressed_name;
if (strcmp (msec->name, look) == 0)
return msec;
{
struct funcinfo* each_func;
struct funcinfo* best_fit = NULL;
- bfd_vma best_fit_len = 0;
+ bfd_vma best_fit_len = (bfd_vma) -1;
struct info_list_node *node;
struct arange *arange;
const char *name = bfd_asymbol_name (sym);
- asection *sec = bfd_asymbol_section (sym);
for (node = lookup_info_hash_table (hash_table, name);
node;
arange;
arange = arange->next)
{
- if ((!each_func->sec || each_func->sec == sec)
- && addr >= arange->low
+ if (addr >= arange->low
&& addr < arange->high
- && (!best_fit
- || arange->high - arange->low < best_fit_len))
+ && arange->high - arange->low < best_fit_len)
{
best_fit = each_func;
best_fit_len = arange->high - arange->low;
if (best_fit)
{
- best_fit->sec = sec;
*filename_ptr = best_fit->file;
*linenumber_ptr = best_fit->line;
return true;
const char **filename_ptr,
unsigned int *linenumber_ptr)
{
- const char *name = bfd_asymbol_name (sym);
- asection *sec = bfd_asymbol_section (sym);
struct varinfo* each;
struct info_list_node *node;
+ const char *name = bfd_asymbol_name (sym);
for (node = lookup_info_hash_table (hash_table, name);
node;
node = node->next)
{
each = (struct varinfo *) node->info;
- if (each->addr == addr
- && (!each->sec || each->sec == sec))
+ if (each->addr == addr)
{
- each->sec = sec;
*filename_ptr = each->file;
*linenumber_ptr = each->line;
return true;
msec;
msec = find_debug_info (debug_bfd, debug_sections, msec))
{
+ if (_bfd_section_size_insane (debug_bfd, msec))
+ return false;
/* Catch PR25070 testcase overflowing size calculation here. */
- if (total_size + msec->size < total_size
- || total_size + msec->size < msec->size)
+ if (total_size + msec->size < total_size)
{
bfd_set_error (bfd_error_no_memory);
return false;
info_ptr_unit, offset_size);
if (each)
{
+ if (file->comp_unit_tree == NULL)
+ file->comp_unit_tree
+ = splay_tree_new (splay_tree_compare_addr_range,
+ splay_tree_free_addr_range, NULL);
+
+ struct addr_range *r
+ = (struct addr_range *)bfd_malloc (sizeof (struct addr_range));
+ r->start = each->info_ptr_unit;
+ r->end = each->end_ptr;
+ splay_tree_node v = splay_tree_lookup (file->comp_unit_tree,
+ (splay_tree_key)r);
+ if (v != NULL || r->end <= r->start)
+ abort ();
+ splay_tree_insert (file->comp_unit_tree, (splay_tree_key)r,
+ (splay_tree_value)each);
+
if (file->all_comp_units)
file->all_comp_units->prev_unit = each;
else
return result;
}
-/* Find the source code location of SYMBOL. If SYMBOL is NULL
- then find the nearest source code location corresponding to
- the address SECTION + OFFSET.
- Returns 1 if the line is found without error and fills in
- FILENAME_PTR and LINENUMBER_PTR. In the case where SYMBOL was
- NULL the FUNCTIONNAME_PTR is also filled in.
- Returns 2 if partial information from _bfd_elf_find_function is
- returned (function and maybe file) by looking at symbols. DWARF2
- info is present but not regarding the requested code location.
- Returns 0 otherwise.
- SYMBOLS contains the symbol table for ABFD.
- DEBUG_SECTIONS contains the name of the dwarf debug sections. */
+/* See _bfd_dwarf2_find_nearest_line_with_alt. */
int
_bfd_dwarf2_find_nearest_line (bfd *abfd,
unsigned int *discriminator_ptr,
const struct dwarf_debug_section *debug_sections,
void **pinfo)
+{
+ return _bfd_dwarf2_find_nearest_line_with_alt
+ (abfd, NULL, symbols, symbol, section, offset, filename_ptr,
+ functionname_ptr, linenumber_ptr, discriminator_ptr, debug_sections,
+ pinfo);
+}
+
+/* Find the source code location of SYMBOL. If SYMBOL is NULL
+ then find the nearest source code location corresponding to
+ the address SECTION + OFFSET.
+ Returns 1 if the line is found without error and fills in
+ FILENAME_PTR and LINENUMBER_PTR. In the case where SYMBOL was
+ NULL the FUNCTIONNAME_PTR is also filled in.
+ Returns 2 if partial information from _bfd_elf_find_function is
+ returned (function and maybe file) by looking at symbols. DWARF2
+ info is present but not regarding the requested code location.
+ Returns 0 otherwise.
+ SYMBOLS contains the symbol table for ABFD.
+ DEBUG_SECTIONS contains the name of the dwarf debug sections.
+ If ALT_FILENAME is given, attempt to open the file and use it
+ as the .gnu_debugaltlink file. Otherwise this file will be
+ searched for when needed. */
+
+int
+_bfd_dwarf2_find_nearest_line_with_alt
+ (bfd *abfd,
+ const char *alt_filename,
+ asymbol **symbols,
+ asymbol *symbol,
+ asection *section,
+ bfd_vma offset,
+ const char **filename_ptr,
+ const char **functionname_ptr,
+ unsigned int *linenumber_ptr,
+ unsigned int *discriminator_ptr,
+ const struct dwarf_debug_section *debug_sections,
+ void **pinfo)
{
/* Read each compilation unit from the section .debug_info, and check
to see if it contains the address we are searching for. If yes,
stash = (struct dwarf2_debug *) *pinfo;
+ if (stash->alt.bfd_ptr == NULL && alt_filename != NULL)
+ {
+ bfd *alt_bfd = bfd_openr (alt_filename, NULL);
+
+ if (alt_bfd == NULL)
+ /* bfd_openr will have set the bfd_error. */
+ return false;
+ if (!bfd_check_format (alt_bfd, bfd_object))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ bfd_close (alt_bfd);
+ return false;
+ }
+
+ stash->alt.bfd_ptr = alt_bfd;
+ }
+
do_line = symbol != NULL;
if (do_line)
{
if (stash->info_hash_status == STASH_INFO_HASH_ON)
{
- found = stash_find_line_fast (stash, symbol, addr, filename_ptr,
- linenumber_ptr);
+ found = stash_find_line_fast (stash, symbol, addr,
+ filename_ptr, linenumber_ptr);
if (found)
goto done;
}
- else
- {
- /* Check the previously read comp. units first. */
- for (each = stash->f.all_comp_units; each; each = each->next_unit)
- if ((symbol->flags & BSF_FUNCTION) == 0
- || each->arange.high == 0
- || comp_unit_contains_address (each, addr))
- {
- found = comp_unit_find_line (each, symbol, addr, filename_ptr,
- linenumber_ptr);
- if (found)
- goto done;
- }
- }
+
+ /* Check the previously read comp. units first. */
+ for (each = stash->f.all_comp_units; each; each = each->next_unit)
+ if ((symbol->flags & BSF_FUNCTION) == 0
+ || each->arange.high == 0
+ || comp_unit_contains_address (each, addr))
+ {
+ found = comp_unit_find_line (each, symbol, addr, filename_ptr,
+ linenumber_ptr);
+ if (found)
+ goto done;
+ }
}
else
{
free (file->line_table->dirs);
}
htab_delete (file->abbrev_offsets);
+ if (file->comp_unit_tree != NULL)
+ splay_tree_delete (file->comp_unit_tree);
free (file->dwarf_line_str_buffer);
free (file->dwarf_str_buffer);