This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PR15106 elf_find_function segfault
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org
- Date: Fri, 8 Feb 2013 17:40:39 +1030
- Subject: PR15106 elf_find_function segfault
I shouldn't have used static vars.. As reported, if a BFD is opened,
elf_find_function called, the BFD closed, then another BFD opened, it
is possible for sections in the second BFD to exactly match addresses
used by the first BFD. A call to elf_find_function might then cause a
segfault as the cache is seen to be current but "func" might not be
pointing at valid memory. This can even happen after the last patch
that tested for a change in the "symbols" pointer. So put the cache
on the BFD tdata, which is zeroed on open.
PR binutils/15106
* elf-bfd.h (struct elf_obj_tdata): Add elf_find_function_cache.
* elf.c (elf_find_function): Revert last change. Use new
tdata field rather than static vars for cache.
Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.357
diff -u -p -r1.357 elf-bfd.h
--- bfd/elf-bfd.h 6 Feb 2013 23:22:08 -0000 1.357
+++ bfd/elf-bfd.h 8 Feb 2013 00:32:31 -0000
@@ -1598,6 +1598,9 @@ struct elf_obj_tdata
/* A place to stash dwarf2 info for this bfd. */
void *dwarf2_find_line_info;
+ /* Stash away info for yet another find line/function variant. */
+ void *elf_find_function_cache;
+
/* An array of stub sections indexed by symbol number, used by the
MIPS ELF linker. FIXME: We should figure out some way to only
include this field for a MIPS ELF target. */
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.583
diff -u -p -r1.583 elf.c
--- bfd/elf.c 7 Feb 2013 04:20:31 -0000 1.583
+++ bfd/elf.c 8 Feb 2013 06:37:59 -0000
@@ -7504,20 +7504,29 @@ elf_find_function (bfd *abfd,
const char **filename_ptr,
const char **functionname_ptr)
{
- static asection *last_section;
- static asymbol **last_symbols;
- static asymbol *func;
- static const char *filename;
- static bfd_size_type func_size;
+ struct elf_find_function_cache
+ {
+ asection *last_section;
+ asymbol *func;
+ const char *filename;
+ bfd_size_type func_size;
+ } *cache;
if (symbols == NULL)
return FALSE;
- if (last_section != section
- || last_symbols != symbols
- || func == NULL
- || offset < func->value
- || offset >= func->value + func_size)
+ cache = elf_tdata (abfd)->elf_find_function_cache;
+ if (cache == NULL)
+ {
+ cache = bfd_zalloc (abfd, sizeof (*cache));
+ elf_tdata (abfd)->elf_find_function_cache = cache;
+ if (cache == NULL)
+ return FALSE;
+ }
+ if (cache->last_section != section
+ || cache->func == NULL
+ || offset < cache->func->value
+ || offset >= cache->func->value + cache->func_size)
{
asymbol *file;
bfd_vma low_func;
@@ -7533,14 +7542,13 @@ elf_find_function (bfd *abfd,
enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- filename = NULL;
- func = NULL;
file = NULL;
low_func = 0;
state = nothing_seen;
- func_size = 0;
- last_section = section;
- last_symbols = symbols;
+ cache->filename = NULL;
+ cache->func = NULL;
+ cache->func_size = 0;
+ cache->last_section = section;
for (p = symbols; *p != NULL; p++)
{
@@ -7561,29 +7569,29 @@ elf_find_function (bfd *abfd,
&& code_off <= offset
&& (code_off > low_func
|| (code_off == low_func
- && size > func_size)))
+ && size > cache->func_size)))
{
- func = sym;
- func_size = size;
+ cache->func = sym;
+ cache->func_size = size;
+ cache->filename = NULL;
low_func = code_off;
- filename = NULL;
if (file != NULL
&& ((sym->flags & BSF_LOCAL) != 0
|| state != file_after_symbol_seen))
- filename = bfd_asymbol_name (file);
+ cache->filename = bfd_asymbol_name (file);
}
if (state == nothing_seen)
state = symbol_seen;
}
}
- if (func == NULL)
+ if (cache->func == NULL)
return FALSE;
if (filename_ptr)
- *filename_ptr = filename;
+ *filename_ptr = cache->filename;
if (functionname_ptr)
- *functionname_ptr = bfd_asymbol_name (func);
+ *functionname_ptr = bfd_asymbol_name (cache->func);
return TRUE;
}
--
Alan Modra
Australia Development Lab, IBM