This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
RFC: save lots of memory
- From: Tom Tromey <tromey at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Wed, 04 Nov 2009 18:23:54 -0700
- Subject: RFC: save lots of memory
- Reply-to: tromey at redhat dot com
While running massif on gdb I found that, to my surprise,
symbol_set_names is a large space user. This is surprising because
there is no reason to copy symbol names, at least for DWARF -- they are
guaranteed to hang around until the objfile is destroyed.
This patch changes gdb so that such names are not copied. This saves a
lot of memory. For example, I ran OO.o writer and attached to it with
gdb (I have full debug info installed for OO.o and all its
dependencies).
Peak memory before: 219580200
Peak memory after : 198568560
Savings : 21011640
That is, we save about 10% of the heap.
I changed the contents of the demangled name hash; the new approach
saves memory if you assume that most mangled names do not need to be
copied and that names are on average longer than the width of a pointer.
I only updated the ELF and DWARF readers. I don't know enough about the
other readers to attempt those. As it stands, this patch will make
those use more memory. I think this is ok, but if it is a problem
either someone could fix the other readers, or we could have two
demangled hashes.
The signal to symbol_set_names that a name does not need to be copied is
passing -1 for the name length. I don't consider that to be too gross,
but I realize others may disagree.
We might be able to save a bit more memory using this same technique, by
not copying the filename argument to allocate_psymtab. According to
massif this accounts for 5791200 bytes in my test run -- but I don't
know how many of those do not need to be copied. Putting the file names
into the bcache might also help.
Let me know what you think.
Tom
2009-11-04 Tom Tromey <tromey@redhat.com>
* symtab.h (prim_record_minimal_symbol_full): Declare.
* symtab.c (struct demangled_name_entry): New struct.
(hash_demangled_name_entry): New function.
(eq_demangled_name_entry): Likewise.
(create_demangled_names_hash): Use new functions.
(symbol_set_names): Allow len==-1. Use struct
demangled_name_entry.
* minsyms.c (prim_record_minimal_symbol_full): New function.
(prim_record_minimal_symbol_and_info): Use it.
* elfread.c (record_minimal_symbol): Add name_len argument. Call
prim_record_minimal_symbol_full.
(elf_symtab_read): Add copy_names argument. Pass -1 to
record_minimal_symbol when appropriate.
(elf_symfile_read): Update calls to elf_symtab_read.
* dwarf2read.c (add_partial_symbol): Pass -1 to
add_psymbol_to_list when appropriate.
(load_partial_dies): Likewise.
(new_symbol): Pass -1 to SYMBOL_SET_NAMES.
* cp-namespace.c (check_one_possible_namespace_symbol): Don't save
name on the obstack. Pass TYPE_NAME and length of -1 to
SYMBOL_SET_NAMES.
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index d2d8f2e..0a3892d 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -714,7 +714,6 @@ check_one_possible_namespace_symbol (const char *name, int len,
if (sym == NULL)
{
struct type *type;
- name_copy = obsavestring (name, len, &objfile->objfile_obstack);
type = init_type (TYPE_CODE_NAMESPACE, 0, 0, name_copy, objfile);
@@ -723,7 +722,9 @@ check_one_possible_namespace_symbol (const char *name, int len,
sym = obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol));
memset (sym, 0, sizeof (struct symbol));
SYMBOL_LANGUAGE (sym) = language_cplus;
- SYMBOL_SET_NAMES (sym, name_copy, len, objfile);
+ /* Note that init_type copied the name to the objfile's
+ obstack. */
+ SYMBOL_SET_NAMES (sym, TYPE_NAME (type), -1, objfile);
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_TYPE (sym) = type;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 9bf89d7..3a80529 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -2391,7 +2391,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
const char *my_prefix;
const struct partial_symbol *psym = NULL;
CORE_ADDR baseaddr;
- int built_actual_name = 0;
+ int built_actual_name = 0, actual_name_len;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
@@ -2405,6 +2405,8 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
if (actual_name == NULL)
actual_name = pdi->name;
+ actual_name_len = built_actual_name ? strlen (actual_name) : -1;
+
switch (pdi->tag)
{
case DW_TAG_subprogram:
@@ -2416,7 +2418,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
in the global scope. */
/*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
mst_text, objfile); */
- psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+ psym = add_psymbol_to_list (actual_name, actual_name_len,
VAR_DOMAIN, LOC_BLOCK,
&objfile->global_psymbols,
0, pdi->lowpc + baseaddr,
@@ -2426,7 +2428,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
{
/*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
mst_file_text, objfile); */
- psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+ psym = add_psymbol_to_list (actual_name, actual_name_len,
VAR_DOMAIN, LOC_BLOCK,
&objfile->static_psymbols,
0, pdi->lowpc + baseaddr,
@@ -2452,7 +2454,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
if (pdi->locdesc)
addr = decode_locdesc (pdi->locdesc, cu);
if (pdi->locdesc || pdi->has_type)
- psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+ psym = add_psymbol_to_list (actual_name, actual_name_len,
VAR_DOMAIN, LOC_STATIC,
&objfile->global_psymbols,
0, addr + baseaddr,
@@ -2470,7 +2472,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
addr = decode_locdesc (pdi->locdesc, cu);
/*prim_record_minimal_symbol (actual_name, addr + baseaddr,
mst_file_data, objfile); */
- psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+ psym = add_psymbol_to_list (actual_name, actual_name_len,
VAR_DOMAIN, LOC_STATIC,
&objfile->static_psymbols,
0, addr + baseaddr,
@@ -2480,13 +2482,13 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
case DW_TAG_typedef:
case DW_TAG_base_type:
case DW_TAG_subrange_type:
- add_psymbol_to_list (actual_name, strlen (actual_name),
+ add_psymbol_to_list (actual_name, actual_name_len,
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
break;
case DW_TAG_namespace:
- add_psymbol_to_list (actual_name, strlen (actual_name),
+ add_psymbol_to_list (actual_name, actual_name_len,
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->global_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
@@ -2510,7 +2512,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
/* NOTE: carlton/2003-10-07: See comment in new_symbol about
static vs. global. */
- add_psymbol_to_list (actual_name, strlen (actual_name),
+ add_psymbol_to_list (actual_name, actual_name_len,
STRUCT_DOMAIN, LOC_TYPEDEF,
(cu->language == language_cplus
|| cu->language == language_java)
@@ -2520,7 +2522,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
break;
case DW_TAG_enumerator:
- add_psymbol_to_list (actual_name, strlen (actual_name),
+ add_psymbol_to_list (actual_name, actual_name_len,
VAR_DOMAIN, LOC_CONST,
(cu->language == language_cplus
|| cu->language == language_java)
@@ -6503,7 +6505,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
|| part_die->tag == DW_TAG_subrange_type))
{
if (building_psymtab && part_die->name != NULL)
- add_psymbol_to_list (part_die->name, strlen (part_die->name),
+ add_psymbol_to_list (part_die->name, -1,
VAR_DOMAIN, LOC_TYPEDEF,
&cu->objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, cu->objfile);
@@ -6524,7 +6526,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
if (part_die->name == NULL)
complaint (&symfile_complaints, _("malformed enumerator DIE ignored"));
else if (building_psymtab)
- add_psymbol_to_list (part_die->name, strlen (part_die->name),
+ add_psymbol_to_list (part_die->name, -1,
VAR_DOMAIN, LOC_CONST,
(cu->language == language_cplus
|| cu->language == language_java)
@@ -8304,7 +8306,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
/* Cache this symbol's name and the name's demangled form (if any). */
SYMBOL_LANGUAGE (sym) = cu->language;
- SYMBOL_SET_NAMES (sym, name, strlen (name), objfile);
+ SYMBOL_SET_NAMES (sym, name, -1, objfile);
/* Default assumptions.
Use the passed type or decode it from the die. */
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 131d7d2..ef45410 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -172,7 +172,7 @@ elf_locate_sections (bfd *ignore_abfd, asection *sectp, void *eip)
}
static struct minimal_symbol *
-record_minimal_symbol (char *name, CORE_ADDR address,
+record_minimal_symbol (const char *name, int name_len, CORE_ADDR address,
enum minimal_symbol_type ms_type,
asection *bfd_section, struct objfile *objfile)
{
@@ -181,8 +181,9 @@ record_minimal_symbol (char *name, CORE_ADDR address,
if (ms_type == mst_text || ms_type == mst_file_text)
address = gdbarch_smash_text_address (gdbarch, address);
- return prim_record_minimal_symbol_and_info
- (name, address, ms_type, bfd_section->index, bfd_section, objfile);
+ return prim_record_minimal_symbol_full (name, name_len, address,
+ ms_type, bfd_section->index,
+ bfd_section, objfile);
}
/*
@@ -216,7 +217,8 @@ record_minimal_symbol (char *name, CORE_ADDR address,
static void
elf_symtab_read (struct objfile *objfile, int type,
- long number_of_symbols, asymbol **symbol_table)
+ long number_of_symbols, asymbol **symbol_table,
+ int copy_names)
{
struct gdbarch *gdbarch = get_objfile_arch (objfile);
long storage_needed;
@@ -297,7 +299,8 @@ elf_symtab_read (struct objfile *objfile, int type,
symaddr += ANOFFSET (objfile->section_offsets, sect->index);
msym = record_minimal_symbol
- ((char *) sym->name, symaddr, mst_solib_trampoline, sect, objfile);
+ (sym->name, copy_names ? strlen (sym->name) : -1,
+ symaddr, mst_solib_trampoline, sect, objfile);
if (msym != NULL)
msym->filename = filesymname;
continue;
@@ -510,7 +513,7 @@ elf_symtab_read (struct objfile *objfile, int type,
continue; /* Skip this symbol. */
}
msym = record_minimal_symbol
- ((char *) sym->name, symaddr,
+ (sym->name, copy_names ? strlen (sym->name) : -1, symaddr,
ms_type, sym->section, objfile);
if (msym)
@@ -545,15 +548,11 @@ elf_symtab_read (struct objfile *objfile, int type,
if (len > 4 && strcmp (sym->name + len - 4, "@plt") == 0)
{
- char *base_name = xmalloc (len - 4 + 1);
struct minimal_symbol *mtramp;
- memcpy (base_name, sym->name, len - 4);
- base_name[len - 4] = '\0';
- mtramp = record_minimal_symbol (base_name, symaddr,
+ mtramp = record_minimal_symbol (sym->name, len - 4, symaddr,
mst_solib_trampoline,
sym->section, objfile);
- xfree (base_name);
if (mtramp)
{
MSYMBOL_SIZE (mtramp) = MSYMBOL_SIZE (msym);
@@ -638,7 +637,7 @@ elf_symfile_read (struct objfile *objfile, int mainline)
error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd),
bfd_errmsg (bfd_get_error ()));
- elf_symtab_read (objfile, ST_REGULAR, symcount, symbol_table);
+ elf_symtab_read (objfile, ST_REGULAR, symcount, symbol_table, 0);
}
/* Add the dynamic symbols. */
@@ -656,7 +655,7 @@ elf_symfile_read (struct objfile *objfile, int mainline)
error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd),
bfd_errmsg (bfd_get_error ()));
- elf_symtab_read (objfile, ST_DYNAMIC, dynsymcount, dyn_symbol_table);
+ elf_symtab_read (objfile, ST_DYNAMIC, dynsymcount, dyn_symbol_table, 0);
}
/* Add synthetic symbols - for instance, names for any PLT entries. */
@@ -674,7 +673,7 @@ elf_symfile_read (struct objfile *objfile, int mainline)
for (i = 0; i < synthcount; i++)
synth_symbol_table[i] = synthsyms + i;
make_cleanup (xfree, synth_symbol_table);
- elf_symtab_read (objfile, ST_SYNTHETIC, synthcount, synth_symbol_table);
+ elf_symtab_read (objfile, ST_SYNTHETIC, synthcount, synth_symbol_table, 1);
}
/* Install any minimal symbols that have been collected as the current
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index 64d20d2..39ed3bf 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -757,11 +757,12 @@ prim_record_minimal_symbol (const char *name, CORE_ADDR address,
newly created. */
struct minimal_symbol *
-prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
- enum minimal_symbol_type ms_type,
- int section,
- asection *bfd_section,
- struct objfile *objfile)
+prim_record_minimal_symbol_full (const char *name, int name_len,
+ CORE_ADDR address,
+ enum minimal_symbol_type ms_type,
+ int section,
+ asection *bfd_section,
+ struct objfile *objfile)
{
struct obj_section *obj_section;
struct msym_bunch *new;
@@ -780,7 +781,11 @@ prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
/* 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))
- ++name;
+ {
+ ++name;
+ if (name_len != -1)
+ --name_len;
+ }
if (ms_type == mst_file_text && strncmp (name, "__gnu_compiled", 14) == 0)
return (NULL);
@@ -795,7 +800,7 @@ prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
msymbol = &msym_bunch->contents[msym_bunch_index];
SYMBOL_INIT_LANGUAGE_SPECIFIC (msymbol, language_unknown);
SYMBOL_LANGUAGE (msymbol) = language_auto;
- SYMBOL_SET_NAMES (msymbol, (char *)name, strlen (name), objfile);
+ SYMBOL_SET_NAMES (msymbol, name, name_len, objfile);
SYMBOL_VALUE_ADDRESS (msymbol) = address;
SYMBOL_SECTION (msymbol) = section;
@@ -828,6 +833,21 @@ prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
return msymbol;
}
+/* Record a minimal symbol in the msym bunches. Returns the symbol
+ newly created. */
+
+struct minimal_symbol *
+prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
+ enum minimal_symbol_type ms_type,
+ int section,
+ asection *bfd_section,
+ struct objfile *objfile)
+{
+ return prim_record_minimal_symbol_full (name, strlen (name),
+ address, ms_type, section,
+ bfd_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. */
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 03586c3..211862e 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -427,6 +427,30 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
/* Functions to initialize a symbol's mangled name. */
+/* Objects of this type are stored in the demangled name hash table. */
+struct demangled_name_entry
+{
+ char *mangled;
+ char demangled[1];
+};
+
+/* Hash function for the demangled name hash. */
+static hashval_t
+hash_demangled_name_entry (const void *data)
+{
+ const struct demangled_name_entry *e = data;
+ return htab_hash_string (e->mangled);
+}
+
+/* Equality function for the demangled name hash. */
+static int
+eq_demangled_name_entry (const void *a, const void *b)
+{
+ const struct demangled_name_entry *da = a;
+ const struct demangled_name_entry *db = b;
+ return strcmp (da->mangled, db->mangled) == 0;
+}
+
/* Create the hash table used for demangled names. Each hash entry is
a pair of strings; one for the mangled name and one for the demangled
name. The entry is hashed via just the mangled name. */
@@ -440,7 +464,7 @@ create_demangled_names_hash (struct objfile *objfile)
1% in symbol reading. */
objfile->demangled_names_hash = htab_create_alloc
- (256, htab_hash_string, (int (*) (const void *, const void *)) streq,
+ (256, hash_demangled_name_entry, eq_demangled_name_entry,
NULL, xcalloc, xfree);
}
@@ -496,10 +520,14 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
}
/* Set both the mangled and demangled (if any) names for GSYMBOL based
- on LINKAGE_NAME and LEN. The hash table corresponding to OBJFILE
- is used, and the memory comes from that objfile's objfile_obstack.
- LINKAGE_NAME is copied, so the pointer can be discarded after
- calling this function. */
+ on LINKAGE_NAME and LEN. Ordinarily, NAME is copied onto the
+ objfile's obstack; but if LEN is -1 then this function assumes that
+ NAME is both NUL-terminated and correctly saved (either permanently
+ or with a lifetime tied to the objfile), and it will not be copied.
+
+ The hash table corresponding to OBJFILE is used, and the memory
+ comes from that objfile's objfile_obstack. LINKAGE_NAME is copied,
+ so the pointer can be discarded after calling this function. */
/* We have to be careful when dealing with Java names: when we run
into a Java minimal symbol, we don't know it's a Java symbol, so it
@@ -524,7 +552,7 @@ void
symbol_set_names (struct general_symbol_info *gsymbol,
const char *linkage_name, int len, struct objfile *objfile)
{
- char **slot;
+ struct demangled_name_entry **slot;
/* A 0-terminated copy of the linkage name. */
const char *linkage_name_copy;
/* A copy of the linkage name that might have a special Java prefix
@@ -532,9 +560,11 @@ symbol_set_names (struct general_symbol_info *gsymbol,
const char *lookup_name;
/* The length of lookup_name. */
int lookup_len;
+ int original_len = len;
+ struct demangled_name_entry entry;
- if (objfile->demangled_names_hash == NULL)
- create_demangled_names_hash (objfile);
+ if (len == -1)
+ len = strlen (linkage_name);
if (gsymbol->language == language_ada)
{
@@ -546,14 +576,22 @@ symbol_set_names (struct general_symbol_info *gsymbol,
been observed with Java. Because we don't store the demangled
name with the symbol, we don't need to use the same trick
as Java. */
- gsymbol->name = obstack_alloc (&objfile->objfile_obstack, len + 1);
- memcpy (gsymbol->name, linkage_name, len);
- gsymbol->name[len] = '\0';
+ if (original_len == -1)
+ gsymbol->name = (char *) linkage_name;
+ else
+ {
+ gsymbol->name = obstack_alloc (&objfile->objfile_obstack, len + 1);
+ memcpy (gsymbol->name, linkage_name, len);
+ gsymbol->name[len] = '\0';
+ }
gsymbol->language_specific.cplus_specific.demangled_name = NULL;
return;
}
+ if (objfile->demangled_names_hash == NULL)
+ create_demangled_names_hash (objfile);
+
/* The stabs reader generally provides names that are not
NUL-terminated; most of the other readers don't do this, so we
can just use the given copy, unless we're in the Java case. */
@@ -589,8 +627,10 @@ symbol_set_names (struct general_symbol_info *gsymbol,
linkage_name_copy = linkage_name;
}
- slot = (char **) htab_find_slot (objfile->demangled_names_hash,
- lookup_name, INSERT);
+ entry.mangled = (char *) lookup_name;
+ slot = ((struct demangled_name_entry **)
+ htab_find_slot (objfile->demangled_names_hash,
+ &entry, INSERT));
/* If this name is not in the hash table, add it. */
if (*slot == NULL)
@@ -599,25 +639,47 @@ symbol_set_names (struct general_symbol_info *gsymbol,
linkage_name_copy);
int demangled_len = demangled_name ? strlen (demangled_name) : 0;
- /* If there is a demangled name, place it right after the mangled name.
- Otherwise, just place a second zero byte after the end of the mangled
- name. */
- *slot = obstack_alloc (&objfile->objfile_obstack,
- lookup_len + demangled_len + 2);
- memcpy (*slot, lookup_name, lookup_len + 1);
+ /* Suppose we have demangled_name==NULL, original_len==-1, and
+ lookup_name==linkage_name. In this case, we already have the
+ mangled name saved, and we don't have a demangled name. So,
+ you might think we could save a little space by not recording
+ this in the hash table at all.
+
+ It turns out that it is actually important to still save such
+ an entry in the hash table, because storing this name gives
+ us better bcache hit rates for partial symbols. */
+ if (original_len == -1 && lookup_name == linkage_name)
+ {
+ *slot = obstack_alloc (&objfile->objfile_obstack,
+ sizeof (struct demangled_name_entry)
+ + demangled_len);
+ (*slot)->mangled = (char *) lookup_name;
+ }
+ else
+ {
+ /* If we must copy the mangled name, put it directly after
+ the demangled name so we can have a single
+ allocation. */
+ *slot = obstack_alloc (&objfile->objfile_obstack,
+ sizeof (struct demangled_name_entry)
+ + lookup_len + demangled_len + 1);
+ (*slot)->mangled = &((*slot)->demangled[demangled_len + 1]);
+ strcpy ((*slot)->mangled, lookup_name);
+ }
+
if (demangled_name != NULL)
{
- memcpy (*slot + lookup_len + 1, demangled_name, demangled_len + 1);
+ strcpy ((*slot)->demangled, demangled_name);
xfree (demangled_name);
}
else
- (*slot)[lookup_len + 1] = '\0';
+ (*slot)->demangled[0] = '\0';
}
- gsymbol->name = *slot + lookup_len - len;
- if ((*slot)[lookup_len + 1] != '\0')
+ gsymbol->name = (*slot)->mangled;
+ if ((*slot)->demangled[0] != '\0')
gsymbol->language_specific.cplus_specific.demangled_name
- = &(*slot)[lookup_len + 1];
+ = (*slot)->demangled;
else
gsymbol->language_specific.cplus_specific.demangled_name = NULL;
}
diff --git a/gdb/symtab.h b/gdb/symtab.h
index acb8510..2b53005 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -1121,6 +1121,11 @@ extern void prim_record_minimal_symbol (const char *, CORE_ADDR,
enum minimal_symbol_type,
struct objfile *);
+extern struct minimal_symbol *prim_record_minimal_symbol_full
+ (const char *, int, CORE_ADDR,
+ enum minimal_symbol_type,
+ int section, asection * bfd_section, struct objfile *);
+
extern struct minimal_symbol *prim_record_minimal_symbol_and_info
(const char *, CORE_ADDR,
enum minimal_symbol_type,