-/* Find the function to a particular section and offset,
- for error reporting. */
-
-static bfd_boolean
-elf_find_function (bfd *abfd,
- asection *section,
- asymbol **symbols,
- bfd_vma offset,
- const char **filename_ptr,
- const char **functionname_ptr)
-{
- static asection *last_section;
- static asymbol *func;
- static const char *filename;
- static bfd_size_type func_size;
-
- if (symbols == NULL)
- return FALSE;
-
- if (last_section != section
- || func == NULL
- || offset < func->value
- || offset >= func->value + func_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
- local symbols, and thus all file symbols must sort before any
- global symbols. The ELF spec may be interpreted to say that a
- file symbol must sort before other local symbols, but currently
- ld -r doesn't do this. So, for ld -r output, it is possible to
- make a better choice of file name for local symbols by ignoring
- file symbols appearing after a given local symbol. */
- 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;
-
- for (p = symbols; *p != NULL; p++)
- {
- asymbol *sym = *p;
- bfd_vma code_off;
- bfd_size_type size;
-
- if ((sym->flags & BSF_FILE) != 0)
- {
- file = sym;
- if (state == symbol_seen)
- state = file_after_symbol_seen;
- continue;
- }
-
- size = bed->maybe_function_sym (sym, section, &code_off);
- if (size != 0
- && code_off <= offset
- && (code_off > low_func
- || (code_off == low_func
- && size > func_size)))
- {
- func = sym;
- func_size = size;
- low_func = code_off;
- filename = NULL;
- if (file != NULL
- && ((sym->flags & BSF_LOCAL) != 0
- || state != file_after_symbol_seen))
- filename = bfd_asymbol_name (file);
- }
- if (state == nothing_seen)
- state = symbol_seen;
- }
- }
-
- if (func == NULL)
- return FALSE;
-
- if (filename_ptr)
- *filename_ptr = filename;
- if (functionname_ptr)
- *functionname_ptr = bfd_asymbol_name (func);
-
- return TRUE;
-}
-