public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
From: Nick Clifton <nickc@sourceware.org>
To: bfd-cvs@sourceware.org
Subject: [binutils-gdb] Fix _bfd_elf_find_function so that it can cope with overlapping symbols
Date: Thu, 23 Feb 2023 17:27:13 +0000 (GMT)	[thread overview]
Message-ID: <20230223172713.82C943858020@sourceware.org> (raw)

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;
+	    }
 	}
     }

                 reply	other threads:[~2023-02-23 17:27 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230223172713.82C943858020@sourceware.org \
    --to=nickc@sourceware.org \
    --cc=bfd-cvs@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).