public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
* [binutils-gdb] Fix _bfd_elf_find_function so that it can cope with overlapping symbols
@ 2023-02-23 17:27 Nick Clifton
  0 siblings, 0 replies; only message in thread
From: Nick Clifton @ 2023-02-23 17:27 UTC (permalink / raw)
  To: bfd-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=c32ea73114dfdd161098f11f2590acd71603a397

commit c32ea73114dfdd161098f11f2590acd71603a397
Author: Nick Clifton <nickc@redhat.com>
Date:   Thu Feb 23 17:27:07 2023 +0000

    Fix _bfd_elf_find_function so that it can cope with overlapping symbols

Diff:
---
 bfd/dwarf2.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 82 insertions(+), 22 deletions(-)

diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 8c9bd7a3026..ac7c4f63c57 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -4681,6 +4681,7 @@ comp_unit_find_nearest_line (struct comp_unit *unit,
 
   *function_ptr = NULL;
   func_p = lookup_address_in_function_table (unit, addr, function_ptr);
+
   if (func_p && (*function_ptr)->tag == DW_TAG_inlined_subroutine)
     unit->stash->inliner_chain = *function_ptr;
 
@@ -6134,6 +6135,60 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abfd, void **pinfo)
     bfd_close (stash->alt.bfd_ptr);
 }
 
+typedef struct elf_find_function_cache
+{
+  asection *     last_section;
+  asymbol *      func;
+  const char *   filename;
+  bfd_size_type  code_size;
+  bfd_vma        code_off;
+
+} elf_find_function_cache;
+
+
+/* Returns TRUE if the symbol with address CODE_OFF and size CODE_SIZE
+   is a better fit to match OFFSET than whatever is currenly stored in
+   CACHE.  */
+
+static inline bool
+better_fit (elf_find_function_cache *  cache,
+	    bfd_vma                    code_off,
+	    bfd_size_type              code_size,
+	    bfd_vma                    offset)
+{
+  /* If the symbol is beyond the desired offset, ignore it.  */
+  if (code_off > offset)
+    return false;
+
+  /* If the symbol is further away from the desired
+     offset than our current best, then ignore it.  */
+  if (code_off < cache->code_off)
+    return false;
+
+  /* On the other hand, if it is closer, then use it.  */
+  if (code_off > cache->code_off)
+    return true;
+
+  /* If our current best fit does not actually reach the desired
+     offset...  */
+  if (cache->code_off + cache->code_size <= offset)
+    {
+      /* Then return whichever candidate covers more area.  */
+      return code_size > cache->code_size;
+    }
+
+  /* If the new symbol also covers the desired offset... */
+  if (code_off + code_size > offset)
+    {
+      /* Then choose whichever is smaller.  */
+      /* FIXME: Maybe prefer LOCAL over GLOBAL or something else here ?  */
+      return code_size < cache->code_size;
+    }
+
+  /* Otherwise the cached symbol is better.  */
+  return false;
+}
+
 /* Find the function to a particular section and offset,
    for error reporting.  */
 
@@ -6145,21 +6200,14 @@ _bfd_elf_find_function (bfd *abfd,
 			const char **filename_ptr,
 			const char **functionname_ptr)
 {
-  struct elf_find_function_cache
-  {
-    asection *last_section;
-    asymbol *func;
-    const char *filename;
-    bfd_size_type func_size;
-  } *cache;
-
   if (symbols == NULL)
     return NULL;
 
   if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
     return NULL;
 
-  cache = elf_tdata (abfd)->elf_find_function_cache;
+  elf_find_function_cache * cache = elf_tdata (abfd)->elf_find_function_cache;
+
   if (cache == NULL)
     {
       cache = bfd_zalloc (abfd, sizeof (*cache));
@@ -6167,13 +6215,13 @@ _bfd_elf_find_function (bfd *abfd,
       if (cache == NULL)
 	return NULL;
     }
+
   if (cache->last_section != section
       || cache->func == NULL
       || offset < cache->func->value
-      || offset >= cache->func->value + cache->func_size)
+      || offset >= cache->func->value + cache->code_size)
     {
       asymbol *file;
-      bfd_vma low_func;
       asymbol **p;
       /* ??? Given multiple file symbols, it is impossible to reliably
 	 choose the right file name for global symbols.  File symbols are
@@ -6187,11 +6235,11 @@ _bfd_elf_find_function (bfd *abfd,
       const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
       file = NULL;
-      low_func = 0;
       state = nothing_seen;
       cache->filename = NULL;
       cache->func = NULL;
-      cache->func_size = 0;
+      cache->code_size = 0;
+      cache->code_off = 0;
       cache->last_section = section;
 
       for (p = symbols; *p != NULL; p++)
@@ -6208,24 +6256,36 @@ _bfd_elf_find_function (bfd *abfd,
 	      continue;
 	    }
 
+	  if (state == nothing_seen)
+	    state = symbol_seen;
+
 	  size = bed->maybe_function_sym (sym, section, &code_off);
-	  if (size != 0
-	      && code_off <= offset
-	      && (code_off > low_func
-		  || (code_off == low_func
-		      && size > cache->func_size)))
+
+	  if (size == 0)
+	    continue;
+
+	  if (better_fit (cache, code_off, size, offset))
 	    {
 	      cache->func = sym;
-	      cache->func_size = size;
+	      cache->code_size = size;
+	      cache->code_off = code_off;
 	      cache->filename = NULL;
-	      low_func = code_off;
+
 	      if (file != NULL
 		  && ((sym->flags & BSF_LOCAL) != 0
 		      || state != file_after_symbol_seen))
 		cache->filename = bfd_asymbol_name (file);
 	    }
-	  if (state == nothing_seen)
-	    state = symbol_seen;
+	  /* Otherwise, if the symbol is beyond the desired offset but it
+	     lies within the bounds of the current best match then reduce
+	     the size of the current best match so that future searches
+	     will not not used the cached symbol by mistake.  */
+	  else if (code_off > offset 
+		   && code_off > cache->code_off
+		   && code_off < cache->code_off + cache->code_size)
+	    {
+	      cache->code_size = code_off - cache->code_off;
+	    }
 	}
     }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-02-23 17:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-23 17:27 [binutils-gdb] Fix _bfd_elf_find_function so that it can cope with overlapping symbols Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).