Index: bfd/dwarf2.c |
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c |
index d31b84939ad47b29643b3d39627bd8d2e28470d9..4a904eafbb32edf70002423940e15359d817fc44 100644 |
--- a/bfd/dwarf2.c |
+++ b/bfd/dwarf2.c |
@@ -1,6 +1,5 @@ |
/* DWARF 2 support. |
- Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, |
- 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. |
+ Copyright 1994-2013 Free Software Foundation, Inc. |
Adapted from gdb/dwarf2read.c by Gavin Koch of Cygnus Solutions |
(gavin@cygnus.com). |
@@ -108,6 +107,16 @@ struct dwarf2_debug |
asection *sec; |
bfd_byte *sec_info_ptr; |
+ /* Support for alternate debug info sections created by the DWZ utility: |
+ This includes a pointer to an alternate bfd which contains *extra*, |
+ possibly duplicate debug sections, and pointers to the loaded |
+ .debug_str and .debug_info sections from this bfd. */ |
+ bfd * alt_bfd_ptr; |
+ bfd_byte * alt_dwarf_str_buffer; |
+ bfd_size_type alt_dwarf_str_size; |
+ bfd_byte * alt_dwarf_info_buffer; |
+ bfd_size_type alt_dwarf_info_size; |
+ |
/* A pointer to the memory block allocated for info_ptr. Neither |
info_ptr nor sec_info_ptr are guaranteed to stay pointing to the |
beginning of the malloc block. This is used only to free the |
@@ -173,6 +182,9 @@ struct dwarf2_debug |
#define STASH_INFO_HASH_OFF 0 |
#define STASH_INFO_HASH_ON 1 |
#define STASH_INFO_HASH_DISABLED 2 |
+ |
+ /* True if we opened bfd_ptr. */ |
+ bfd_boolean close_on_cleanup; |
}; |
struct arange |
@@ -287,6 +299,7 @@ const struct dwarf_debug_section dwarf_debug_sections[] = |
{ ".debug_aranges", ".zdebug_aranges" }, |
{ ".debug_frame", ".zdebug_frame" }, |
{ ".debug_info", ".zdebug_info" }, |
+ { ".debug_info", ".zdebug_info" }, |
{ ".debug_line", ".zdebug_line" }, |
{ ".debug_loc", ".zdebug_loc" }, |
{ ".debug_macinfo", ".zdebug_macinfo" }, |
@@ -297,6 +310,7 @@ const struct dwarf_debug_section dwarf_debug_sections[] = |
{ ".debug_static_func", ".zdebug_static_func" }, |
{ ".debug_static_vars", ".zdebug_static_vars" }, |
{ ".debug_str", ".zdebug_str", }, |
+ { ".debug_str", ".zdebug_str", }, |
{ ".debug_types", ".zdebug_types" }, |
/* GNU DWARF 1 extensions */ |
{ ".debug_sfnames", ".zdebug_sfnames" }, |
@@ -309,12 +323,15 @@ const struct dwarf_debug_section dwarf_debug_sections[] = |
{ NULL, NULL }, |
}; |
+/* NB/ Numbers in this enum must match up with indicies |
+ into the dwarf_debug_sections[] array above. */ |
enum dwarf_debug_section_enum |
{ |
debug_abbrev = 0, |
debug_aranges, |
debug_frame, |
debug_info, |
+ debug_info_alt, |
debug_line, |
debug_loc, |
debug_macinfo, |
@@ -325,6 +342,7 @@ enum dwarf_debug_section_enum |
debug_static_func, |
debug_static_vars, |
debug_str, |
+ debug_str_alt, |
debug_types, |
debug_sfnames, |
debug_srcinfo, |
@@ -481,8 +499,8 @@ read_section (bfd * abfd, |
asection *msec; |
const char *section_name = sec->uncompressed_name; |
- /* read_section is a noop if the section has already been read. */ |
- if (!*section_buffer) |
+ /* The section may have already been read. */ |
+ if (*section_buffer == NULL) |
{ |
msec = bfd_get_section_by_name (abfd, section_name); |
if (! msec) |
@@ -623,6 +641,104 @@ read_indirect_string (struct comp_unit * unit, |
return str; |
} |
+/* Like read_indirect_string but uses a .debug_str located in |
+ an alternate filepointed to by the .gnu_debuglink section. |
+ Used to impement DW_FORM_GNU_strp_alt. */ |
+ |
+static char * |
+read_alt_indirect_string (struct comp_unit * unit, |
+ bfd_byte * buf, |
+ unsigned int * bytes_read_ptr) |
+{ |
+ bfd_uint64_t offset; |
+ struct dwarf2_debug *stash = unit->stash; |
+ char *str; |
+ |
+ if (unit->offset_size == 4) |
+ offset = read_4_bytes (unit->abfd, buf); |
+ else |
+ offset = read_8_bytes (unit->abfd, buf); |
+ |
+ *bytes_read_ptr = unit->offset_size; |
+ |
+ if (stash->alt_bfd_ptr == NULL) |
+ { |
+ bfd * debug_bfd; |
+ char * debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR); |
+ |
+ if (debug_filename == NULL) |
+ return NULL; |
+ |
+ if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL |
+ || ! bfd_check_format (debug_bfd, bfd_object)) |
+ { |
+ if (debug_bfd) |
+ bfd_close (debug_bfd); |
+ |
+ /* FIXME: Should we report our failure to follow the debuglink ? */ |
+ free (debug_filename); |
+ return NULL; |
+ } |
+ stash->alt_bfd_ptr = debug_bfd; |
+ } |
+ |
+ if (! read_section (unit->stash->alt_bfd_ptr, |
+ stash->debug_sections + debug_str_alt, |
+ NULL, /* FIXME: Do we need to load alternate symbols ? */ |
+ offset, |
+ &stash->alt_dwarf_str_buffer, |
+ &stash->alt_dwarf_str_size)) |
+ return NULL; |
+ |
+ str = (char *) stash->alt_dwarf_str_buffer + offset; |
+ if (*str == '\0') |
+ return NULL; |
+ |
+ return str; |
+} |
+ |
+/* Resolve an alternate reference from UNIT at OFFSET. |
+ Returns a pointer into the loaded alternate CU upon success |
+ or NULL upon failure. */ |
+ |
+static bfd_byte * |
+read_alt_indirect_ref (struct comp_unit * unit, |
+ bfd_uint64_t offset) |
+{ |
+ struct dwarf2_debug *stash = unit->stash; |
+ |
+ if (stash->alt_bfd_ptr == NULL) |
+ { |
+ bfd * debug_bfd; |
+ char * debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR); |
+ |
+ if (debug_filename == NULL) |
+ return FALSE; |
+ |
+ if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL |
+ || ! bfd_check_format (debug_bfd, bfd_object)) |
+ { |
+ if (debug_bfd) |
+ bfd_close (debug_bfd); |
+ |
+ /* FIXME: Should we report our failure to follow the debuglink ? */ |
+ free (debug_filename); |
+ return NULL; |
+ } |
+ stash->alt_bfd_ptr = debug_bfd; |
+ } |
+ |
+ if (! read_section (unit->stash->alt_bfd_ptr, |
+ stash->debug_sections + debug_info_alt, |
+ NULL, /* FIXME: Do we need to load alternate symbols ? */ |
+ offset, |
+ &stash->alt_dwarf_info_buffer, |
+ &stash->alt_dwarf_info_size)) |
+ return NULL; |
+ |
+ return stash->alt_dwarf_info_buffer + offset; |
+} |
+ |
static bfd_uint64_t |
read_address (struct comp_unit *unit, bfd_byte *buf) |
{ |
@@ -826,6 +942,7 @@ read_attribute_value (struct attribute *attr, |
attr->u.val = read_address (unit, info_ptr); |
info_ptr += unit->addr_size; |
break; |
+ case DW_FORM_GNU_ref_alt: |
case DW_FORM_sec_offset: |
if (unit->offset_size == 4) |
attr->u.val = read_4_bytes (unit->abfd, info_ptr); |
@@ -875,6 +992,10 @@ read_attribute_value (struct attribute *attr, |
attr->u.str = read_indirect_string (unit, info_ptr, &bytes_read); |
info_ptr += bytes_read; |
break; |
+ case DW_FORM_GNU_strp_alt: |
+ attr->u.str = read_alt_indirect_string (unit, info_ptr, &bytes_read); |
+ info_ptr += bytes_read; |
+ break; |
case DW_FORM_exprloc: |
case DW_FORM_block: |
amt = sizeof (struct dwarf_block); |
@@ -947,7 +1068,7 @@ read_attribute_value (struct attribute *attr, |
info_ptr = read_attribute_value (attr, form, unit, info_ptr); |
break; |
default: |
- (*_bfd_error_handler) (_("Dwarf Error: Invalid or unhandled FORM value: %u."), |
+ (*_bfd_error_handler) (_("Dwarf Error: Invalid or unhandled FORM value: %#x."), |
form); |
bfd_set_error (bfd_error_bad_value); |
return NULL; |
@@ -980,6 +1101,7 @@ struct line_info |
char *filename; |
unsigned int line; |
unsigned int column; |
+ unsigned int discriminator; |
unsigned char op_index; |
unsigned char end_sequence; /* End of (sequential) code sequence. */ |
}; |
@@ -1080,6 +1202,7 @@ add_line_info (struct line_info_table *table, |
char *filename, |
unsigned int line, |
unsigned int column, |
+ unsigned int discriminator, |
int end_sequence) |
{ |
bfd_size_type amt = sizeof (struct line_info); |
@@ -1095,6 +1218,7 @@ add_line_info (struct line_info_table *table, |
info->op_index = op_index; |
info->line = line; |
info->column = column; |
+ info->discriminator = discriminator; |
info->end_sequence = end_sequence; |
if (filename && filename[0]) |
@@ -1573,6 +1697,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) |
char * filename = table->num_files ? concat_filename (table, 1) : NULL; |
unsigned int line = 1; |
unsigned int column = 0; |
+ unsigned int discriminator = 0; |
int is_stmt = lh.default_is_stmt; |
int end_sequence = 0; |
/* eraxxon@alumni.rice.edu: Against the DWARF2 specs, some |
@@ -1607,8 +1732,9 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) |
line += lh.line_base + (adj_opcode % lh.line_range); |
/* Append row to matrix using current values. */ |
if (!add_line_info (table, address, op_index, filename, |
- line, column, 0)) |
+ line, column, discriminator, 0)) |
goto line_fail; |
+ discriminator = 0; |
if (address < low_pc) |
low_pc = address; |
if (address > high_pc) |
@@ -1626,9 +1752,10 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) |
{ |
case DW_LNE_end_sequence: |
end_sequence = 1; |
- if (!add_line_info (table, address, op_index, filename, |
- line, column, end_sequence)) |
+ if (!add_line_info (table, address, op_index, filename, line, |
+ column, discriminator, end_sequence)) |
goto line_fail; |
+ discriminator = 0; |
if (address < low_pc) |
low_pc = address; |
if (address > high_pc) |
@@ -1668,7 +1795,8 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) |
table->num_files++; |
break; |
case DW_LNE_set_discriminator: |
- (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read); |
+ discriminator = |
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read); |
line_ptr += bytes_read; |
break; |
case DW_LNE_HP_source_file_correlation: |
@@ -1686,8 +1814,9 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) |
break; |
case DW_LNS_copy: |
if (!add_line_info (table, address, op_index, |
- filename, line, column, 0)) |
+ filename, line, column, discriminator, 0)) |
goto line_fail; |
+ discriminator = 0; |
if (address < low_pc) |
low_pc = address; |
if (address > high_pc) |
@@ -1780,15 +1909,18 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) |
return NULL; |
} |
-/* If ADDR is within TABLE set the output parameters and return TRUE, |
- otherwise return FALSE. The output parameters, FILENAME_PTR and |
- LINENUMBER_PTR, are pointers to the objects to be filled in. */ |
+/* If ADDR is within TABLE set the output parameters and return the |
+ range of addresses covered by the entry used to fill them out. |
+ Otherwise set * FILENAME_PTR to NULL and return 0. |
+ The parameters FILENAME_PTR, LINENUMBER_PTR and DISCRIMINATOR_PTR |
+ are pointers to the objects to be filled in. */ |
-static bfd_boolean |
+static bfd_vma |
lookup_address_in_line_info_table (struct line_info_table *table, |
bfd_vma addr, |
const char **filename_ptr, |
- unsigned int *linenumber_ptr) |
+ unsigned int *linenumber_ptr, |
+ unsigned int *discriminator_ptr) |
{ |
struct line_sequence *seq = NULL; |
struct line_info *each_line; |
@@ -1823,12 +1955,14 @@ lookup_address_in_line_info_table (struct line_info_table *table, |
{ |
*filename_ptr = each_line->filename; |
*linenumber_ptr = each_line->line; |
- return TRUE; |
+ if (discriminator_ptr) |
+ *discriminator_ptr = each_line->discriminator; |
+ return seq->last_line->address - seq->low_pc; |
} |
} |
*filename_ptr = NULL; |
- return FALSE; |
+ return 0; |
} |
/* Read in the .debug_ranges section for future reference. */ |
@@ -1844,10 +1978,10 @@ read_debug_ranges (struct comp_unit *unit) |
/* Function table functions. */ |
-/* If ADDR is within TABLE, set FUNCTIONNAME_PTR, and return TRUE. |
- Note that we need to find the function that has the smallest |
- range that contains ADDR, to handle inlined functions without |
- depending upon them being ordered in TABLE by increasing range. */ |
+/* If ADDR is within UNIT's function tables, set FUNCTIONNAME_PTR, and return |
+ TRUE. Note that we need to find the function that has the smallest range |
+ that contains ADDR, to handle inlined functions without depending upon |
+ them being ordered in TABLE by increasing range. */ |
static bfd_boolean |
lookup_address_in_function_table (struct comp_unit *unit, |
@@ -1982,7 +2116,7 @@ find_abstract_instance_name (struct comp_unit *unit, |
struct abbrev_info *abbrev; |
bfd_uint64_t die_ref = attr_ptr->u.val; |
struct attribute attr; |
- char *name = 0; |
+ char *name = NULL; |
/* DW_FORM_ref_addr can reference an entry in a different CU. It |
is an offset from the .debug_info section, not the current CU. */ |
@@ -1995,8 +2129,20 @@ find_abstract_instance_name (struct comp_unit *unit, |
info_ptr = unit->sec_info_ptr + die_ref; |
} |
- else |
+ else if (attr_ptr->form == DW_FORM_GNU_ref_alt) |
+ { |
+ info_ptr = read_alt_indirect_ref (unit, die_ref); |
+ if (info_ptr == NULL) |
+ { |
+ (*_bfd_error_handler) |
+ (_("Dwarf Error: Unable to read alt ref %u."), die_ref); |
+ bfd_set_error (bfd_error_bad_value); |
+ return name; |
+ } |
+ } |
+ else |
info_ptr = unit->info_ptr_unit + die_ref; |
+ |
abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); |
info_ptr += bytes_read; |
@@ -2543,18 +2689,18 @@ comp_unit_contains_address (struct comp_unit *unit, bfd_vma addr) |
FUNCTIONNAME_PTR, and LINENUMBER_PTR, are pointers to the objects |
to be filled in. |
- Return TRUE if UNIT contains ADDR, and no errors were encountered; |
- FALSE otherwise. */ |
+ Returns the range of addresses covered by the entry that was used |
+ to fill in *LINENUMBER_PTR or 0 if it was not filled in. */ |
-static bfd_boolean |
+static bfd_vma |
comp_unit_find_nearest_line (struct comp_unit *unit, |
bfd_vma addr, |
const char **filename_ptr, |
const char **functionname_ptr, |
unsigned int *linenumber_ptr, |
+ unsigned int *discriminator_ptr, |
struct dwarf2_debug *stash) |
{ |
- bfd_boolean line_p; |
bfd_boolean func_p; |
struct funcinfo *function; |
@@ -2590,10 +2736,11 @@ comp_unit_find_nearest_line (struct comp_unit *unit, |
&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, |
- filename_ptr, |
- linenumber_ptr); |
- return line_p || func_p; |
+ |
+ return lookup_address_in_line_info_table (unit->line_table, addr, |
+ filename_ptr, |
+ linenumber_ptr, |
+ discriminator_ptr); |
} |
/* Check to see if line info is already decoded in a comp_unit. |
@@ -3193,6 +3340,7 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, |
if (! stash) |
return FALSE; |
stash->debug_sections = debug_sections; |
+ stash->syms = symbols; |
*pinfo = stash; |
@@ -3222,7 +3370,9 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, |
free (debug_filename); |
return FALSE; |
} |
+ stash->close_on_cleanup = TRUE; |
} |
+ stash->bfd_ptr = debug_bfd; |
/* There can be more than one DWARF2 info section in a BFD these |
days. First handle the easy case when there's only one. If |
@@ -3280,9 +3430,6 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, |
stash->info_ptr_end = stash->info_ptr + total_size; |
stash->sec = find_debug_info (debug_bfd, debug_sections, NULL); |
stash->sec_info_ptr = stash->info_ptr; |
- stash->syms = symbols; |
- stash->bfd_ptr = debug_bfd; |
- |
return TRUE; |
} |
@@ -3308,6 +3455,7 @@ find_line (bfd *abfd, |
const char **filename_ptr, |
const char **functionname_ptr, |
unsigned int *linenumber_ptr, |
+ unsigned int *discriminator_ptr, |
unsigned int addr_size, |
void **pinfo) |
{ |
@@ -3323,13 +3471,15 @@ find_line (bfd *abfd, |
/* What address are we looking for? */ |
bfd_vma addr; |
struct comp_unit* each; |
- bfd_vma found = FALSE; |
+ bfd_boolean found = FALSE; |
bfd_boolean do_line; |
*filename_ptr = NULL; |
if (functionname_ptr != NULL) |
*functionname_ptr = NULL; |
*linenumber_ptr = 0; |
+ if (discriminator_ptr) |
+ *discriminator_ptr = 0; |
if (! _bfd_dwarf2_slurp_debug_info (abfd, NULL, |
debug_sections, symbols, pinfo)) |
@@ -3411,17 +3561,56 @@ find_line (bfd *abfd, |
} |
else |
{ |
+ bfd_vma min_range = (bfd_vma) -1; |
+ const char * local_filename = NULL; |
+ const char * local_functionname = NULL; |
+ unsigned int local_linenumber = 0; |
+ unsigned int local_discriminator = 0; |
+ |
for (each = stash->all_comp_units; each; each = each->next_unit) |
{ |
+ bfd_vma range = (bfd_vma) -1; |
+ |
found = ((each->arange.high == 0 |
|| comp_unit_contains_address (each, addr)) |
- && comp_unit_find_nearest_line (each, addr, |
- filename_ptr, |
- functionname_ptr, |
- linenumber_ptr, |
- stash)); |
+ && (range = comp_unit_find_nearest_line (each, addr, |
+ & local_filename, |
+ & local_functionname, |
+ & local_linenumber, |
+ & local_discriminator, |
+ stash)) != 0); |
if (found) |
- goto done; |
+ { |
+ /* PRs 15935 15994: Bogus debug information may have provided us |
+ with an erroneous match. We attempt to counter this by |
+ selecting the match that has the smallest address range |
+ associated with it. (We are assuming that corrupt debug info |
+ will tend to result in extra large address ranges rather than |
+ extra small ranges). |
+ |
+ This does mean that we scan through all of the CUs associated |
+ with the bfd each time this function is called. But this does |
+ have the benefit of producing consistent results every time the |
+ function is called. */ |
+ if (range <= min_range) |
+ { |
+ if (filename_ptr && local_filename) |
+ * filename_ptr = local_filename; |
+ if (functionname_ptr && local_functionname) |
+ * functionname_ptr = local_functionname; |
+ if (discriminator_ptr && local_discriminator) |
+ * discriminator_ptr = local_discriminator; |
+ if (local_linenumber) |
+ * linenumber_ptr = local_linenumber; |
+ min_range = range; |
+ } |
+ } |
+ } |
+ |
+ if (* linenumber_ptr) |
+ { |
+ found = TRUE; |
+ goto done; |
} |
} |
@@ -3488,10 +3677,10 @@ find_line (bfd *abfd, |
stash->all_comp_units->prev_unit = each; |
else |
stash->last_comp_unit = each; |
- |
+ |
each->next_unit = stash->all_comp_units; |
stash->all_comp_units = each; |
- |
+ |
/* DW_AT_low_pc and DW_AT_high_pc are optional for |
compilation units. If we don't have them (i.e., |
unit->high == 0), we need to consult the line info table |
@@ -3512,7 +3701,8 @@ find_line (bfd *abfd, |
filename_ptr, |
functionname_ptr, |
linenumber_ptr, |
- stash)); |
+ discriminator_ptr, |
+ stash)) > 0; |
if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr) |
== stash->sec->size) |
@@ -3546,12 +3736,13 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd, |
const char **filename_ptr, |
const char **functionname_ptr, |
unsigned int *linenumber_ptr, |
+ unsigned int *discriminator_ptr, |
unsigned int addr_size, |
void **pinfo) |
{ |
return find_line (abfd, debug_sections, section, offset, NULL, symbols, |
- filename_ptr, functionname_ptr, linenumber_ptr, addr_size, |
- pinfo); |
+ filename_ptr, functionname_ptr, linenumber_ptr, |
+ discriminator_ptr, addr_size, pinfo); |
} |
/* The DWARF2 version of find_line. |
@@ -3563,11 +3754,13 @@ _bfd_dwarf2_find_line (bfd *abfd, |
asymbol *symbol, |
const char **filename_ptr, |
unsigned int *linenumber_ptr, |
+ unsigned int *discriminator_ptr, |
unsigned int addr_size, |
void **pinfo) |
{ |
return find_line (abfd, dwarf_debug_sections, NULL, 0, symbol, symbols, |
- filename_ptr, NULL, linenumber_ptr, addr_size, pinfo); |
+ filename_ptr, NULL, linenumber_ptr, discriminator_ptr, |
+ addr_size, pinfo); |
} |
bfd_boolean |
@@ -3600,7 +3793,7 @@ _bfd_dwarf2_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED, |
void |
_bfd_dwarf2_cleanup_debug_info (bfd *abfd, void **pinfo) |
{ |
- struct dwarf2_debug *stash = (struct dwarf2_debug *) *pinfo;; |
+ struct dwarf2_debug *stash = (struct dwarf2_debug *) *pinfo; |
struct comp_unit *each; |
if (abfd == NULL || stash == NULL) |
@@ -3668,4 +3861,12 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abfd, void **pinfo) |
free (stash->dwarf_ranges_buffer); |
if (stash->info_ptr_memory) |
free (stash->info_ptr_memory); |
+ if (stash->close_on_cleanup) |
+ bfd_close (stash->bfd_ptr); |
+ if (stash->alt_dwarf_str_buffer) |
+ free (stash->alt_dwarf_str_buffer); |
+ if (stash->alt_dwarf_info_buffer) |
+ free (stash->alt_dwarf_info_buffer); |
+ if (stash->alt_bfd_ptr) |
+ bfd_close (stash->alt_bfd_ptr); |
} |