diff options
author | Nick Clifton <nickc@redhat.com> | 2023-02-24 12:25:50 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2023-02-24 12:25:50 +0000 |
commit | 7b1792f543161424ce60ff28b9d012a590e220b2 (patch) | |
tree | 4eb1db0784410f2acbfdda60954ce8e1a077e67a /bfd/dwarf2.c | |
parent | 18e7a6587e3f111e9367ea707f9eb21acf4b9af7 (diff) | |
download | gdb-7b1792f543161424ce60ff28b9d012a590e220b2.zip gdb-7b1792f543161424ce60ff28b9d012a590e220b2.tar.gz gdb-7b1792f543161424ce60ff28b9d012a590e220b2.tar.bz2 |
Enhance better_fit() function to prefer function symbols over non-function symbols.
Diffstat (limited to 'bfd/dwarf2.c')
-rw-r--r-- | bfd/dwarf2.c | 52 |
1 files changed, 37 insertions, 15 deletions
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index ac7c4f6..15862dc 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -6146,12 +6146,13 @@ typedef struct elf_find_function_cache } elf_find_function_cache; -/* Returns TRUE if the symbol with address CODE_OFF and size CODE_SIZE +/* Returns TRUE if symbol SYM 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, + asymbol * sym, bfd_vma code_off, bfd_size_type code_size, bfd_vma offset) @@ -6169,24 +6170,45 @@ better_fit (elf_find_function_cache * cache, if (code_off > cache->code_off) return true; + /* assert (code_off == cache->code_off); */ + /* 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; - } + /* ... then return whichever candidate covers + more area and hence gets closer to OFFSET. */ + 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; - } + /* The current cache'd symbol covers OFFSET. */ - /* Otherwise the cached symbol is better. */ - return false; + /* If the new symbol does not cover the desired offset then skip it. */ + if (code_off + code_size <= offset) + return false; + + /* Both symbols cover OFFSET. */ + + /* Prefer functions over non-functions. */ + flagword cache_flags = cache->func->flags; + flagword sym_flags = sym->flags; + + if ((cache_flags & BSF_FUNCTION) && ((sym_flags & BSF_FUNCTION) == 0)) + return false; + if ((sym_flags & BSF_FUNCTION) && ((cache_flags & BSF_FUNCTION) == 0)) + return true; + + /* FIXME: Should we choose LOCAL over GLOBAL ? */ + + /* Prefer typed symbols over notyped. */ + int cache_type = ELF_ST_TYPE (((elf_symbol_type *) cache->func)->internal_elf_sym.st_info); + int sym_type = ELF_ST_TYPE (((elf_symbol_type *) sym)->internal_elf_sym.st_info); + + if (cache_type == STT_NOTYPE && sym_type != STT_NOTYPE) + return true; + if (cache_type != STT_NOTYPE && sym_type == STT_NOTYPE) + return false; + + /* Otherwise choose whichever symbol covers a smaller area. */ + return code_size < cache->code_size; } /* Find the function to a particular section and offset, @@ -6264,7 +6286,7 @@ _bfd_elf_find_function (bfd *abfd, if (size == 0) continue; - if (better_fit (cache, code_off, size, offset)) + if (better_fit (cache, sym, code_off, size, offset)) { cache->func = sym; cache->code_size = size; |