PR23652, Use symbols from debug bfd for _bfd_elf_find_function

Message ID 20191127013553.GE9080@bubble.grove.modra.org
State New
Headers show
Series
  • PR23652, Use symbols from debug bfd for _bfd_elf_find_function
Related show

Commit Message

Alan Modra Nov. 27, 2019, 1:35 a.m.
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.


-- 
Alan Modra
Australia Development Lab, IBM

Comments

Alan Modra Nov. 27, 2019, 8:41 a.m. | #1
On Wed, Nov 27, 2019 at 12:05:53PM +1030, Alan Modra wrote:
> 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.


Well, it does look at symbols, but not ideally.  There were a number
of problems with the patch.  Firstly, _bfd_dwarf2_stash_syms didn't do
anything when the original file had dynamic symbols, and secondly,
info found by the symbol search didn't make it out of
_bfd_elf_find_nearest_line except in the case of DWARF functions
without external linkage.

	PR 23652
	* dwarf2.c (_bfd_dwarf2_stash_syms): Break out of loop on finding
	matching section.
	(_bfd_dwarf2_find_nearest_line): Return an int, with value 2 when
	returning info from the symbol table.  Do the _bfd_elf_find_function
	search also when !found.  Call _bfd_dwarf2_stash_syms regardless of
	symbols.
	* elf64-alpha.c (elf64_alpha_find_nearest_line): Accept dwarf2
	result of 1 only.
	* elfxx-mips.c (_bfd_mips_elf_find_nearest_line): Likewise.
	* libbfd-in.h (_bfd_dwarf2_find_nearest_line): Update prototype.
	* libbfd.h: Regenerate.

diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index e42483a535..a25f76ac2b 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -3923,6 +3923,7 @@ _bfd_dwarf2_stash_syms (struct dwarf2_debug *stash, bfd *abfd,
 	    {
 	      *sec = d;
 	      *syms = stash->syms;
+	      break;
 	    }
 	}
     }
@@ -4692,15 +4693,19 @@ _bfd_dwarf2_find_symbol_bias (asymbol ** symbols, void ** pinfo)
 /* Find the source code location of SYMBOL.  If SYMBOL is NULL
    then find the nearest source code location corresponding to
    the address SECTION + OFFSET.
-   Returns TRUE if the line is found without error and fills in
+   Returns 1 if the line is found without error and fills in
    FILENAME_PTR and LINENUMBER_PTR.  In the case where SYMBOL was
    NULL the FUNCTIONNAME_PTR is also filled in.
+   Returns 2 if partial information from _bfd_elf_find_function is
+   returned (function and maybe file) by looking at symbols.  DWARF2
+   info is present but not regarding the requested code location.
+   Returns 0 otherwise.
    SYMBOLS contains the symbol table for ABFD.
    DEBUG_SECTIONS contains the name of the dwarf debug sections.
    field and in the abbreviation offset, or zero to indicate that the
    default value should be used.  */
 
-bfd_boolean
+int
 _bfd_dwarf2_find_nearest_line (bfd *abfd,
 			       asymbol **symbols,
 			       asymbol *symbol,
@@ -4726,7 +4731,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
   bfd_vma addr;
   struct comp_unit* each;
   struct funcinfo *function = NULL;
-  bfd_boolean found = FALSE;
+  int found = FALSE;
   bfd_boolean do_line;
 
   *filename_ptr = NULL;
@@ -4925,19 +4930,21 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
   if (functionname_ptr && function && function->is_linkage)
     *functionname_ptr = function->name;
   else if (functionname_ptr
-	   && ((found && !*functionname_ptr)
+	   && (!*functionname_ptr
 	       || (function && !function->is_linkage)))
     {
       asymbol *fun;
       asymbol **syms = symbols;
       asection *sec = section;
 
-      if (symbols == NULL || *symbols == NULL)
-	_bfd_dwarf2_stash_syms (stash, abfd, &sec, &syms);
+      _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)
 	{
 	  bfd_vma sec_vma;
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index d4ac0c1469..f312a6e03d 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -1468,7 +1468,8 @@ elf64_alpha_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))
+				     &elf_tdata (abfd)->dwarf2_find_line_info)
+      == 1)
     return TRUE;
 
   msec = bfd_get_section_by_name (abfd, ".mdebug");
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index e9af7abd4b..b1f83a0545 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -13078,7 +13078,8 @@ _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))
+				     &elf_tdata (abfd)->dwarf2_find_line_info)
+      == 1)
     return TRUE;
 
   if (_bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index f498ffd5e7..64ae6c6e91 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -596,7 +596,7 @@ struct dwarf_debug_section
 extern const struct dwarf_debug_section dwarf_debug_sections[] ATTRIBUTE_HIDDEN;
 
 /* Find the nearest line using DWARF 2 debugging information.  */
-extern bfd_boolean _bfd_dwarf2_find_nearest_line
+extern int _bfd_dwarf2_find_nearest_line
   (bfd *, asymbol **, asymbol *, asection *, bfd_vma,
    const char **, const char **, unsigned int *, unsigned int *,
    const struct dwarf_debug_section *, void **) ATTRIBUTE_HIDDEN;

-- 
Alan Modra
Australia Development Lab, IBM

Patch

diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index c3d9ffc3c5..e42483a535 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -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);
 
diff --git a/bfd/elf.c b/bfd/elf.c
index a4f26dac71..1aa2603ee8 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -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,
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index dca208f06a..37b5b64dc6 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -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)
-{
-  const char * filename = NULL;
-  asymbol * func = NULL;
-  bfd_vma low_func = 0;
-  asymbol ** p;
-
-  if (symbols == NULL)
-    return FALSE;
-
-  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
-    return FALSE;
-
-  for (p = symbols; *p != NULL; p++)
-    {
-      elf_symbol_type *q;
+static bfd_size_type
+elf32_arm_maybe_function_sym (const asymbol *sym, asection *sec,
+			      bfd_vma *code_off)
+{
+  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_asymbol_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 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;
+	default:
+	  return 0;
+      }
 
-  if (! arm_elf_find_function (abfd, symbols, section, offset,
-			       filename_ptr, functionname_ptr))
-    return FALSE;
+  if ((sym->flags & BSF_LOCAL)
+      && bfd_is_arm_special_symbol_name (sym->name,
+					 BFD_ARM_SPECIAL_SYM_TYPE_ANY))
+    return 0;
 
-  *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
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index a71071161c..51d7526a72 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -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)
-{
-  const char *filename = NULL;
-  asymbol *func = NULL;
-  bfd_vma low_func = 0;
-  asymbol **p;
-
-  if (symbols == NULL)
-    return FALSE;
-
-  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
-    return FALSE;
-
-  for (p = symbols; *p != NULL; p++)
-    {
-      elf_symbol_type *q;
+static bfd_size_type
+elfNN_aarch64_maybe_function_sym (const asymbol *sym, asection *sec,
+				  bfd_vma *code_off)
+{
+  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_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;
-	}
-    }
-
-  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,
-				     &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;
+	default:
+	  return 0;
+      }
 
-  if (!aarch64_elf_find_function (abfd, symbols, section, offset,
-				  filename_ptr, functionname_ptr))
-    return FALSE;
+  if ((sym->flags & BSF_LOCAL)
+      && bfd_is_aarch64_special_symbol_name (sym->name,
+					     BFD_AARCH64_SPECIAL_SYM_TYPE_ANY))
+    return 0;
 
-  *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
 
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 3982ed25e9..e9af7abd4b 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -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))
-    {
-      /* 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);
-	}
+				     &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,
+				*filename_ptr ? NULL : filename_ptr,
+				functionname_ptr);
       return TRUE;
     }