/* GDB routines for manipulating the minimal symbol tables.
- Copyright (C) 1992-2016 Free Software Foundation, Inc.
+ Copyright (C) 1992-2017 Free Software Foundation, Inc.
Contributed by Cygnus Support, using pieces from other GDB modules.
This file is part of GDB.
#include "language.h"
#include "cli/cli-utils.h"
#include "symbol.h"
+#include <algorithm>
+
+/* See minsyms.h. */
+
+bool
+msymbol_is_text (minimal_symbol *msymbol)
+{
+ switch (MSYMBOL_TYPE (msymbol))
+ {
+ case mst_text:
+ case mst_text_gnu_ifunc:
+ case mst_solib_trampoline:
+ case mst_file_text:
+ return true;
+ default:
+ return false;
+ }
+}
/* Accumulate the minimal symbols for each objfile in bunches of BUNCH_SIZE.
At the end, copy them all into one newly allocated location on an objfile's
struct minimal_symbol contents[BUNCH_SIZE];
};
-/* Bunch currently being filled up.
- The next field points to chain of filled bunches. */
-
-static struct msym_bunch *msym_bunch;
-
-/* Number of slots filled in current bunch. */
-
-static int msym_bunch_index;
-
-/* Total number of minimal symbols recorded so far for the objfile. */
-
-static int msym_count;
-
/* See minsyms.h. */
unsigned int
while (*string && *string != '(')
{
- string = skip_spaces_const (string);
+ string = skip_spaces (string);
if (*string && *string != '(')
{
hash = SYMBOL_HASH_NEXT (hash, *string);
TABLE. */
static void
add_minsym_to_demangled_hash_table (struct minimal_symbol *sym,
- struct minimal_symbol **table)
+ struct objfile *objfile)
{
if (sym->demangled_hash_next == NULL)
{
- unsigned int hash = msymbol_hash_iw (MSYMBOL_SEARCH_NAME (sym))
- % MINIMAL_SYMBOL_HASH_SIZE;
+ unsigned int hash = search_name_hash (MSYMBOL_LANGUAGE (sym),
+ MSYMBOL_SEARCH_NAME (sym));
+
+ auto &vec = objfile->per_bfd->demangled_hash_languages;
+ auto it = std::lower_bound (vec.begin (), vec.end (),
+ MSYMBOL_LANGUAGE (sym));
+ if (it == vec.end () || *it != MSYMBOL_LANGUAGE (sym))
+ vec.insert (it, MSYMBOL_LANGUAGE (sym));
+
+ struct minimal_symbol **table
+ = objfile->per_bfd->msymbol_demangled_hash;
+ unsigned int hash_index = hash % MINIMAL_SYMBOL_HASH_SIZE;
+ sym->demangled_hash_next = table[hash_index];
+ table[hash_index] = sym;
+ }
+}
- sym->demangled_hash_next = table[hash];
- table[hash] = sym;
+/* Worker object for lookup_minimal_symbol. Stores temporary results
+ while walking the symbol tables. */
+
+struct found_minimal_symbols
+{
+ /* External symbols are best. */
+ bound_minimal_symbol external_symbol {};
+
+ /* File-local symbols are next best. */
+ bound_minimal_symbol file_symbol {};
+
+ /* Symbols for shared library trampolines are next best. */
+ bound_minimal_symbol trampoline_symbol {};
+
+ /* Called when a symbol name matches. Check if the minsym is a
+ better type than what we had already found, and record it in one
+ of the members fields if so. Returns true if we collected the
+ real symbol, in which case we can stop searching. */
+ bool maybe_collect (const char *sfile, objfile *objf,
+ minimal_symbol *msymbol);
+};
+
+/* See declaration above. */
+
+bool
+found_minimal_symbols::maybe_collect (const char *sfile,
+ struct objfile *objfile,
+ minimal_symbol *msymbol)
+{
+ switch (MSYMBOL_TYPE (msymbol))
+ {
+ case mst_file_text:
+ case mst_file_data:
+ case mst_file_bss:
+ if (sfile == NULL
+ || filename_cmp (msymbol->filename, sfile) == 0)
+ {
+ file_symbol.minsym = msymbol;
+ file_symbol.objfile = objfile;
+ }
+ break;
+
+ case mst_solib_trampoline:
+
+ /* If a trampoline symbol is found, we prefer to keep
+ looking for the *real* symbol. If the actual symbol
+ is not found, then we'll use the trampoline
+ entry. */
+ if (trampoline_symbol.minsym == NULL)
+ {
+ trampoline_symbol.minsym = msymbol;
+ trampoline_symbol.objfile = objfile;
+ }
+ break;
+
+ case mst_unknown:
+ default:
+ external_symbol.minsym = msymbol;
+ external_symbol.objfile = objfile;
+ /* We have the real symbol. No use looking further. */
+ return true;
+ }
+
+ /* Keep looking. */
+ return false;
+}
+
+/* Walk the mangled name hash table, and pass each symbol whose name
+ matches LOOKUP_NAME according to NAMECMP to FOUND. */
+
+static void
+lookup_minimal_symbol_mangled (const char *lookup_name,
+ const char *sfile,
+ struct objfile *objfile,
+ struct minimal_symbol **table,
+ unsigned int hash,
+ int (*namecmp) (const char *, const char *),
+ found_minimal_symbols &found)
+{
+ for (minimal_symbol *msymbol = table[hash];
+ msymbol != NULL;
+ msymbol = msymbol->hash_next)
+ {
+ const char *symbol_name = MSYMBOL_LINKAGE_NAME (msymbol);
+
+ if (namecmp (symbol_name, lookup_name) == 0
+ && found.maybe_collect (sfile, objfile, msymbol))
+ return;
+ }
+}
+
+/* Walk the demangled name hash table, and pass each symbol whose name
+ matches LOOKUP_NAME according to MATCHER to FOUND. */
+
+static void
+lookup_minimal_symbol_demangled (const lookup_name_info &lookup_name,
+ const char *sfile,
+ struct objfile *objfile,
+ struct minimal_symbol **table,
+ unsigned int hash,
+ symbol_name_matcher_ftype *matcher,
+ found_minimal_symbols &found)
+{
+ for (minimal_symbol *msymbol = table[hash];
+ msymbol != NULL;
+ msymbol = msymbol->demangled_hash_next)
+ {
+ const char *symbol_name = MSYMBOL_SEARCH_NAME (msymbol);
+
+ if (matcher (symbol_name, lookup_name, NULL)
+ && found.maybe_collect (sfile, objfile, msymbol))
+ return;
}
}
struct objfile *objf)
{
struct objfile *objfile;
- struct bound_minimal_symbol found_symbol = { NULL, NULL };
- struct bound_minimal_symbol found_file_symbol = { NULL, NULL };
- struct bound_minimal_symbol trampoline_symbol = { NULL, NULL };
+ found_minimal_symbols found;
- unsigned int hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE;
- unsigned int dem_hash = msymbol_hash_iw (name) % MINIMAL_SYMBOL_HASH_SIZE;
+ unsigned int mangled_hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE;
- int needtofreename = 0;
- const char *modified_name;
+ auto *mangled_cmp
+ = (case_sensitivity == case_sensitive_on
+ ? strcmp
+ : strcasecmp);
if (sfile != NULL)
sfile = lbasename (sfile);
- /* For C++, canonicalize the input name. */
- modified_name = name;
- if (current_language->la_language == language_cplus)
- {
- char *cname = cp_canonicalize_string (name);
-
- if (cname)
- {
- modified_name = cname;
- needtofreename = 1;
- }
- }
+ lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
for (objfile = object_files;
- objfile != NULL && found_symbol.minsym == NULL;
+ objfile != NULL && found.external_symbol.minsym == NULL;
objfile = objfile->next)
{
struct minimal_symbol *msymbol;
if (objf == NULL || objf == objfile
|| objf == objfile->separate_debug_objfile_backlink)
{
+ if (symbol_lookup_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_minimal_symbol (%s, %s, %s)\n",
+ name, sfile != NULL ? sfile : "NULL",
+ objfile_debug_name (objfile));
+ }
+
/* Do two passes: the first over the ordinary hash table,
and the second over the demangled hash table. */
- int pass;
+ lookup_minimal_symbol_mangled (name, sfile, objfile,
+ objfile->per_bfd->msymbol_hash,
+ mangled_hash, mangled_cmp, found);
- if (symbol_lookup_debug)
- {
- fprintf_unfiltered (gdb_stdlog,
- "lookup_minimal_symbol (%s, %s, %s)\n",
- name, sfile != NULL ? sfile : "NULL",
- objfile_debug_name (objfile));
- }
-
- for (pass = 1; pass <= 2 && found_symbol.minsym == NULL; pass++)
+ /* If not found, try the demangled hash table. */
+ if (found.external_symbol.minsym == NULL)
{
- /* Select hash list according to pass. */
- if (pass == 1)
- msymbol = objfile->per_bfd->msymbol_hash[hash];
- else
- msymbol = objfile->per_bfd->msymbol_demangled_hash[dem_hash];
-
- while (msymbol != NULL && found_symbol.minsym == NULL)
+ /* Once for each language in the demangled hash names
+ table (usually just zero or one languages). */
+ for (auto lang : objfile->per_bfd->demangled_hash_languages)
{
- int match;
-
- if (pass == 1)
- {
- int (*cmp) (const char *, const char *);
-
- cmp = (case_sensitivity == case_sensitive_on
- ? strcmp : strcasecmp);
- match = cmp (MSYMBOL_LINKAGE_NAME (msymbol),
- modified_name) == 0;
- }
- else
- {
- /* The function respects CASE_SENSITIVITY. */
- match = MSYMBOL_MATCHES_SEARCH_NAME (msymbol,
- modified_name);
- }
-
- if (match)
- {
- switch (MSYMBOL_TYPE (msymbol))
- {
- case mst_file_text:
- case mst_file_data:
- case mst_file_bss:
- if (sfile == NULL
- || filename_cmp (msymbol->filename, sfile) == 0)
- {
- found_file_symbol.minsym = msymbol;
- found_file_symbol.objfile = objfile;
- }
- break;
-
- case mst_solib_trampoline:
-
- /* If a trampoline symbol is found, we prefer to
- keep looking for the *real* symbol. If the
- actual symbol is not found, then we'll use the
- trampoline entry. */
- if (trampoline_symbol.minsym == NULL)
- {
- trampoline_symbol.minsym = msymbol;
- trampoline_symbol.objfile = objfile;
- }
- break;
-
- case mst_unknown:
- default:
- found_symbol.minsym = msymbol;
- found_symbol.objfile = objfile;
- break;
- }
- }
-
- /* Find the next symbol on the hash chain. */
- if (pass == 1)
- msymbol = msymbol->hash_next;
- else
- msymbol = msymbol->demangled_hash_next;
+ unsigned int hash
+ = (lookup_name.search_name_hash (lang)
+ % MINIMAL_SYMBOL_HASH_SIZE);
+
+ symbol_name_matcher_ftype *match
+ = language_get_symbol_name_matcher (language_def (lang),
+ lookup_name);
+ struct minimal_symbol **msymbol_demangled_hash
+ = objfile->per_bfd->msymbol_demangled_hash;
+
+ lookup_minimal_symbol_demangled (lookup_name, sfile, objfile,
+ msymbol_demangled_hash,
+ hash, match, found);
+
+ if (found.external_symbol.minsym != NULL)
+ break;
}
}
}
}
- if (needtofreename)
- xfree ((void *) modified_name);
-
/* External symbols are best. */
- if (found_symbol.minsym != NULL)
+ if (found.external_symbol.minsym != NULL)
{
if (symbol_lookup_debug)
{
+ minimal_symbol *minsym = found.external_symbol.minsym;
+
fprintf_unfiltered (gdb_stdlog,
- "lookup_minimal_symbol (...) = %s"
- " (external)\n",
- host_address_to_string (found_symbol.minsym));
+ "lookup_minimal_symbol (...) = %s (external)\n",
+ host_address_to_string (minsym));
}
- return found_symbol;
+ return found.external_symbol;
}
/* File-local symbols are next best. */
- if (found_file_symbol.minsym != NULL)
+ if (found.file_symbol.minsym != NULL)
{
if (symbol_lookup_debug)
{
+ minimal_symbol *minsym = found.file_symbol.minsym;
+
fprintf_unfiltered (gdb_stdlog,
- "lookup_minimal_symbol (...) = %s"
- " (file-local)\n",
- host_address_to_string
- (found_file_symbol.minsym));
+ "lookup_minimal_symbol (...) = %s (file-local)\n",
+ host_address_to_string (minsym));
}
- return found_file_symbol;
+ return found.file_symbol;
}
/* Symbols for shared library trampolines are next best. */
- if (symbol_lookup_debug)
+ if (found.trampoline_symbol.minsym != NULL)
{
- fprintf_unfiltered (gdb_stdlog,
- "lookup_minimal_symbol (...) = %s%s\n",
- trampoline_symbol.minsym != NULL
- ? host_address_to_string (trampoline_symbol.minsym)
- : "NULL",
- trampoline_symbol.minsym != NULL
- ? " (trampoline)" : "");
+ if (symbol_lookup_debug)
+ {
+ minimal_symbol *minsym = found.trampoline_symbol.minsym;
+
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_minimal_symbol (...) = %s (trampoline)\n",
+ host_address_to_string (minsym));
+ }
+
+ return found.trampoline_symbol;
}
- return trampoline_symbol;
+
+ /* Not found. */
+ if (symbol_lookup_debug)
+ fprintf_unfiltered (gdb_stdlog, "lookup_minimal_symbol (...) = NULL\n");
+ return {};
}
/* See minsyms.h. */
/* See minsyms.h. */
void
-iterate_over_minimal_symbols (struct objfile *objf, const char *name,
+iterate_over_minimal_symbols (struct objfile *objf,
+ const lookup_name_info &lookup_name,
void (*callback) (struct minimal_symbol *,
void *),
void *user_data)
{
- unsigned int hash;
- struct minimal_symbol *iter;
- int (*cmp) (const char *, const char *);
/* The first pass is over the ordinary hash table. */
- hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE;
- iter = objf->per_bfd->msymbol_hash[hash];
- cmp = (case_sensitivity == case_sensitive_on ? strcmp : strcasecmp);
- while (iter)
{
- if (cmp (MSYMBOL_LINKAGE_NAME (iter), name) == 0)
- (*callback) (iter, user_data);
- iter = iter->hash_next;
+ const char *name = lookup_name.name ().c_str ();
+ unsigned int hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE;
+ auto *mangled_cmp
+ = (case_sensitivity == case_sensitive_on
+ ? strcmp
+ : strcasecmp);
+
+ for (minimal_symbol *iter = objf->per_bfd->msymbol_hash[hash];
+ iter != NULL;
+ iter = iter->hash_next)
+ {
+ if (mangled_cmp (MSYMBOL_LINKAGE_NAME (iter), name) == 0)
+ (*callback) (iter, user_data);
+ }
}
- /* The second pass is over the demangled table. */
- hash = msymbol_hash_iw (name) % MINIMAL_SYMBOL_HASH_SIZE;
- iter = objf->per_bfd->msymbol_demangled_hash[hash];
- while (iter)
+ /* The second pass is over the demangled table. Once for each
+ language in the demangled hash names table (usually just zero or
+ one). */
+ for (auto lang : objf->per_bfd->demangled_hash_languages)
{
- if (MSYMBOL_MATCHES_SEARCH_NAME (iter, name))
- (*callback) (iter, user_data);
- iter = iter->demangled_hash_next;
+ const language_defn *lang_def = language_def (lang);
+ symbol_name_matcher_ftype *name_match
+ = language_get_symbol_name_matcher (lang_def, lookup_name);
+
+ unsigned int hash
+ = lookup_name.search_name_hash (lang) % MINIMAL_SYMBOL_HASH_SIZE;
+ for (minimal_symbol *iter = objf->per_bfd->msymbol_demangled_hash[hash];
+ iter != NULL;
+ iter = iter->demangled_hash_next)
+ if (name_match (MSYMBOL_SEARCH_NAME (iter), lookup_name, NULL))
+ (*callback) (iter, user_data);
}
}
/* See minsyms.h. */
minimal_symbol_reader::minimal_symbol_reader (struct objfile *obj)
-: m_objfile (obj)
-{
- msym_count = 0;
- msym_bunch = NULL;
- /* Note that presetting msym_bunch_index to BUNCH_SIZE causes the
+: m_objfile (obj),
+ m_msym_bunch (NULL),
+ /* Note that presetting m_msym_bunch_index to BUNCH_SIZE causes the
first call to save a minimal symbol to allocate the memory for
the first bunch. */
- msym_bunch_index = BUNCH_SIZE;
+ m_msym_bunch_index (BUNCH_SIZE),
+ m_msym_count (0)
+{
}
/* Discard the currently collected minimal symbols, if any. If we wish
{
struct msym_bunch *next;
- while (msym_bunch != NULL)
+ while (m_msym_bunch != NULL)
{
- next = msym_bunch->next;
- xfree (msym_bunch);
- msym_bunch = next;
+ next = m_msym_bunch->next;
+ xfree (m_msym_bunch);
+ m_msym_bunch = next;
}
}
/* See minsyms.h. */
void
-prim_record_minimal_symbol (const char *name, CORE_ADDR address,
- enum minimal_symbol_type ms_type,
- struct objfile *objfile)
+minimal_symbol_reader::record (const char *name, CORE_ADDR address,
+ enum minimal_symbol_type ms_type)
{
int section;
case mst_text_gnu_ifunc:
case mst_file_text:
case mst_solib_trampoline:
- section = SECT_OFF_TEXT (objfile);
+ section = SECT_OFF_TEXT (m_objfile);
break;
case mst_data:
case mst_file_data:
- section = SECT_OFF_DATA (objfile);
+ section = SECT_OFF_DATA (m_objfile);
break;
case mst_bss:
case mst_file_bss:
- section = SECT_OFF_BSS (objfile);
+ section = SECT_OFF_BSS (m_objfile);
break;
default:
section = -1;
}
- prim_record_minimal_symbol_and_info (name, address, ms_type,
- section, objfile);
+ record_with_info (name, address, ms_type, section);
}
/* See minsyms.h. */
struct minimal_symbol *
-prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name,
- CORE_ADDR address,
- enum minimal_symbol_type ms_type,
- int section,
- struct objfile *objfile)
+minimal_symbol_reader::record_full (const char *name, int name_len,
+ bool copy_name, CORE_ADDR address,
+ enum minimal_symbol_type ms_type,
+ int section)
{
struct msym_bunch *newobj;
struct minimal_symbol *msymbol;
/* It's safe to strip the leading char here once, since the name
is also stored stripped in the minimal symbol table. */
- if (name[0] == get_symbol_leading_char (objfile->obfd))
+ if (name[0] == get_symbol_leading_char (m_objfile->obfd))
{
++name;
--name_len;
if (ms_type == mst_file_text && startswith (name, "__gnu_compiled"))
return (NULL);
- if (msym_bunch_index == BUNCH_SIZE)
+ if (m_msym_bunch_index == BUNCH_SIZE)
{
newobj = XCNEW (struct msym_bunch);
- msym_bunch_index = 0;
- newobj->next = msym_bunch;
- msym_bunch = newobj;
+ m_msym_bunch_index = 0;
+ newobj->next = m_msym_bunch;
+ m_msym_bunch = newobj;
}
- msymbol = &msym_bunch->contents[msym_bunch_index];
+ msymbol = &m_msym_bunch->contents[m_msym_bunch_index];
MSYMBOL_SET_LANGUAGE (msymbol, language_auto,
- &objfile->per_bfd->storage_obstack);
- MSYMBOL_SET_NAMES (msymbol, name, name_len, copy_name, objfile);
+ &m_objfile->per_bfd->storage_obstack);
+ MSYMBOL_SET_NAMES (msymbol, name, name_len, copy_name, m_objfile);
SET_MSYMBOL_VALUE_ADDRESS (msymbol, address);
MSYMBOL_SECTION (msymbol) = section;
/* If we already read minimal symbols for this objfile, then don't
ever allocate a new one. */
- if (!objfile->per_bfd->minsyms_read)
+ if (!m_objfile->per_bfd->minsyms_read)
{
- msym_bunch_index++;
- objfile->per_bfd->n_minsyms++;
+ m_msym_bunch_index++;
+ m_objfile->per_bfd->n_minsyms++;
}
- msym_count++;
+ m_msym_count++;
return msymbol;
}
-/* See minsyms.h. */
-
-struct minimal_symbol *
-prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
- enum minimal_symbol_type ms_type,
- int section,
- struct objfile *objfile)
-{
- return prim_record_minimal_symbol_full (name, strlen (name), 1,
- address, ms_type,
- section, objfile);
-}
-
/* Compare two minimal symbols by address and return a signed result based
on unsigned comparisons, so that we sort into unsigned numeric order.
Within groups with the same address, sort by name. */
msym->demangled_hash_next = 0;
if (MSYMBOL_SEARCH_NAME (msym) != MSYMBOL_LINKAGE_NAME (msym))
- add_minsym_to_demangled_hash_table (msym,
- objfile->per_bfd->msymbol_demangled_hash);
+ add_minsym_to_demangled_hash_table (msym, objfile);
}
}
if (m_objfile->per_bfd->minsyms_read)
return;
- if (msym_count > 0)
+ if (m_msym_count > 0)
{
if (symtab_create_debug)
{
fprintf_unfiltered (gdb_stdlog,
"Installing %d minimal symbols of objfile %s.\n",
- msym_count, objfile_name (m_objfile));
+ m_msym_count, objfile_name (m_objfile));
}
/* Allocate enough space in the obstack, into which we will gather the
compact out the duplicate entries. Once we have a final table,
we will give back the excess space. */
- alloc_count = msym_count + m_objfile->per_bfd->minimal_symbol_count + 1;
+ alloc_count = m_msym_count + m_objfile->per_bfd->minimal_symbol_count + 1;
obstack_blank (&m_objfile->per_bfd->storage_obstack,
alloc_count * sizeof (struct minimal_symbol));
msymbols = (struct minimal_symbol *)
mcount = m_objfile->per_bfd->minimal_symbol_count;
- for (bunch = msym_bunch; bunch != NULL; bunch = bunch->next)
+ for (bunch = m_msym_bunch; bunch != NULL; bunch = bunch->next)
{
- for (bindex = 0; bindex < msym_bunch_index; bindex++, mcount++)
+ for (bindex = 0; bindex < m_msym_bunch_index; bindex++, mcount++)
msymbols[mcount] = bunch->contents[bindex];
- msym_bunch_index = BUNCH_SIZE;
+ m_msym_bunch_index = BUNCH_SIZE;
}
/* Sort the minimal symbols by address. */