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.
This commit is contained in:
Alan Modra 2019-11-26 22:32:51 +10:30
parent 96e2dbda08
commit e76790600a
6 changed files with 145 additions and 251 deletions

View File

@ -1,3 +1,22 @@
2019-11-27 Alan Modra <amodra@gmail.com>
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.
2019-11-27 Alan Modra <amodra@gmail.com>
* elf32-sh.c (sh_reloc): Use a bfd_vma insn.

View File

@ -3894,6 +3894,40 @@ set_debug_vma (bfd *orig_bfd, bfd *debug_bfd)
}
}
/* 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->bfd_ptr != abfd)
{
asection *s, *d;
if (*sec == NULL)
{
*syms = stash->syms;
return;
}
for (s = abfd->sections, d = stash->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->syms;
}
}
}
}
/* Unset vmas for adjusted sections in STASH. */
static void
@ -4888,16 +4922,26 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
}
done:
if (function)
if (functionname_ptr && function && function->is_linkage)
*functionname_ptr = function->name;
else if (functionname_ptr
&& ((found && !*functionname_ptr)
|| (function && !function->is_linkage)))
{
if (!function->is_linkage)
asymbol *fun;
asymbol **syms = symbols;
asection *sec = section;
if (symbols == NULL || *symbols == NULL)
_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 (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;
@ -4908,8 +4952,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);

View File

@ -9030,10 +9030,11 @@ _bfd_elf_find_nearest_line (bfd *abfd,
filename_ptr, functionname_ptr,
line_ptr, discriminator_ptr,
dwarf_debug_sections,
&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,

View File

@ -16040,125 +16040,44 @@ elf32_arm_is_target_special_symbol (bfd * abfd ATTRIBUTE_UNUSED, asymbol * sym)
BFD_ARM_SPECIAL_SYM_TYPE_ANY);
}
/* This is a version of _bfd_elf_find_function() from dwarf2.c except that
ARM mapping symbols are ignored when looking for function names
and STT_ARM_TFUNC is considered to a function type. */
/* 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_boolean
arm_elf_find_function (bfd * abfd,
asymbol ** symbols,
asection * section,
bfd_vma offset,
const char ** filename_ptr,
const char ** functionname_ptr)
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;
bfd_size_type size;
if (symbols == NULL)
return FALSE;
if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT
| BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0
|| sym->section != sec)
return 0;
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
return FALSE;
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_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_asymbol_section (&q->symbol) == section
&& q->symbol.value >= low_func
&& q->symbol.value <= offset)
{
func = (asymbol *) q;
low_func = q->symbol.value;
}
break;
}
}
default:
return 0;
}
if (func == NULL)
return FALSE;
if ((sym->flags & BSF_LOCAL)
&& bfd_is_arm_special_symbol_name (sym->name,
BFD_ARM_SPECIAL_SYM_TYPE_ANY))
return 0;
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 arm_elf_find_function. */
static bfd_boolean
elf32_arm_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,
& elf_tdata (abfd)->dwarf2_find_line_info))
{
if (!*functionname_ptr)
arm_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 ARM 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 (! arm_elf_find_function (abfd, symbols, section, offset,
filename_ptr, functionname_ptr))
return FALSE;
*line_ptr = 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;
}
static bfd_boolean
@ -20488,7 +20407,6 @@ elf32_arm_backend_symbol_processing (bfd *abfd, asymbol *sym)
#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
@ -20496,6 +20414,7 @@ elf32_arm_backend_symbol_processing (bfd *abfd, asymbol *sym)
#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

View File

@ -7999,122 +7999,43 @@ elfNN_aarch64_is_target_special_symbol (bfd *abfd ATTRIBUTE_UNUSED,
BFD_AARCH64_SPECIAL_SYM_TYPE_ANY);
}
/* This is a version of _bfd_elf_find_function() from dwarf2.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_boolean
aarch64_elf_find_function (bfd * abfd,
asymbol ** symbols,
asection * section,
bfd_vma offset,
const char ** filename_ptr,
const char ** functionname_ptr)
static bfd_size_type
elfNN_aarch64_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;
bfd_size_type size;
if (symbols == NULL)
return FALSE;
if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT
| BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0
|| sym->section != sec)
return 0;
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
return FALSE;
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_asymbol_section (&q->symbol) == section
&& q->symbol.value >= low_func && q->symbol.value <= offset)
{
func = (asymbol *) q;
low_func = q->symbol.value;
}
break;
}
}
default:
return 0;
}
if (func == NULL)
return FALSE;
if ((sym->flags & BSF_LOCAL)
&& bfd_is_aarch64_special_symbol_name (sym->name,
BFD_AARCH64_SPECIAL_SYM_TYPE_ANY))
return 0;
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,
&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;
*line_ptr = 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;
}
static bfd_boolean
@ -10123,9 +10044,6 @@ const struct elf_size_info elfNN_aarch64_size_info =
#define bfd_elfNN_find_inliner_info \
elfNN_aarch64_find_inliner_info
#define bfd_elfNN_find_nearest_line \
elfNN_aarch64_find_nearest_line
#define bfd_elfNN_get_synthetic_symtab \
elfNN_aarch64_get_synthetic_symtab
@ -10170,6 +10088,9 @@ const struct elf_size_info elfNN_aarch64_size_info =
#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

View File

@ -13078,27 +13078,17 @@ _bfd_mips_elf_find_nearest_line (bfd *abfd, asymbol **symbols,
filename_ptr, functionname_ptr,
line_ptr, discriminator_ptr,
dwarf_debug_sections,
&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))
{
/* PR 22789: If the function name or filename was not found through
the debug information, then try an ordinary lookup instead. */
if ((functionname_ptr != NULL && *functionname_ptr == NULL)
|| (filename_ptr != NULL && *filename_ptr == NULL))
{
/* Do not override already discovered names. */
if (functionname_ptr != NULL && *functionname_ptr != NULL)
functionname_ptr = NULL;
if (filename_ptr != NULL && *filename_ptr != NULL)
filename_ptr = NULL;
_bfd_elf_find_function (abfd, symbols, section, offset,
filename_ptr, functionname_ptr);
}
if (!*functionname_ptr)
_bfd_elf_find_function (abfd, symbols, section, offset,
*filename_ptr ? NULL : filename_ptr,
functionname_ptr);
return TRUE;
}