binutils/SOURCES/binutils-Add-BFD-support-for-dwz-files.patch

2026 lines
64 KiB
Diff

From 99b06c600f0f5cb730cbdab9c3bb8b1f9317e0a1 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Sat, 30 Nov 2019 16:57:55 +1030
Subject: [PATCH] PR25230, dwarf2.c per file stash
This is just moving things around, in preparation for parsing alt
file debug_info.
PR 25230
* dwarf2.c (struct dwarf2_debug_file): New struct.
(struct dwarf2_debug): Delete fields now in dwarf2_debug_file.
Add f, alt fields.
(struct comp_unit): Add file field.
(read_indirect_string, read_indirect_line_string): Adjust to suit.
(read_alt_indirect_string, read_alt_indirect_ref): Likewise.
(read_debug_ranges, find_abstract_instance, read_rangelist): Likewise.
(_bfd_dwarf2_stash_syms, place_sections): Likewise.
(stash_maybe_update_info_hash_tablse): Likewise.
(stash_verify_info_hash_table): Likewise.
(_bfd_dwarf2_slurp_debug_info): Likewise.
(_bfd_dwarf2_find_symbol_bias): Likewise.
(_bfd_dwarf2_find_nearest_line): Likewise.
(_bfd_dwarf2_cleanup_debug_info): Likewise.
(read_abbrevs): Add file param and adjust. Update calls.
(stash_comp_unit): Likewise.
(decode_line_info): Delete stash param and adjust. Update calls.
(comp_unit_find_nearest_line): Likewise.
(comp_unit_maybe_decode_line_info): Likewise.
(comp_unit_find_line): Likewise.
(parse_comp_unit): Add file and info_ptr param and adjust. Update
calls.
From e63ef0954d02bec8ecb9cf7ff9fc14adc45e8010 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Mon, 2 Dec 2019 23:37:34 +1030
Subject: [PATCH] PR25230, addr2line fails on dwz output
This patch remedies the following DW_FORM_GNU_ref_alt related problem:
/* FIXME: Do we need to locate the correct CU, in a similar
fashion to the code in the DW_FORM_ref_addr case above ? */
Without the correct CU the wrong abbrevs are used, resulting in
errors and/or wrong file names.
There is scope for further work here. Parsing of CUs should be a two
step process, with the first stage just finding the bounds of the CU.
This would allow find_abstract_instance to quickly find the CU
referenced by DW_FORM_ref_addr or DW_FORM_GNU_ref_alt, then take the
second stage of CU parsing where abbrevs, ranges and suchlike consume
time and memory. As it is, we just process CUs from the start of
.debug_info until we find the one of interest. The testcase in the PR
takes 98G of virtual memory.
PR 25230
* dwarf2.c (struct dwarf2_debug_file): Add line_table and
abbrev_offsets.
(struct abbrev_offset_entry): New.
(hash_abbrev, eq_abbrev, del_abbrev): New functions.
(read_abbrevs): Check whether we have already read abbrevs at
given offset, and add new offset/abbrev to hash table.
(decode_line_info): Keep line table at offset zero in file struct.
Return this for a cu reusing the same dir/file list.
(find_abstract_instance): Find cu for DW_FORM_GNU_ref_alt.
(_bfd_dwarf2_slurp_debug_info): Create offset/abbrev hash tables.
(_bfd_dwarf2_cleanup_debug_info): Adjust deletion of lines and
abbrevs.
From e76790600aeba4939225eda32e59642ed2813ac8 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Tue, 26 Nov 2019 22:32:51 +1030
Subject: [PATCH] PR23652, Use symbols from debug bfd for
_bfd_elf_find_function
Sometimes DWARF info for a function is incomplete, and the function
can be retrieved by examining symbols. However, when separate debug
files are used it may be that the original file is completely
stripped of symbols. This patch teaches BFD to look at symbols from
the debug file in that case.
The patch also removes arm_elf_find_function, instead implementing
elf_backend_maybe_function_sym. arm_elf_find_function was written
before the generic _bfd_elf_find_function called maybe_function_sym.
aarch64 copied arm, so that file gets the same treatment. There is
some chance this will speed up arm and aarch64 lookup of function/line.
PR 23652
* dwarf2.c (_bfd_dwarf2_stash_syms): New function.
(_bfd_dwarf2_find_nearest_line): Use it here, passing syms to
_bfd_elf_find_function. Call _bfd_elf_find_function in cases
where _bfd_elf_find_nearest_line would do so.
* elf.c (_bfd_elf_find_nearest_line): Omit _bfd_elf_find_function
for dwarf2.
* elfxx-mips.c (_bfd_mips_elf_find_nearest_line): Similarly. Tidy.
* elf32-arm.c (elf32_arm_maybe_function_sym): New function.
(elf_backend_maybe_function_sym): Define.
(arm_elf_find_function, elf32_arm_find_nearest_line): Delete.
(bfd_elf32_find_nearest_line): Don't define.
* elfnn-aarch64.c (elfNN_aarch64_maybe_function_sym): New function.
(elf_backend_maybe_function_sym): Define.
(aarch64_elf_find_function, elfNN_aarch64_find_nearest_line): Delete.
(bfd_elfNN_find_nearest_line): Don't define.
---
--- binutils.orig/bfd/dwarf2.c 2025-03-19 14:50:47.471871607 +0000
+++ binutils-2.30/bfd/dwarf2.c 2025-03-19 16:49:27.152219426 +0000
@@ -35,6 +35,7 @@
#include "libbfd.h"
#include "elf-bfd.h"
#include "dwarf2.h"
+#include "hashtab.h"
/* The data in the .debug_line statement prologue looks like this. */
@@ -81,55 +82,23 @@ struct adjusted_section
bfd_vma adj_vma;
};
-struct dwarf2_debug
+struct dwarf2_debug_file
{
- /* A list of all previously read comp_units. */
- struct comp_unit *all_comp_units;
-
- /* Last comp unit in list above. */
- struct comp_unit *last_comp_unit;
+ /* The actual bfd from which debug info was loaded. Might be
+ different to orig_bfd because of gnu_debuglink sections. */
+ bfd *bfd_ptr;
- /* Names of the debug sections. */
- const struct dwarf_debug_section *debug_sections;
+ /* Pointer to the symbol table. */
+ asymbol **syms;
- /* The next unread compilation unit within the .debug_info section.
- Zero indicates that the .debug_info section has not been loaded
- into a buffer yet. */
+ /* The current info pointer for the .debug_info section being parsed. */
bfd_byte *info_ptr;
- /* Pointer to the end of the .debug_info section memory buffer. */
- bfd_byte *info_ptr_end;
+ /* A pointer to the memory block allocated for .debug_info sections. */
+ bfd_byte *dwarf_info_buffer;
- /* Pointer to the original bfd for which debug was loaded. This is what
- we use to compare and so check that the cached debug data is still
- valid - it saves having to possibly dereference the gnu_debuglink each
- time. */
- bfd *orig_bfd;
-
- /* Pointer to the bfd, section and address of the beginning of the
- section. The bfd might be different than expected because of
- gnu_debuglink sections. */
- bfd *bfd_ptr;
- 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. */
- bfd_byte *info_ptr_memory;
-
- /* Pointer to the symbol table. */
- asymbol **syms;
+ /* Length of the loaded .debug_info sections. */
+ bfd_size_type dwarf_info_size;
/* Pointer to the .debug_abbrev section loaded into memory. */
bfd_byte *dwarf_abbrev_buffer;
@@ -167,6 +136,31 @@ struct dwarf2_debug
/* Length of the loaded .debug_rnglists section. */
bfd_size_type dwarf_rnglists_size;
+ /* A list of all previously read comp_units. */
+ struct comp_unit *all_comp_units;
+
+ /* Last comp unit in list above. */
+ struct comp_unit *last_comp_unit;
+
+ /* Line table at line_offset zero. */
+ struct line_info_table *line_table;
+};
+
+struct dwarf2_debug
+{
+ /* Names of the debug sections. */
+ const struct dwarf_debug_section *debug_sections;
+
+ /* Per-file stuff. */
+ struct dwarf2_debug_file f;
+ struct dwarf2_debug_file alt;
+
+ /* Pointer to the original bfd for which debug was loaded. This is what
+ we use to compare and so check that the cached debug data is still
+ valid - it saves having to possibly dereference the gnu_debuglink each
+ time. */
+ bfd *orig_bfd;
+
/* 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
@@ -175,6 +169,8 @@ struct dwarf2_debug
/* Section VMAs at the time the stash was built. */
bfd_vma *sec_vma;
+ /* Number of sections in the SEC_VMA table. */
+ unsigned int sec_vma_count;
/* Number of sections whose VMA we must adjust. */
int adjusted_section_count;
@@ -279,8 +275,9 @@ struct comp_unit
/* A list of the variables found in this comp. unit. */
struct varinfo *variable_table;
- /* Pointer to dwarf2_debug structure. */
+ /* Pointers to dwarf2_debug structures. */
struct dwarf2_debug *stash;
+ struct dwarf2_debug_file *file;
/* DWARF format version for this unit - from unit header. */
int version;
@@ -352,7 +349,7 @@ const struct dwarf_debug_section dwarf_d
{ NULL, NULL },
};
-/* NB/ Numbers in this enum must match up with indicies
+/* NB/ Numbers in this enum must match up with indices
into the dwarf_debug_sections[] array above. */
enum dwarf_debug_section_enum
{
@@ -725,6 +722,7 @@ read_indirect_string (struct comp_unit *
{
bfd_uint64_t offset;
struct dwarf2_debug *stash = unit->stash;
+ struct dwarf2_debug_file *file = unit->file;
char *str;
if (buf + unit->offset_size > buf_end)
@@ -741,13 +739,13 @@ read_indirect_string (struct comp_unit *
*bytes_read_ptr = unit->offset_size;
if (! read_section (unit->abfd, &stash->debug_sections[debug_str],
- stash->syms, offset,
- &stash->dwarf_str_buffer, &stash->dwarf_str_size))
+ file->syms, offset,
+ &file->dwarf_str_buffer, &file->dwarf_str_size))
return NULL;
- if (offset >= stash->dwarf_str_size)
+ if (offset >= file->dwarf_str_size)
return NULL;
- str = (char *) stash->dwarf_str_buffer + offset;
+ str = (char *) file->dwarf_str_buffer + offset;
if (*str == '\0')
return NULL;
return str;
@@ -763,6 +761,7 @@ read_indirect_line_string (struct comp_u
{
bfd_uint64_t offset;
struct dwarf2_debug *stash = unit->stash;
+ struct dwarf2_debug_file *file = unit->file;
char *str;
if (buf + unit->offset_size > buf_end)
@@ -779,14 +778,14 @@ read_indirect_line_string (struct comp_u
*bytes_read_ptr = unit->offset_size;
if (! read_section (unit->abfd, &stash->debug_sections[debug_line_str],
- stash->syms, offset,
- &stash->dwarf_line_str_buffer,
- &stash->dwarf_line_str_size))
+ file->syms, offset,
+ &file->dwarf_line_str_buffer,
+ &file->dwarf_line_str_size))
return NULL;
- if (offset >= stash->dwarf_line_str_size)
+ if (offset >= file->dwarf_line_str_size)
return NULL;
- str = (char *) stash->dwarf_line_str_buffer + offset;
+ str = (char *) file->dwarf_line_str_buffer + offset;
if (*str == '\0')
return NULL;
return str;
@@ -819,7 +818,7 @@ read_alt_indirect_string (struct comp_un
*bytes_read_ptr = unit->offset_size;
- if (stash->alt_bfd_ptr == NULL)
+ if (stash->alt.bfd_ptr == NULL)
{
bfd * debug_bfd;
char * debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR);
@@ -837,20 +836,19 @@ read_alt_indirect_string (struct comp_un
free (debug_filename);
return NULL;
}
- stash->alt_bfd_ptr = debug_bfd;
+ stash->alt.bfd_ptr = debug_bfd;
}
- if (! read_section (unit->stash->alt_bfd_ptr,
+ 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))
+ stash->alt.syms, offset,
+ &stash->alt.dwarf_str_buffer,
+ &stash->alt.dwarf_str_size))
return NULL;
- if (offset >= stash->alt_dwarf_str_size)
+ if (offset >= stash->alt.dwarf_str_size)
return NULL;
- str = (char *) stash->alt_dwarf_str_buffer + offset;
+ str = (char *) stash->alt.dwarf_str_buffer + offset;
if (*str == '\0')
return NULL;
@@ -867,13 +865,13 @@ read_alt_indirect_ref (struct comp_unit
{
struct dwarf2_debug *stash = unit->stash;
- if (stash->alt_bfd_ptr == NULL)
+ 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;
+ return NULL;
if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
|| ! bfd_check_format (debug_bfd, bfd_object))
@@ -885,20 +883,19 @@ read_alt_indirect_ref (struct comp_unit
free (debug_filename);
return NULL;
}
- stash->alt_bfd_ptr = debug_bfd;
+ stash->alt.bfd_ptr = debug_bfd;
}
- if (! read_section (unit->stash->alt_bfd_ptr,
+ 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))
+ stash->alt.syms, offset,
+ &stash->alt.dwarf_info_buffer,
+ &stash->alt.dwarf_info_size))
return NULL;
- if (offset >= stash->alt_dwarf_info_size)
+ if (offset >= stash->alt.dwarf_info_size)
return NULL;
- return stash->alt_dwarf_info_buffer + offset;
+ return stash->alt.dwarf_info_buffer + offset;
}
static bfd_uint64_t
@@ -970,7 +967,8 @@ lookup_abbrev (unsigned int number, stru
in a hash table. */
static struct abbrev_info**
-read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
+read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash,
+ struct dwarf2_debug_file *file)
{
struct abbrev_info **abbrevs;
bfd_byte *abbrev_ptr;
@@ -981,11 +979,12 @@ read_abbrevs (bfd *abfd, bfd_uint64_t of
bfd_size_type amt;
if (! read_section (abfd, &stash->debug_sections[debug_abbrev],
- stash->syms, offset,
- &stash->dwarf_abbrev_buffer, &stash->dwarf_abbrev_size))
+ file->syms, offset,
+ &file->dwarf_abbrev_buffer,
+ &file->dwarf_abbrev_size))
return NULL;
- if (offset >= stash->dwarf_abbrev_size)
+ if (offset >= file->dwarf_abbrev_size)
return NULL;
amt = sizeof (struct abbrev_info*) * ABBREV_HASH_SIZE;
@@ -993,8 +992,8 @@ read_abbrevs (bfd *abfd, bfd_uint64_t of
if (abbrevs == NULL)
return NULL;
- abbrev_ptr = stash->dwarf_abbrev_buffer + offset;
- abbrev_end = stash->dwarf_abbrev_buffer + stash->dwarf_abbrev_size;
+ abbrev_ptr = file->dwarf_abbrev_buffer + offset;
+ abbrev_end = file->dwarf_abbrev_buffer + file->dwarf_abbrev_size;
abbrev_number = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
FALSE, abbrev_end);
abbrev_ptr += bytes_read;
@@ -1085,8 +1084,8 @@ read_abbrevs (bfd *abfd, bfd_uint64_t of
already read (which means we are about to read the abbreviations
for the next compile unit) or if the end of the abbreviation
table is reached. */
- if ((unsigned int) (abbrev_ptr - stash->dwarf_abbrev_buffer)
- >= stash->dwarf_abbrev_size)
+ if ((size_t) (abbrev_ptr - file->dwarf_abbrev_buffer)
+ >= file->dwarf_abbrev_size)
break;
abbrev_number = _bfd_safe_read_leb128 (abfd, abbrev_ptr,
&bytes_read, FALSE, abbrev_end);
@@ -2108,9 +2107,11 @@ read_formatted_entries (struct comp_unit
/* Decode the line number information for UNIT. */
static struct line_info_table*
-decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
+decode_line_info (struct comp_unit *unit)
{
bfd *abfd = unit->abfd;
+ struct dwarf2_debug *stash = unit->stash;
+ struct dwarf2_debug_file *file = unit->file;
struct line_info_table* table;
bfd_byte *line_ptr;
bfd_byte *line_end;
@@ -2121,39 +2122,24 @@ decode_line_info (struct comp_unit *unit
unsigned int exop_len;
bfd_size_type amt;
- if (! read_section (abfd, &stash->debug_sections[debug_line],
- stash->syms, unit->line_offset,
- &stash->dwarf_line_buffer, &stash->dwarf_line_size))
- return NULL;
+ if (unit->line_offset == 0 && file->line_table)
+ return file->line_table;
- amt = sizeof (struct line_info_table);
- table = (struct line_info_table *) bfd_alloc (abfd, amt);
- if (table == NULL)
+ if (! read_section (abfd, &stash->debug_sections[debug_line],
+ file->syms, unit->line_offset,
+ &file->dwarf_line_buffer, &file->dwarf_line_size))
return NULL;
- table->abfd = abfd;
- table->comp_dir = unit->comp_dir;
- table->num_files = 0;
- table->files = NULL;
-
- table->num_dirs = 0;
- table->dirs = NULL;
-
- table->num_sequences = 0;
- table->sequences = NULL;
-
- table->lcl_head = NULL;
-
- if (stash->dwarf_line_size < 16)
+ if (file->dwarf_line_size < 16)
{
_bfd_error_handler
(_("Dwarf Error: Line info section is too small (%Ld)"),
- stash->dwarf_line_size);
+ file->dwarf_line_size);
bfd_set_error (bfd_error_bad_value);
return NULL;
}
- line_ptr = stash->dwarf_line_buffer + unit->line_offset;
- line_end = stash->dwarf_line_buffer + stash->dwarf_line_size;
+ line_ptr = file->dwarf_line_buffer + unit->line_offset;
+ line_end = file->dwarf_line_buffer + file->dwarf_line_size;
/* Read in the prologue. */
lh.total_length = read_4_bytes (abfd, line_ptr, line_end);
@@ -2280,6 +2266,24 @@ decode_line_info (struct comp_unit *unit
line_ptr += 1;
}
+ amt = sizeof (struct line_info_table);
+ table = (struct line_info_table *) bfd_alloc (abfd, amt);
+ if (table == NULL)
+ return NULL;
+ table->abfd = abfd;
+ table->comp_dir = unit->comp_dir;
+
+ table->num_files = 0;
+ table->files = NULL;
+
+ table->num_dirs = 0;
+ table->dirs = NULL;
+
+ table->num_sequences = 0;
+ table->sequences = NULL;
+
+ table->lcl_head = NULL;
+
if (lh.version >= 5)
{
/* Read directory table. */
@@ -2479,16 +2483,16 @@ decode_line_info (struct comp_unit *unit
break;
case DW_LNS_set_file:
{
- unsigned int file;
+ unsigned int filenum;
/* The file and directory tables are 0
based, the references are 1 based. */
- file = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
+ filenum = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
FALSE, line_end);
line_ptr += bytes_read;
if (filename)
free (filename);
- filename = concat_filename (table, file);
+ filename = concat_filename (table, filenum);
break;
}
case DW_LNS_set_column:
@@ -2537,6 +2541,8 @@ decode_line_info (struct comp_unit *unit
free (filename);
}
+ if (unit->line_offset == 0)
+ file->line_table = table;
if (sort_line_sequences (table))
return table;
@@ -2633,11 +2639,12 @@ static bfd_boolean
read_debug_ranges (struct comp_unit * unit)
{
struct dwarf2_debug * stash = unit->stash;
+ struct dwarf2_debug_file *file = unit->file;
return read_section (unit->abfd, &stash->debug_sections[debug_ranges],
- stash->syms, 0,
- &stash->dwarf_ranges_buffer,
- &stash->dwarf_ranges_size);
+ file->syms, 0,
+ &file->dwarf_ranges_buffer,
+ &file->dwarf_ranges_size);
}
/* Read in the .debug_rnglists section for future reference. */
@@ -2646,11 +2653,12 @@ static bfd_boolean
read_debug_rnglists (struct comp_unit * unit)
{
struct dwarf2_debug *stash = unit->stash;
+ struct dwarf2_debug_file *file = unit->file;
return read_section (unit->abfd, stash->debug_sections + debug_rnglists,
- stash->syms, 0,
- & stash->dwarf_rnglists_buffer,
- & stash->dwarf_rnglists_size);
+ file->syms, 0,
+ & file->dwarf_rnglists_buffer,
+ & file->dwarf_rnglists_size);
}
/* Function table functions. */
@@ -2908,12 +2916,18 @@ lookup_symbol_in_variable_table (struct
return FALSE;
}
+static struct comp_unit *stash_comp_unit (struct dwarf2_debug *,
+ struct dwarf2_debug_file *);
+static bfd_boolean comp_unit_maybe_decode_line_info (struct comp_unit *);
+
static bfd_boolean
-find_abstract_instance_name (struct comp_unit *unit,
- struct attribute *attr_ptr,
- unsigned int recur_count,
- const char **pname,
- bfd_boolean *is_linkage)
+find_abstract_instance (struct comp_unit *unit,
+ struct attribute *attr_ptr,
+ unsigned int recur_count,
+ const char **pname,
+ bfd_boolean *is_linkage,
+ char **filename_ptr,
+ int *linenumber_ptr)
{
bfd *abfd = unit->abfd;
bfd_byte *info_ptr;
@@ -2949,12 +2963,12 @@ find_abstract_instance_name (struct comp
a symbolic reference to a label in any .debug_info section
might be used. Since we lay out multiple .debug_info
sections at non-zero VMAs (see place_sections), and read
- them contiguously into stash->info_ptr_memory, that means
- the reference is relative to stash->info_ptr_memory. */
+ them contiguously into dwarf_info_buffer, that means the
+ reference is relative to dwarf_info_buffer. */
size_t total;
- info_ptr = unit->stash->info_ptr_memory;
- info_ptr_end = unit->stash->info_ptr_end;
+ info_ptr = unit->file->dwarf_info_buffer;
+ info_ptr_end = info_ptr + unit->file->dwarf_info_size;
total = info_ptr_end - info_ptr;
if (!die_ref)
return TRUE;
@@ -2966,14 +2980,37 @@ find_abstract_instance_name (struct comp
return FALSE;
}
info_ptr += die_ref;
+ }
+ else if (attr_ptr->form == DW_FORM_GNU_ref_alt)
+ {
+ bfd_boolean first_time = unit->stash->alt.dwarf_info_buffer == NULL;
+ info_ptr = read_alt_indirect_ref (unit, die_ref);
+ if (first_time)
+ unit->stash->alt.info_ptr = unit->stash->alt.dwarf_info_buffer;
+ if (info_ptr == NULL)
+ {
+ _bfd_error_handler
+ (_("DWARF error: unable to read alt ref %llu"),
+ (bfd_vma) die_ref);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ info_ptr_end = (unit->stash->alt.dwarf_info_buffer
+ + unit->stash->alt.dwarf_info_size);
+ if (unit->stash->alt.all_comp_units)
+ unit = unit->stash->alt.all_comp_units;
+ }
+ if (attr_ptr->form == DW_FORM_ref_addr
+ || attr_ptr->form == DW_FORM_GNU_ref_alt)
+ {
/* Now find the CU containing this pointer. */
if (info_ptr >= unit->info_ptr_unit && info_ptr < unit->end_ptr)
info_ptr_end = unit->end_ptr;
else
{
/* Check other CUs to see if they contain the abbrev. */
- struct comp_unit * u;
+ 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)
@@ -2984,30 +3021,39 @@ find_abstract_instance_name (struct comp
if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
break;
- if (u)
+ if (attr_ptr->form == DW_FORM_ref_addr)
+ while (u == NULL)
+ {
+ u = stash_comp_unit (unit->stash, &unit->stash->f);
+ if (u == NULL)
+ break;
+ if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
+ break;
+ u = NULL;
+ }
+
+ if (attr_ptr->form == DW_FORM_GNU_ref_alt)
+ while (u == NULL)
+ {
+ u = stash_comp_unit (unit->stash, &unit->stash->alt);
+ if (u == NULL)
+ break;
+ if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
+ break;
+ u = NULL;
+ }
+
+ if (u == NULL)
{
- unit = u;
- info_ptr_end = unit->end_ptr;
+ _bfd_error_handler
+ (_("DWARF error: unable to locate abstract instance DIE ref %llu"),
+ (bfd_vma) die_ref);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
}
- /* else FIXME: What do we do now ? */
- }
- }
- 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 %llu."),
- (long long) die_ref);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ unit = u;
+ info_ptr_end = unit->end_ptr;
}
- info_ptr_end = (unit->stash->alt_dwarf_info_buffer
- + unit->stash->alt_dwarf_info_size);
-
- /* FIXME: Do we need to locate the correct CU, in a similar
- fashion to the code in the DW_FORM_ref_addr case above ? */
}
else
{
@@ -3022,7 +3068,7 @@ find_abstract_instance_name (struct comp
if (!die_ref || die_ref >= total)
{
_bfd_error_handler
- (_("Dwarf Error: Invalid abstract instance DIE ref."));
+ (_("DWARF error: invalid abstract instance DIE ref"));
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
@@ -3065,8 +3111,9 @@ find_abstract_instance_name (struct comp
}
break;
case DW_AT_specification:
- if (!find_abstract_instance_name (unit, &attr, recur_count + 1,
- pname, is_linkage))
+ if (!find_abstract_instance (unit, &attr, recur_count + 1,
+ pname, is_linkage,
+ filename_ptr, linenumber_ptr))
return FALSE;
break;
case DW_AT_linkage_name:
@@ -3079,6 +3126,15 @@ find_abstract_instance_name (struct comp
*is_linkage = TRUE;
}
break;
+ case DW_AT_decl_file:
+ if (!comp_unit_maybe_decode_line_info (unit))
+ return FALSE;
+ *filename_ptr = concat_filename (unit->line_table,
+ attr.u.val);
+ break;
+ case DW_AT_decl_line:
+ *linenumber_ptr = attr.u.val;
+ break;
default:
break;
}
@@ -3096,18 +3152,18 @@ read_ranges (struct comp_unit *unit, str
bfd_byte *ranges_end;
bfd_vma base_address = unit->base_address;
- if (! unit->stash->dwarf_ranges_buffer)
+ if (! unit->file->dwarf_ranges_buffer)
{
if (! read_debug_ranges (unit))
return FALSE;
}
- if (offset > unit->stash->dwarf_ranges_size)
+ if (offset > unit->file->dwarf_ranges_size)
return FALSE;
- ranges_ptr = unit->stash->dwarf_ranges_buffer + offset;
- if (ranges_ptr < unit->stash->dwarf_ranges_buffer)
+ ranges_ptr = unit->file->dwarf_ranges_buffer + offset;
+ if (ranges_ptr < unit->file->dwarf_ranges_buffer)
return FALSE;
- ranges_end = unit->stash->dwarf_ranges_buffer + unit->stash->dwarf_ranges_size;
+ ranges_end = unit->file->dwarf_ranges_buffer + unit->file->dwarf_ranges_size;
for (;;)
{
@@ -3147,17 +3203,17 @@ read_rnglists (struct comp_unit *unit, s
bfd_vma high_pc;
bfd *abfd = unit->abfd;
- if (! unit->stash->dwarf_rnglists_buffer)
+ if (! unit->file->dwarf_rnglists_buffer)
{
if (! read_debug_rnglists (unit))
return FALSE;
}
- rngs_ptr = unit->stash->dwarf_rnglists_buffer + offset;
- if (rngs_ptr < unit->stash->dwarf_rnglists_buffer)
+ rngs_ptr = unit->file->dwarf_rnglists_buffer + offset;
+ if (rngs_ptr < unit->file->dwarf_rnglists_buffer)
return FALSE;
- rngs_end = unit->stash->dwarf_rnglists_buffer;
- rngs_end += unit->stash->dwarf_rnglists_size;
+ rngs_end = unit->file->dwarf_rnglists_buffer;
+ rngs_end += unit->file->dwarf_rnglists_size;
for (;;)
{
@@ -3245,7 +3301,7 @@ scan_unit_for_symbols (struct comp_unit
{
bfd *abfd = unit->abfd;
bfd_byte *info_ptr = unit->first_child_die_ptr;
- bfd_byte *info_ptr_end = unit->stash->info_ptr_end;
+ bfd_byte *info_ptr_end = unit->end_ptr;
int nesting_level = 0;
struct nest_funcinfo {
struct funcinfo *func;
@@ -3370,9 +3426,11 @@ scan_unit_for_symbols (struct comp_unit
case DW_AT_abstract_origin:
case DW_AT_specification:
- if (!find_abstract_instance_name (unit, &attr, 0,
- &func->name,
- &func->is_linkage))
+ if (!find_abstract_instance (unit, &attr, 0,
+ &func->name,
+ &func->is_linkage,
+ &func->file,
+ &func->line))
goto fail;
break;
@@ -3523,7 +3581,7 @@ scan_unit_for_symbols (struct comp_unit
return FALSE;
}
-/* Parse a DWARF2 compilation unit starting at INFO_PTR. This
+/* Parse a DWARF2 compilation unit starting at INFO_PTR. UNIT_LENGTH
includes the compilation unit header that proceeds the DIE's, but
does not include the length field that precedes each compilation
unit header. END_PTR points one past the end of this comp unit.
@@ -3534,6 +3592,8 @@ scan_unit_for_symbols (struct comp_unit
static struct comp_unit *
parse_comp_unit (struct dwarf2_debug *stash,
+ struct dwarf2_debug_file *file,
+ bfd_byte *info_ptr,
bfd_vma unit_length,
bfd_byte *info_ptr_unit,
unsigned int offset_size)
@@ -3547,12 +3607,11 @@ parse_comp_unit (struct dwarf2_debug *st
unsigned int abbrev_number, bytes_read, i;
struct abbrev_info *abbrev;
struct attribute attr;
- bfd_byte *info_ptr = stash->info_ptr;
bfd_byte *end_ptr = info_ptr + unit_length;
bfd_size_type amt;
bfd_vma low_pc = 0;
bfd_vma high_pc = 0;
- bfd *abfd = stash->bfd_ptr;
+ bfd *abfd = file->bfd_ptr;
bfd_boolean high_pc_relative = FALSE;
enum dwarf_unit_type unit_type;
@@ -3629,7 +3688,7 @@ parse_comp_unit (struct dwarf2_debug *st
}
/* Read the abbrevs for this compilation unit into a table. */
- abbrevs = read_abbrevs (abfd, abbrev_offset, stash);
+ abbrevs = read_abbrevs (abfd, abbrev_offset, stash, file);
if (! abbrevs)
return NULL;
@@ -3665,6 +3724,7 @@ parse_comp_unit (struct dwarf2_debug *st
unit->abbrevs = abbrevs;
unit->end_ptr = end_ptr;
unit->stash = stash;
+ unit->file = file;
unit->info_ptr_unit = info_ptr_unit;
for (i = 0; i < abbrev->num_attrs; ++i)
@@ -3791,42 +3851,17 @@ comp_unit_find_nearest_line (struct comp
const char **filename_ptr,
struct funcinfo **function_ptr,
unsigned int *linenumber_ptr,
- unsigned int *discriminator_ptr,
- struct dwarf2_debug *stash)
+ unsigned int *discriminator_ptr)
{
bfd_boolean func_p;
- if (unit->error)
+ if (!comp_unit_maybe_decode_line_info (unit))
return FALSE;
- if (! unit->line_table)
- {
- if (! unit->stmtlist)
- {
- unit->error = 1;
- return FALSE;
- }
-
- unit->line_table = decode_line_info (unit, stash);
-
- if (! unit->line_table)
- {
- unit->error = 1;
- return FALSE;
- }
-
- if (unit->first_child_die_ptr < unit->end_ptr
- && ! scan_unit_for_symbols (unit))
- {
- unit->error = 1;
- return FALSE;
- }
- }
-
*function_ptr = NULL;
func_p = lookup_address_in_function_table (unit, addr, function_ptr);
if (func_p && (*function_ptr)->tag == DW_TAG_inlined_subroutine)
- stash->inliner_chain = *function_ptr;
+ unit->stash->inliner_chain = *function_ptr;
return lookup_address_in_line_info_table (unit->line_table, addr,
filename_ptr,
@@ -3839,8 +3874,7 @@ comp_unit_find_nearest_line (struct comp
FALSE otherwise. */
static bfd_boolean
-comp_unit_maybe_decode_line_info (struct comp_unit *unit,
- struct dwarf2_debug *stash)
+comp_unit_maybe_decode_line_info (struct comp_unit *unit)
{
if (unit->error)
return FALSE;
@@ -3853,7 +3887,7 @@ comp_unit_maybe_decode_line_info (struct
return FALSE;
}
- unit->line_table = decode_line_info (unit, stash);
+ unit->line_table = decode_line_info (unit);
if (! unit->line_table)
{
@@ -3885,10 +3919,9 @@ comp_unit_find_line (struct comp_unit *u
asymbol *sym,
bfd_vma addr,
const char **filename_ptr,
- unsigned int *linenumber_ptr,
- struct dwarf2_debug *stash)
+ unsigned int *linenumber_ptr)
{
- if (!comp_unit_maybe_decode_line_info (unit, stash))
+ if (!comp_unit_maybe_decode_line_info (unit))
return FALSE;
if (sym->flags & BSF_FUNCTION)
@@ -3947,7 +3980,7 @@ comp_unit_hash_info (struct dwarf2_debug
BFD_ASSERT (stash->info_hash_status != STASH_INFO_HASH_DISABLED);
- if (!comp_unit_maybe_decode_line_info (unit, stash))
+ if (!comp_unit_maybe_decode_line_info (unit))
return FALSE;
BFD_ASSERT (!unit->cached);
@@ -4078,6 +4111,41 @@ set_debug_vma (bfd *orig_bfd, bfd *debug
}
}
+/* If the dwarf2 info was found in a separate debug file, return the
+ debug file section corresponding to the section in the original file
+ and the debug file symbols. */
+
+static void
+_bfd_dwarf2_stash_syms (struct dwarf2_debug *stash, bfd *abfd,
+ asection **sec, asymbol ***syms)
+{
+ if (stash->f.bfd_ptr != abfd)
+ {
+ asection *s, *d;
+
+ if (*sec == NULL)
+ {
+ *syms = stash->f.syms;
+ return;
+ }
+
+ for (s = abfd->sections, d = stash->f.bfd_ptr->sections;
+ s != NULL && d != NULL;
+ s = s->next, d = d->next)
+ {
+ if ((d->flags & SEC_DEBUGGING) != 0)
+ break;
+ if (s == *sec
+ && strcmp (s->name, d->name) == 0)
+ {
+ *sec = d;
+ *syms = stash->f.syms;
+ break;
+ }
+ }
+ }
+}
+
/* Unset vmas for adjusted sections in STASH. */
static void
@@ -4145,9 +4213,9 @@ place_sections (bfd *orig_bfd, struct dw
i++;
}
- if (abfd == stash->bfd_ptr)
+ if (abfd == stash->f.bfd_ptr)
break;
- abfd = stash->bfd_ptr;
+ abfd = stash->f.bfd_ptr;
}
if (i <= 1)
@@ -4210,14 +4278,14 @@ place_sections (bfd *orig_bfd, struct dw
p->adj_vma = sect->vma;
p++;
}
- if (abfd == stash->bfd_ptr)
+ if (abfd == stash->f.bfd_ptr)
break;
- abfd = stash->bfd_ptr;
+ abfd = stash->f.bfd_ptr;
}
}
- if (orig_bfd != stash->bfd_ptr)
- set_debug_vma (orig_bfd, stash->bfd_ptr);
+ if (orig_bfd != stash->f.bfd_ptr)
+ set_debug_vma (orig_bfd, stash->f.bfd_ptr);
return TRUE;
}
@@ -4321,13 +4389,13 @@ stash_maybe_update_info_hash_tables (str
struct comp_unit *each;
/* Exit if hash tables are up-to-date. */
- if (stash->all_comp_units == stash->hash_units_head)
+ if (stash->f.all_comp_units == stash->hash_units_head)
return TRUE;
if (stash->hash_units_head)
each = stash->hash_units_head->prev_unit;
else
- each = stash->last_comp_unit;
+ each = stash->f.last_comp_unit;
while (each)
{
@@ -4340,7 +4408,7 @@ stash_maybe_update_info_hash_tables (str
each = each->prev_unit;
}
- stash->hash_units_head = stash->all_comp_units;
+ stash->hash_units_head = stash->f.all_comp_units;
return TRUE;
}
@@ -4355,7 +4423,7 @@ stash_verify_info_hash_table (struct dwa
struct info_list_node *node;
bfd_boolean found;
- for (each_unit = stash->all_comp_units;
+ for (each_unit = stash->f.all_comp_units;
each_unit;
each_unit = each_unit->next_unit)
{
@@ -4425,8 +4493,8 @@ stash_maybe_enable_info_hash_tables (bfd
/* We need a forced update so that the info hash tables will
be created even though there is no compilation unit. That
happens if STASH_INFO_HASH_TRIGGER is 0. */
- stash_maybe_update_info_hash_tables (stash);
- stash->info_hash_status = STASH_INFO_HASH_ON;
+ if (stash_maybe_update_info_hash_tables (stash))
+ stash->info_hash_status = STASH_INFO_HASH_ON;
}
/* Find the file and line associated with a symbol and address using the
@@ -4463,7 +4531,10 @@ save_section_vma (const bfd *abfd, struc
stash->sec_vma = bfd_malloc (sizeof (*stash->sec_vma) * abfd->section_count);
if (stash->sec_vma == NULL)
return FALSE;
- for (i = 0, s = abfd->sections; i < abfd->section_count; i++, s = s->next)
+ stash->sec_vma_count = abfd->section_count;
+ for (i = 0, s = abfd->sections;
+ s != NULL && i < abfd->section_count;
+ i++, s = s->next)
{
if (s->output_section != NULL)
stash->sec_vma[i] = s->output_section->vma + s->output_offset;
@@ -4486,7 +4557,15 @@ section_vma_same (const bfd *abfd, const
asection *s;
unsigned int i;
- for (i = 0, s = abfd->sections; i < abfd->section_count; i++, s = s->next)
+ /* PR 24334: If the number of sections in ABFD has changed between
+ when the stash was created and now, then we cannot trust the
+ stashed vma information. */
+ if (abfd->section_count != stash->sec_vma_count)
+ return FALSE;
+
+ for (i = 0, s = abfd->sections;
+ s != NULL && i < abfd->section_count;
+ i++, s = s->next)
{
bfd_vma vma;
@@ -4524,7 +4603,7 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
{
/* Check that we did previously find some debug information
before attempting to make use of it. */
- if (stash->bfd_ptr != NULL)
+ if (stash->f.bfd_ptr != NULL)
{
if (do_place && !place_sections (abfd, stash))
return FALSE;
@@ -4544,7 +4623,7 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
}
stash->orig_bfd = abfd;
stash->debug_sections = debug_sections;
- stash->syms = symbols;
+ stash->f.syms = symbols;
if (!save_section_vma (abfd, stash))
return FALSE;
@@ -4585,10 +4664,10 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
}
symbols = bfd_get_outsymbols (debug_bfd);
- stash->syms = symbols;
+ stash->f.syms = symbols;
stash->close_on_cleanup = TRUE;
}
- stash->bfd_ptr = debug_bfd;
+ stash->f.bfd_ptr = debug_bfd;
if (do_place
&& !place_sections (abfd, stash))
@@ -4611,7 +4690,7 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
total_size = msec->size;
if (! read_section (debug_bfd, &stash->debug_sections[debug_info],
symbols, 0,
- &stash->info_ptr_memory, &total_size))
+ &stash->f.dwarf_info_buffer, &total_size))
return FALSE;
}
else
@@ -4631,8 +4710,8 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
total_size += msec->size;
}
- stash->info_ptr_memory = (bfd_byte *) bfd_malloc (total_size);
- if (stash->info_ptr_memory == NULL)
+ stash->f.dwarf_info_buffer = (bfd_byte *) bfd_malloc (total_size);
+ if (stash->f.dwarf_info_buffer == NULL)
return FALSE;
total_size = 0;
@@ -4647,7 +4726,7 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
continue;
if (!(bfd_simple_get_relocated_section_contents
- (debug_bfd, msec, stash->info_ptr_memory + total_size,
+ (debug_bfd, msec, stash->f.dwarf_info_buffer + total_size,
symbols)))
return FALSE;
@@ -4655,13 +4734,106 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
}
}
- stash->info_ptr = stash->info_ptr_memory;
- 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->f.info_ptr = stash->f.dwarf_info_buffer;
+ stash->f.dwarf_info_size = total_size;
return TRUE;
}
+/* Parse the next DWARF2 compilation unit at FILE->INFO_PTR. */
+
+static struct comp_unit *
+stash_comp_unit (struct dwarf2_debug *stash, struct dwarf2_debug_file *file)
+{
+ bfd_size_type length;
+ unsigned int offset_size;
+ bfd_byte *info_ptr_unit = file->info_ptr;
+ bfd_byte *info_ptr_end = file->dwarf_info_buffer + file->dwarf_info_size;
+
+ if (file->info_ptr >= info_ptr_end)
+ return NULL;
+
+ length = read_4_bytes (file->bfd_ptr, file->info_ptr, info_ptr_end);
+ /* A 0xffffff length is the DWARF3 way of indicating
+ we use 64-bit offsets, instead of 32-bit offsets. */
+ if (length == 0xffffffff)
+ {
+ offset_size = 8;
+ length = read_8_bytes (file->bfd_ptr, file->info_ptr + 4,
+ info_ptr_end);
+ file->info_ptr += 12;
+ }
+ /* A zero length is the IRIX way of indicating 64-bit offsets,
+ mostly because the 64-bit length will generally fit in 32
+ bits, and the endianness helps. */
+ else if (length == 0)
+ {
+ offset_size = 8;
+ length = read_4_bytes (file->bfd_ptr, file->info_ptr + 4,
+ info_ptr_end);
+ file->info_ptr += 8;
+ }
+ /* In the absence of the hints above, we assume 32-bit DWARF2
+ offsets even for targets with 64-bit addresses, because:
+ a) most of the time these targets will not have generated
+ more than 2Gb of debug info and so will not need 64-bit
+ offsets,
+ and
+ b) if they do use 64-bit offsets but they are not using
+ the size hints that are tested for above then they are
+ not conforming to the DWARF3 standard anyway. */
+ else
+ {
+ offset_size = 4;
+ file->info_ptr += 4;
+ }
+
+ if (length != 0
+ && file->info_ptr + length <= info_ptr_end
+ && file->info_ptr + length > file->info_ptr)
+ {
+ struct comp_unit *each = parse_comp_unit (stash, file,
+ file->info_ptr, length,
+ info_ptr_unit, offset_size);
+ if (each)
+ {
+ if (file->all_comp_units)
+ file->all_comp_units->prev_unit = each;
+ else
+ file->last_comp_unit = each;
+
+ each->next_unit = file->all_comp_units;
+ file->all_comp_units = each;
+
+ file->info_ptr += length;
+ return each;
+ }
+ }
+
+ /* Don't trust any of the DWARF info after a corrupted length or
+ parse error. */
+ file->info_ptr = info_ptr_end;
+ return NULL;
+}
+
+/* Hash function for an asymbol. */
+
+static hashval_t
+hash_asymbol (const void *sym)
+{
+ const asymbol *asym = sym;
+ return htab_hash_string (asym->name);
+}
+
+/* Equality function for asymbols. */
+
+static int
+eq_asymbol (const void *a, const void *b)
+{
+ const asymbol *sa = a;
+ const asymbol *sb = b;
+ return strcmp (sa->name, sb->name) == 0;
+}
+
/* Scan the debug information in PINFO looking for a DW_TAG_subprogram
abbrev with a DW_AT_low_pc attached to it. Then lookup that same
symbol in SYMBOLS and return the difference between the low_pc and
@@ -4672,45 +4844,55 @@ _bfd_dwarf2_find_symbol_bias (asymbol **
{
struct dwarf2_debug *stash;
struct comp_unit * unit;
+ htab_t sym_hash;
+ bfd_signed_vma result = 0;
+ asymbol ** psym;
stash = (struct dwarf2_debug *) *pinfo;
- if (stash == NULL)
+ if (stash == NULL || symbols == NULL)
return 0;
- for (unit = stash->all_comp_units; unit; unit = unit->next_unit)
+ sym_hash = htab_create_alloc (10, hash_asymbol, eq_asymbol,
+ NULL, xcalloc, free);
+ for (psym = symbols; * psym != NULL; psym++)
{
- struct funcinfo * func;
+ asymbol * sym = * psym;
- if (unit->function_table == NULL)
+ if (sym->flags & BSF_FUNCTION && sym->section != NULL)
{
- if (unit->line_table == NULL)
- unit->line_table = decode_line_info (unit, stash);
- if (unit->line_table != NULL)
- scan_unit_for_symbols (unit);
+ void **slot = htab_find_slot (sym_hash, sym, INSERT);
+ *slot = sym;
}
+ }
+
+ for (unit = stash->f.all_comp_units; unit; unit = unit->next_unit)
+ {
+ struct funcinfo * func;
+
+ comp_unit_maybe_decode_line_info (unit);
for (func = unit->function_table; func != NULL; func = func->prev_func)
if (func->name && func->arange.low)
{
- asymbol ** psym;
+ asymbol search, *sym;
/* FIXME: Do we need to scan the aranges looking for the lowest pc value ? */
- for (psym = symbols; * psym != NULL; psym++)
+ search.name = func->name;
+ sym = htab_find (sym_hash, &search);
+ if (sym != NULL)
{
- asymbol * sym = * psym;
-
- if (sym->flags & BSF_FUNCTION
- && sym->section != NULL
- && strcmp (sym->name, func->name) == 0)
- return ((bfd_signed_vma) func->arange.low) -
- ((bfd_signed_vma) (sym->value + sym->section->vma));
+ result = ((bfd_signed_vma) func->arange.low) -
+ ((bfd_signed_vma) (sym->value + sym->section->vma));
+ goto done;
}
}
}
- return 0;
+ done:
+ htab_delete (sym_hash);
+ return result;
}
/* Find the source code location of SYMBOL. If SYMBOL is NULL
@@ -4821,7 +5003,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
/* A null info_ptr indicates that there is no dwarf2 info
(or that an error occured while setting up the stash). */
- if (! stash->info_ptr)
+ if (! stash->f.info_ptr)
return FALSE;
stash->inliner_chain = NULL;
@@ -4850,13 +5032,13 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
else
{
/* Check the previously read comp. units first. */
- for (each = stash->all_comp_units; each; each = each->next_unit)
+ 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, stash);
+ linenumber_ptr);
if (found)
goto done;
}
@@ -4870,7 +5052,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
unsigned int local_linenumber = 0;
unsigned int local_discriminator = 0;
- for (each = stash->all_comp_units; each; each = each->next_unit)
+ for (each = stash->f.all_comp_units; each; each = each->next_unit)
{
bfd_vma range = (bfd_vma) -1;
@@ -4880,8 +5062,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
& local_filename,
& local_function,
& local_linenumber,
- & local_discriminator,
- stash)) != 0);
+ & local_discriminator)) != 0);
if (found)
{
/* PRs 15935 15994: Bogus debug information may have provided us
@@ -4925,128 +5106,55 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
BFD_ASSERT (addr_size == 4 || addr_size == 8);
/* Read each remaining comp. units checking each as they are read. */
- while (stash->info_ptr < stash->info_ptr_end)
+ while ((each = stash_comp_unit (stash, &stash->f)) != NULL)
{
- bfd_vma length;
- unsigned int offset_size = addr_size;
- bfd_byte *info_ptr_unit = stash->info_ptr;
-
- length = read_4_bytes (stash->bfd_ptr, stash->info_ptr, stash->info_ptr_end);
- /* A 0xffffff length is the DWARF3 way of indicating
- we use 64-bit offsets, instead of 32-bit offsets. */
- if (length == 0xffffffff)
- {
- offset_size = 8;
- length = read_8_bytes (stash->bfd_ptr, stash->info_ptr + 4, stash->info_ptr_end);
- stash->info_ptr += 12;
- }
- /* A zero length is the IRIX way of indicating 64-bit offsets,
- mostly because the 64-bit length will generally fit in 32
- bits, and the endianness helps. */
- else if (length == 0)
- {
- offset_size = 8;
- length = read_4_bytes (stash->bfd_ptr, stash->info_ptr + 4, stash->info_ptr_end);
- stash->info_ptr += 8;
- }
- /* In the absence of the hints above, we assume 32-bit DWARF2
- offsets even for targets with 64-bit addresses, because:
- a) most of the time these targets will not have generated
- more than 2Gb of debug info and so will not need 64-bit
- offsets,
- and
- b) if they do use 64-bit offsets but they are not using
- the size hints that are tested for above then they are
- not conforming to the DWARF3 standard anyway. */
- else if (addr_size == 8)
- {
- offset_size = 4;
- stash->info_ptr += 4;
- }
+ /* 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
+ to see if a compilation unit contains the given
+ address. */
+ if (do_line)
+ found = (((symbol->flags & BSF_FUNCTION) == 0
+ || each->arange.high == 0
+ || comp_unit_contains_address (each, addr))
+ && comp_unit_find_line (each, symbol, addr,
+ filename_ptr, linenumber_ptr));
else
- stash->info_ptr += 4;
-
- if (length > 0)
- {
- bfd_byte * new_ptr;
-
- /* PR 21151 */
- if (stash->info_ptr + length > stash->info_ptr_end)
- return FALSE;
-
- each = parse_comp_unit (stash, length, info_ptr_unit,
- offset_size);
- if (!each)
- /* The dwarf information is damaged, don't trust it any
- more. */
- break;
+ found = ((each->arange.high == 0
+ || comp_unit_contains_address (each, addr))
+ && comp_unit_find_nearest_line (each, addr,
+ filename_ptr,
+ &function,
+ linenumber_ptr,
+ discriminator_ptr) != 0);
- new_ptr = stash->info_ptr + length;
- /* PR 17512: file: 1500698c. */
- if (new_ptr < stash->info_ptr)
- {
- /* A corrupt length value - do not trust the info any more. */
- found = FALSE;
- break;
- }
- else
- stash->info_ptr = new_ptr;
-
- if (stash->all_comp_units)
- 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
- to see if a compilation unit contains the given
- address. */
- if (do_line)
- found = (((symbol->flags & BSF_FUNCTION) == 0
- || each->arange.high == 0
- || comp_unit_contains_address (each, addr))
- && comp_unit_find_line (each, symbol, addr,
- filename_ptr,
- linenumber_ptr,
- stash));
- else
- found = ((each->arange.high == 0
- || comp_unit_contains_address (each, addr))
- && comp_unit_find_nearest_line (each, addr,
- filename_ptr,
- &function,
- linenumber_ptr,
- discriminator_ptr,
- stash) != 0);
-
- if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr)
- == stash->sec->size)
- {
- stash->sec = find_debug_info (stash->bfd_ptr, debug_sections,
- stash->sec);
- stash->sec_info_ptr = stash->info_ptr;
- }
-
- if (found)
- goto done;
- }
+ if (found)
+ break;
}
done:
- if (function)
- {
- if (!function->is_linkage)
+ if (functionname_ptr && function && function->is_linkage)
+ *functionname_ptr = function->name;
+ else if (functionname_ptr
+ && (!*functionname_ptr
+ || (function && !function->is_linkage)))
+ {
+ asymbol *fun;
+ asymbol **syms = symbols;
+ asection *sec = section;
+
+ _bfd_dwarf2_stash_syms (stash, abfd, &sec, &syms);
+ fun = _bfd_elf_find_function (abfd, syms, sec, offset,
+ *filename_ptr ? NULL : filename_ptr,
+ functionname_ptr);
+
+ if (!found && fun != NULL)
+ found = 2;
+
+ if (function && !function->is_linkage)
{
- asymbol *fun;
bfd_vma sec_vma;
- fun = _bfd_elf_find_function (abfd, symbols, section, offset,
- *filename_ptr ? NULL : filename_ptr,
- functionname_ptr);
sec_vma = section->vma;
if (section->output_section != NULL)
sec_vma = section->output_section->vma + section->output_offset;
@@ -5057,8 +5165,8 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
to stop a repeated search of symbols. */
function->is_linkage = TRUE;
}
- *functionname_ptr = function->name;
}
+
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
unset_sections (stash);
@@ -5097,96 +5205,84 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abf
{
struct dwarf2_debug *stash = (struct dwarf2_debug *) *pinfo;
struct comp_unit *each;
+ struct dwarf2_debug_file *file;
if (abfd == NULL || stash == NULL)
return;
- for (each = stash->all_comp_units; each; each = each->next_unit)
- {
- struct abbrev_info **abbrevs = each->abbrevs;
- struct funcinfo *function_table = each->function_table;
- struct varinfo *variable_table = each->variable_table;
- size_t i;
+ if (stash->varinfo_hash_table)
+ bfd_hash_table_free (&stash->varinfo_hash_table->base);
+ if (stash->funcinfo_hash_table)
+ bfd_hash_table_free (&stash->funcinfo_hash_table->base);
- for (i = 0; i < ABBREV_HASH_SIZE; i++)
+ file = &stash->f;
+ while (1)
+ {
+ for (each = file->all_comp_units; each; each = each->next_unit)
{
- struct abbrev_info *abbrev = abbrevs[i];
+ struct funcinfo *function_table = each->function_table;
+ struct varinfo *variable_table = each->variable_table;
- while (abbrev)
+ if (each->line_table && each->line_table != file->line_table)
{
- free (abbrev->attrs);
- abbrev = abbrev->next;
+ free (each->line_table->files);
+ free (each->line_table->dirs);
}
- }
- if (each->line_table)
- {
- free (each->line_table->dirs);
- free (each->line_table->files);
- }
+ if (each->lookup_funcinfo_table)
+ {
+ free (each->lookup_funcinfo_table);
+ each->lookup_funcinfo_table = NULL;
+ }
- while (function_table)
- {
- if (function_table->file)
+ while (function_table)
{
- free (function_table->file);
- function_table->file = NULL;
+ if (function_table->file)
+ {
+ free (function_table->file);
+ function_table->file = NULL;
+ }
+ if (function_table->caller_file)
+ {
+ free (function_table->caller_file);
+ function_table->caller_file = NULL;
+ }
+ function_table = function_table->prev_func;
}
- if (function_table->caller_file)
+ while (variable_table)
{
- free (function_table->caller_file);
- function_table->caller_file = NULL;
+ if (variable_table->file)
+ {
+ free (variable_table->file);
+ variable_table->file = NULL;
+ }
+ variable_table = variable_table->prev_var;
}
- function_table = function_table->prev_func;
}
- if (each->lookup_funcinfo_table)
+ if (file->line_table)
{
- free (each->lookup_funcinfo_table);
- each->lookup_funcinfo_table = NULL;
+ free (file->line_table->files);
+ free (file->line_table->dirs);
}
- while (variable_table)
- {
- if (variable_table->file)
- {
- free (variable_table->file);
- variable_table->file = NULL;
- }
-
- variable_table = variable_table->prev_var;
- }
+ free (file->dwarf_line_str_buffer);
+ free (file->dwarf_str_buffer);
+ free (file->dwarf_ranges_buffer);
+ free (file->dwarf_line_buffer);
+ free (file->dwarf_abbrev_buffer);
+ free (file->dwarf_info_buffer);
+ if (file == &stash->alt)
+ break;
+ file = &stash->alt;
}
-
- if (stash->funcinfo_hash_table)
- bfd_hash_table_free (&stash->funcinfo_hash_table->base);
- if (stash->varinfo_hash_table)
- bfd_hash_table_free (&stash->varinfo_hash_table->base);
- if (stash->dwarf_abbrev_buffer)
- free (stash->dwarf_abbrev_buffer);
- if (stash->dwarf_line_buffer)
- free (stash->dwarf_line_buffer);
- if (stash->dwarf_str_buffer)
- free (stash->dwarf_str_buffer);
- if (stash->dwarf_line_str_buffer)
- free (stash->dwarf_line_str_buffer);
- if (stash->dwarf_ranges_buffer)
- free (stash->dwarf_ranges_buffer);
- if (stash->info_ptr_memory)
- free (stash->info_ptr_memory);
+ free (stash->sec_vma);
+ free (stash->adjusted_sections);
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->sec_vma)
- free (stash->sec_vma);
- if (stash->adjusted_sections)
- free (stash->adjusted_sections);
- if (stash->alt_bfd_ptr)
- bfd_close (stash->alt_bfd_ptr);
+ bfd_close (stash->f.bfd_ptr);
+ if (stash->alt.bfd_ptr)
+ bfd_close (stash->alt.bfd_ptr);
}
/* Find the function to a particular section and offset,
diff -rup binutils.orig/bfd/elf.c binutils-2.30/bfd/elf.c
--- binutils.orig/bfd/elf.c 2025-04-14 14:37:39.496183572 +0100
+++ binutils-2.30/bfd/elf.c 2025-04-14 15:15:42.734192670 +0100
@@ -8836,10 +8836,12 @@ _bfd_elf_find_nearest_line (bfd *abfd,
filename_ptr, functionname_ptr,
line_ptr, discriminator_ptr,
dwarf_debug_sections, 0,
- &elf_tdata (abfd)->dwarf2_find_line_info)
- || _bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
- filename_ptr, functionname_ptr,
- line_ptr))
+ &elf_tdata (abfd)->dwarf2_find_line_info))
+ return TRUE;
+
+ if (_bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
+ filename_ptr, functionname_ptr,
+ line_ptr))
{
if (!*functionname_ptr)
_bfd_elf_find_function (abfd, symbols, section, offset,
Only in binutils-2.30/bfd: elf.c.orig
Only in binutils-2.30/bfd: elf.c.rej
diff -rup binutils.orig/bfd/elf32-arm.c binutils-2.30/bfd/elf32-arm.c
--- binutils.orig/bfd/elf32-arm.c 2025-04-14 14:37:39.495351114 +0100
+++ binutils-2.30/bfd/elf32-arm.c 2025-04-14 15:18:08.269574813 +0100
@@ -14963,68 +14963,46 @@ elf32_arm_is_target_special_symbol (bfd
BFD_ARM_SPECIAL_SYM_TYPE_ANY);
}
-/* This is a copy of elf_find_function() from elf.c except that
- ARM mapping symbols are ignored when looking for function names
- and STT_ARM_TFUNC is considered to a function type. */
-
-static bfd_boolean
-arm_elf_find_function (bfd * abfd ATTRIBUTE_UNUSED,
- asymbol ** symbols,
- asection * section,
- bfd_vma offset,
- const char ** filename_ptr,
- const char ** functionname_ptr)
+/* If the ELF symbol SYM might be a function in SEC, return the
+ function size and set *CODE_OFF to the function's entry point,
+ otherwise return zero. */
+
+static bfd_size_type
+elf32_arm_maybe_function_sym (const asymbol *sym, asection *sec,
+ bfd_vma *code_off)
{
- const char * filename = NULL;
- asymbol * func = NULL;
- bfd_vma low_func = 0;
- asymbol ** p;
-
- for (p = symbols; *p != NULL; p++)
- {
- elf_symbol_type *q;
+ bfd_size_type size;
- q = (elf_symbol_type *) *p;
+ if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT
+ | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0
+ || sym->section != sec)
+ return 0;
- switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
- {
- default:
- break;
- case STT_FILE:
- filename = bfd_asymbol_name (&q->symbol);
- break;
+ if (!(sym->flags & BSF_SYNTHETIC))
+ switch (ELF_ST_TYPE (((elf_symbol_type *) sym)->internal_elf_sym.st_info))
+ {
case STT_FUNC:
case STT_ARM_TFUNC:
case STT_NOTYPE:
- /* Skip mapping symbols. */
- if ((q->symbol.flags & BSF_LOCAL)
- && bfd_is_arm_special_symbol_name (q->symbol.name,
- BFD_ARM_SPECIAL_SYM_TYPE_ANY))
- continue;
- /* Fall through. */
- if (bfd_get_section (&q->symbol) == section
- && q->symbol.value >= low_func
- && q->symbol.value <= offset)
- {
- func = (asymbol *) q;
- low_func = q->symbol.value;
- }
break;
- }
- }
-
- if (func == NULL)
- return FALSE;
+ default:
+ return 0;
+ }
- if (filename_ptr)
- *filename_ptr = filename;
- if (functionname_ptr)
- *functionname_ptr = bfd_asymbol_name (func);
+ if ((sym->flags & BSF_LOCAL)
+ && bfd_is_arm_special_symbol_name (sym->name,
+ BFD_ARM_SPECIAL_SYM_TYPE_ANY))
+ return 0;
- return TRUE;
+ *code_off = sym->value;
+ size = 0;
+ if (!(sym->flags & BSF_SYNTHETIC))
+ size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
+ if (size == 0)
+ size = 1;
+ return size;
}
-
/* Find the nearest line to a particular section and offset, for error
reporting. This code is a duplicate of the code in elf.c, except
that it uses arm_elf_find_function. */
@@ -19210,7 +19188,6 @@ elf32_arm_backend_symbol_processing (bfd
#define bfd_elf32_bfd_link_hash_table_create elf32_arm_link_hash_table_create
#define bfd_elf32_bfd_reloc_type_lookup elf32_arm_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup elf32_arm_reloc_name_lookup
-#define bfd_elf32_find_nearest_line elf32_arm_find_nearest_line
#define bfd_elf32_find_inliner_info elf32_arm_find_inliner_info
#define bfd_elf32_new_section_hook elf32_arm_new_section_hook
#define bfd_elf32_bfd_is_target_special_symbol elf32_arm_is_target_special_symbol
@@ -19218,6 +19195,7 @@ elf32_arm_backend_symbol_processing (bfd
#define bfd_elf32_get_synthetic_symtab elf32_arm_get_synthetic_symtab
#define elf_backend_get_symbol_type elf32_arm_get_symbol_type
+#define elf_backend_maybe_function_sym elf32_arm_maybe_function_sym
#define elf_backend_gc_mark_hook elf32_arm_gc_mark_hook
#define elf_backend_gc_mark_extra_sections elf32_arm_gc_mark_extra_sections
#define elf_backend_check_relocs elf32_arm_check_relocs
Only in binutils-2.30/bfd: elf32-arm.c.orig
Only in binutils-2.30/bfd: elf32-arm.c.rej
diff -rup binutils.orig/bfd/elfnn-aarch64.c binutils-2.30/bfd/elfnn-aarch64.c
--- binutils.orig/bfd/elfnn-aarch64.c 2025-04-14 14:37:39.496183572 +0100
+++ binutils-2.30/bfd/elfnn-aarch64.c 2025-04-14 15:20:44.373968637 +0100
@@ -7417,116 +7417,43 @@ elfNN_aarch64_is_target_special_symbol (
BFD_AARCH64_SPECIAL_SYM_TYPE_ANY);
}
-/* This is a copy of elf_find_function () from elf.c except that
- AArch64 mapping symbols are ignored when looking for function names. */
+/* If the ELF symbol SYM might be a function in SEC, return the
+ function size and set *CODE_OFF to the function's entry point,
+ otherwise return zero. */
+
+static bfd_size_type
+elfNN_aarch64_maybe_function_sym (const asymbol *sym, asection *sec,
+ bfd_vma *code_off)
+{
+ bfd_size_type size;
+
+ if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT
+ | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0
+ || sym->section != sec)
+ return 0;
-static bfd_boolean
-aarch64_elf_find_function (bfd *abfd ATTRIBUTE_UNUSED,
- asymbol **symbols,
- asection *section,
- bfd_vma offset,
- const char **filename_ptr,
- const char **functionname_ptr)
-{
- const char *filename = NULL;
- asymbol *func = NULL;
- bfd_vma low_func = 0;
- asymbol **p;
-
- for (p = symbols; *p != NULL; p++)
- {
- elf_symbol_type *q;
-
- q = (elf_symbol_type *) * p;
-
- switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
- {
- default:
- break;
- case STT_FILE:
- filename = bfd_asymbol_name (&q->symbol);
- break;
+ if (!(sym->flags & BSF_SYNTHETIC))
+ switch (ELF_ST_TYPE (((elf_symbol_type *) sym)->internal_elf_sym.st_info))
+ {
case STT_FUNC:
case STT_NOTYPE:
- /* Skip mapping symbols. */
- if ((q->symbol.flags & BSF_LOCAL)
- && (bfd_is_aarch64_special_symbol_name
- (q->symbol.name, BFD_AARCH64_SPECIAL_SYM_TYPE_ANY)))
- continue;
- /* Fall through. */
- if (bfd_get_section (&q->symbol) == section
- && q->symbol.value >= low_func && q->symbol.value <= offset)
- {
- func = (asymbol *) q;
- low_func = q->symbol.value;
- }
break;
- }
- }
-
- if (func == NULL)
- return FALSE;
-
- if (filename_ptr)
- *filename_ptr = filename;
- if (functionname_ptr)
- *functionname_ptr = bfd_asymbol_name (func);
-
- return TRUE;
-}
-
-
-/* Find the nearest line to a particular section and offset, for error
- reporting. This code is a duplicate of the code in elf.c, except
- that it uses aarch64_elf_find_function. */
-
-static bfd_boolean
-elfNN_aarch64_find_nearest_line (bfd *abfd,
- asymbol **symbols,
- asection *section,
- bfd_vma offset,
- const char **filename_ptr,
- const char **functionname_ptr,
- unsigned int *line_ptr,
- unsigned int *discriminator_ptr)
-{
- bfd_boolean found = FALSE;
-
- if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
- filename_ptr, functionname_ptr,
- line_ptr, discriminator_ptr,
- dwarf_debug_sections, 0,
- &elf_tdata (abfd)->dwarf2_find_line_info))
- {
- if (!*functionname_ptr)
- aarch64_elf_find_function (abfd, symbols, section, offset,
- *filename_ptr ? NULL : filename_ptr,
- functionname_ptr);
-
- return TRUE;
- }
-
- /* Skip _bfd_dwarf1_find_nearest_line since no known AArch64
- toolchain uses DWARF1. */
-
- if (!_bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
- &found, filename_ptr,
- functionname_ptr, line_ptr,
- &elf_tdata (abfd)->line_info))
- return FALSE;
-
- if (found && (*functionname_ptr || *line_ptr))
- return TRUE;
-
- if (symbols == NULL)
- return FALSE;
-
- if (!aarch64_elf_find_function (abfd, symbols, section, offset,
- filename_ptr, functionname_ptr))
- return FALSE;
+ default:
+ return 0;
+ }
- *line_ptr = 0;
- return TRUE;
+ if ((sym->flags & BSF_LOCAL)
+ && bfd_is_aarch64_special_symbol_name (sym->name,
+ BFD_AARCH64_SPECIAL_SYM_TYPE_ANY))
+ return 0;
+
+ *code_off = sym->value;
+ size = 0;
+ if (!(sym->flags & BSF_SYNTHETIC))
+ size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
+ if (size == 0)
+ size = 1;
+ return size;
}
static bfd_boolean
@@ -9457,6 +9384,9 @@ const struct elf_size_info elfNN_aarch64
#define elf_backend_output_arch_local_syms \
elfNN_aarch64_output_arch_local_syms
+#define elf_backend_maybe_function_sym \
+ elfNN_aarch64_maybe_function_sym
+
#define elf_backend_plt_sym_val \
elfNN_aarch64_plt_sym_val