aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ChangeLog5
-rw-r--r--include/ctf-api.h4
-rw-r--r--libctf/ChangeLog51
-rw-r--r--libctf/ctf-archive.c180
-rw-r--r--libctf/ctf-impl.h6
-rw-r--r--libctf/ctf-lookup.c232
-rw-r--r--libctf/ctf-open.c1
-rw-r--r--libctf/libctf.ver6
-rw-r--r--libctf/testsuite/libctf-lookup/conflicting-type-syms-a.c5
-rw-r--r--libctf/testsuite/libctf-lookup/conflicting-type-syms-b.c5
-rw-r--r--libctf/testsuite/libctf-lookup/conflicting-type-syms.c99
-rw-r--r--libctf/testsuite/libctf-lookup/conflicting-type-syms.lk7
-rw-r--r--libctf/testsuite/libctf-lookup/enum-symbol-obj.lk5
-rw-r--r--libctf/testsuite/libctf-lookup/enum-symbol.c115
-rw-r--r--libctf/testsuite/libctf-writable/symtypetab-nonlinker-writeout.c34
15 files changed, 576 insertions, 179 deletions
diff --git a/include/ChangeLog b/include/ChangeLog
index a24c920..71f0beb 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,8 @@
+2021-02-17 Nick Alcock <nick.alcock@oracle.com>
+
+ * ctf-api.h (ctf_arc_lookup_symbol_name): New.
+ (ctf_lookup_by_symbol_name): Likewise.
+
2021-02-19 Nelson Chu <nelson.chu@sifive.com>
PR 27158
diff --git a/include/ctf-api.h b/include/ctf-api.h
index 6dd43aa..ce764df 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -338,6 +338,9 @@ extern void ctf_arc_close (ctf_archive_t *);
extern ctf_dict_t *ctf_arc_lookup_symbol (ctf_archive_t *,
unsigned long symidx,
ctf_id_t *, int *errp);
+extern ctf_dict_t *ctf_arc_lookup_symbol_name (ctf_archive_t *,
+ const char *name,
+ ctf_id_t *, int *errp);
extern void ctf_arc_flush_caches (ctf_archive_t *);
extern ctf_dict_t *ctf_dict_open (const ctf_archive_t *,
const char *, int *);
@@ -388,6 +391,7 @@ extern int ctf_func_type_args (ctf_dict_t *, ctf_id_t, uint32_t, ctf_id_t *);
extern ctf_id_t ctf_lookup_by_name (ctf_dict_t *, const char *);
extern ctf_id_t ctf_lookup_by_symbol (ctf_dict_t *, unsigned long);
+extern ctf_id_t ctf_lookup_by_symbol_name (ctf_dict_t *, const char *);
extern ctf_id_t ctf_symbol_next (ctf_dict_t *, ctf_next_t **,
const char **name, int functions);
extern ctf_id_t ctf_lookup_variable (ctf_dict_t *, const char *);
diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index 7a69476..acf3c46 100644
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -1,3 +1,54 @@
+2021-02-17 Nick Alcock <nick.alcock@oracle.com>
+
+ * ctf-impl.h (ctf_dict_t) <ctf_symhash>: New.
+ <ctf_symhash_latest>: Likewise.
+ (struct ctf_archive_internal) <ctfi_crossdict_cache>: New.
+ <ctfi_symnamedicts>: New.
+ <ctfi_syms>: Remove.
+ (ctf_lookup_symbol_name): Remove.
+ * ctf-lookup.c (ctf_lookup_symbol_name): Propagate errors from
+ parent properly. Make static.
+ (ctf_lookup_symbol_idx): New, linear search for the symbol name,
+ cached in the crossdict cache's ctf_symhash (if available), or
+ this dict's (otherwise).
+ (ctf_try_lookup_indexed): Allow the symname to be passed in.
+ (ctf_lookup_by_symbol): Turn into a wrapper around...
+ (ctf_lookup_by_sym_or_name): ... this, supporting name lookup too,
+ using ctf_lookup_symbol_idx in non-writable dicts. Special-case
+ name lookup in dynamic dicts without reported symbols, which have
+ no symtab or dynsymidx but where name lookup should still work.
+ (ctf_lookup_by_symbol_name): New, another wrapper.
+ * ctf-archive.c (enosym): Note that this is present in
+ ctfi_symnamedicts too.
+ (ctf_arc_close): Adjust for removal of ctfi_syms. Free the
+ ctfi_symnamedicts.
+ (ctf_arc_flush_caches): Likewise.
+ (ctf_dict_open_cached): Memoize the first cached dict in the
+ crossdict cache.
+ (ctf_arc_lookup_symbol): Turn into a wrapper around...
+ (ctf_arc_lookup_sym_or_name): ... this. No longer cache
+ ctf_id_t lookups: just call ctf_lookup_by_symbol as needed (but
+ still cache the dicts those lookups succeed in). Add
+ lookup-by-name support, with dicts of successful lookups cached in
+ ctfi_symnamedicts. Refactor the caching code a bit.
+ (ctf_arc_lookup_symbol_name): New, another wrapper.
+ * ctf-open.c (ctf_dict_close): Free the ctf_symhash.
+ * libctf.ver (LIBCTF_1.2): New version. Add
+ ctf_lookup_by_symbol_name, ctf_arc_lookup_symbol_name.
+ * testsuite/libctf-lookup/enum-symbol.c (main): Use
+ ctf_arc_lookup_symbol rather than looking up the name ourselves.
+ Fish it out repeatedly, to make sure that symbol caching isn't
+ broken.
+ (symidx_64): Remove.
+ (symidx_32): Remove.
+ * testsuite/libctf-lookup/enum-symbol-obj.lk: Test symbol lookup
+ in an unlinked object file (indexed symtypetab sections only).
+ * testsuite/libctf-writable/symtypetab-nonlinker-writeout.c
+ (try_maybe_reporting): Check symbol types via
+ ctf_lookup_by_symbol_name as well as ctf_symbol_next.
+ * testsuite/libctf-lookup/conflicting-type-syms.*: New test of
+ lookups in a multi-dict archive.
+
2021-02-20 Alan Modra <amodra@gmail.com>
* testsuite/config/default.exp (ld_L_opt): Define.
diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c
index 193fc4d..6d9c75c 100644
--- a/libctf/ctf-archive.c
+++ b/libctf/ctf-archive.c
@@ -46,8 +46,8 @@ static int arc_mmap_writeout (int fd, void *header, size_t headersz,
static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg);
static void ctf_arc_import_parent (const ctf_archive_t *arc, ctf_dict_t *fp);
-/* Flag to indicate "symbol not present" in
- ctf_archive_internal.ctfi_symdicts. Never initialized. */
+/* Flag to indicate "symbol not present" in ctf_archive_internal.ctfi_symdicts
+ and ctfi_symnamedicts. Never initialized. */
static ctf_dict_t enosym;
/* Write out a CTF archive to the start of the file referenced by the passed-in
@@ -529,8 +529,8 @@ ctf_arc_close (ctf_archive_t *arc)
}
else
ctf_dict_close (arc->ctfi_dict);
- free (arc->ctfi_syms);
free (arc->ctfi_symdicts);
+ free (arc->ctfi_symnamedicts);
ctf_dynhash_destroy (arc->ctfi_dicts);
if (arc->ctfi_free_symsect)
free ((void *) arc->ctfi_symsect.cts_data);
@@ -645,8 +645,9 @@ ctf_cached_dict_close (void *fp)
ctf_dict_close ((ctf_dict_t *) fp);
}
-/* Return the ctf_dict_t with the given name and cache it in the
- archive's ctfi_dicts. */
+/* Return the ctf_dict_t with the given name and cache it in the archive's
+ ctfi_dicts. If this is the first cached dict, designate it the
+ crossdict_cache. */
static ctf_dict_t *
ctf_dict_open_cached (ctf_archive_t *arc, const char *name, int *errp)
{
@@ -678,6 +679,9 @@ ctf_dict_open_cached (ctf_archive_t *arc, const char *name, int *errp)
goto oom;
fp->ctf_refcnt++;
+ if (arc->ctfi_crossdict_cache == NULL)
+ arc->ctfi_crossdict_cache = fp;
+
return fp;
oom:
@@ -693,11 +697,12 @@ void
ctf_arc_flush_caches (ctf_archive_t *wrapper)
{
free (wrapper->ctfi_symdicts);
- free (wrapper->ctfi_syms);
+ free (wrapper->ctfi_symnamedicts);
ctf_dynhash_destroy (wrapper->ctfi_dicts);
wrapper->ctfi_symdicts = NULL;
- wrapper->ctfi_syms = NULL;
+ wrapper->ctfi_symnamedicts = NULL;
wrapper->ctfi_dicts = NULL;
+ wrapper->ctfi_crossdict_cache = NULL;
}
/* Return the ctf_dict_t at the given ctfa_ctfs-relative offset, or NULL if
@@ -778,31 +783,46 @@ ctf_archive_count (const ctf_archive_t *wrapper)
return wrapper->ctfi_archive->ctfa_ndicts;
}
-/* Look up a symbol in an archive. Return the dict in the archive that the
- symbol is found in, and (optionally) the ctf_id_t of the symbol in that dict
- (so you don't have to look it up yourself). The dict and mapping are both
- cached, so repeated lookups are nearly free.
+/* Look up a symbol in an archive by name or index (if the name is set, a lookup
+ by name is done). Return the dict in the archive that the symbol is found
+ in, and (optionally) the ctf_id_t of the symbol in that dict (so you don't
+ have to look it up yourself). The dict is cached, so repeated lookups are
+ nearly free.
As usual, you should ctf_dict_close() the returned dict once you are done
with it.
Returns NULL on error, and an error in errp (if set). */
-ctf_dict_t *
-ctf_arc_lookup_symbol (ctf_archive_t *wrapper, unsigned long symidx,
- ctf_id_t *typep, int *errp)
+static ctf_dict_t *
+ctf_arc_lookup_sym_or_name (ctf_archive_t *wrapper, unsigned long symidx,
+ const char *symname, ctf_id_t *typep, int *errp)
{
ctf_dict_t *fp;
+ void *fpkey;
ctf_id_t type;
/* The usual non-archive-transparent-wrapper special case. */
if (!wrapper->ctfi_is_archive)
{
- if ((type = ctf_lookup_by_symbol (wrapper->ctfi_dict, symidx)) == CTF_ERR)
+ if (!symname)
{
- if (errp)
- *errp = ctf_errno (wrapper->ctfi_dict);
- return NULL;
+ if ((type = ctf_lookup_by_symbol (wrapper->ctfi_dict, symidx)) == CTF_ERR)
+ {
+ if (errp)
+ *errp = ctf_errno (wrapper->ctfi_dict);
+ return NULL;
+ }
+ }
+ else
+ {
+ if ((type = ctf_lookup_by_symbol_name (wrapper->ctfi_dict,
+ symname)) == CTF_ERR)
+ {
+ if (errp)
+ *errp = ctf_errno (wrapper->ctfi_dict);
+ return NULL;
+ }
}
if (typep)
*typep = type;
@@ -820,27 +840,28 @@ ctf_arc_lookup_symbol (ctf_archive_t *wrapper, unsigned long symidx,
return NULL;
}
- /* Make enough space for all possible symbols, if not already done.
- We cache both the ctf_id_t and the originating dictionary of all symbols.
- The dict links are weak, to the dictionaries cached in ctfi_dicts: their
- refcnts are *not* bumped. */
+ /* Make enough space for all possible symbol indexes, if not already done. We
+ cache the originating dictionary of all symbols. The dict links are weak,
+ to the dictionaries cached in ctfi_dicts: their refcnts are *not* bumped.
+ We also cache similar mappings for symbol names: these are ordinary
+ dynhashes, with weak links to dicts. */
- if (!wrapper->ctfi_syms)
+ if (!wrapper->ctfi_symdicts)
{
- if ((wrapper->ctfi_syms = calloc (wrapper->ctfi_symsect.cts_size
- / wrapper->ctfi_symsect.cts_entsize,
- sizeof (ctf_id_t))) == NULL)
+ if ((wrapper->ctfi_symdicts = calloc (wrapper->ctfi_symsect.cts_size
+ / wrapper->ctfi_symsect.cts_entsize,
+ sizeof (ctf_dict_t *))) == NULL)
{
if (errp)
*errp = ENOMEM;
return NULL;
}
}
- if (!wrapper->ctfi_symdicts)
+ if (!wrapper->ctfi_symnamedicts)
{
- if ((wrapper->ctfi_symdicts = calloc (wrapper->ctfi_symsect.cts_size
- / wrapper->ctfi_symsect.cts_entsize,
- sizeof (ctf_dict_t *))) == NULL)
+ if ((wrapper->ctfi_symnamedicts = ctf_dynhash_create (ctf_hash_string,
+ ctf_hash_eq_string,
+ free, NULL)) == NULL)
{
if (errp)
*errp = ENOMEM;
@@ -848,22 +869,38 @@ ctf_arc_lookup_symbol (ctf_archive_t *wrapper, unsigned long symidx,
}
}
- /* Perhaps it's cached. */
- if (wrapper->ctfi_symdicts[symidx] != NULL)
+ /* Perhaps the dict in which we found a previous lookup is cached. If it's
+ supposed to be cached but we don't find it, pretend it was always not
+ found: this should never happen, but shouldn't be allowed to cause trouble
+ if it does. */
+
+ if ((symname && ctf_dynhash_lookup_kv (wrapper->ctfi_symnamedicts,
+ symname, NULL, &fpkey))
+ || (!symname && wrapper->ctfi_symdicts[symidx] != NULL))
{
- if (wrapper->ctfi_symdicts[symidx] == &enosym)
+ if (symname)
+ fp = (ctf_dict_t *) fpkey;
+ else
+ fp = wrapper->ctfi_symdicts[symidx];
+
+ if (fp == &enosym)
+ goto no_sym;
+
+ if (symname)
{
- if (errp)
- *errp = ECTF_NOTYPEDAT;
- if (typep)
- *typep = CTF_ERR;
- return NULL;
+ if ((type = ctf_lookup_by_symbol_name (fp, symname)) == CTF_ERR)
+ goto cache_no_sym;
+ }
+ else
+ {
+ if ((type = ctf_lookup_by_symbol (fp, symidx)) == CTF_ERR)
+ goto cache_no_sym;
}
if (typep)
- *typep = wrapper->ctfi_syms[symidx];
- wrapper->ctfi_symdicts[symidx]->ctf_refcnt++;
- return wrapper->ctfi_symdicts[symidx];
+ *typep = type;
+ fp->ctf_refcnt++;
+ return fp;
}
/* Not cached: find it and cache it. We must track open errors ourselves even
@@ -882,16 +919,36 @@ ctf_arc_lookup_symbol (ctf_archive_t *wrapper, unsigned long symidx,
while ((fp = ctf_archive_next (wrapper, &i, &name, 0, local_errp)) != NULL)
{
- if ((type = ctf_lookup_by_symbol (fp, symidx)) != CTF_ERR)
+ if (!symname)
{
- wrapper->ctfi_syms[symidx] = type;
- wrapper->ctfi_symdicts[symidx] = fp;
- ctf_next_destroy (i);
+ if ((type = ctf_lookup_by_symbol (fp, symidx)) != CTF_ERR)
+ wrapper->ctfi_symdicts[symidx] = fp;
+ }
+ else
+ {
+ if ((type = ctf_lookup_by_symbol_name (fp, symname)) != CTF_ERR)
+ {
+ char *tmp;
+ /* No error checking, as above. */
+ if ((tmp = strdup (symname)) != NULL)
+ ctf_dynhash_insert (wrapper->ctfi_symnamedicts, tmp, fp);
+ }
+ }
+ if (type != CTF_ERR)
+ {
if (typep)
*typep = type;
+ ctf_next_destroy (i);
return fp;
}
+ if (ctf_errno (fp) != ECTF_NOTYPEDAT)
+ {
+ if (errp)
+ *errp = ctf_errno (fp);
+ ctf_next_destroy (i);
+ return NULL; /* errno is set for us. */
+ }
ctf_dict_close (fp);
}
if (*local_errp != ECTF_NEXT_END)
@@ -899,11 +956,25 @@ ctf_arc_lookup_symbol (ctf_archive_t *wrapper, unsigned long symidx,
ctf_next_destroy (i);
return NULL;
}
+
/* Don't leak end-of-iteration to the caller. */
*local_errp = 0;
- wrapper->ctfi_symdicts[symidx] = &enosym;
+ cache_no_sym:
+ if (!symname)
+ wrapper->ctfi_symdicts[symidx] = &enosym;
+ else
+ {
+ char *tmp;
+
+ /* No error checking: if caching fails, there is only a slight performance
+ impact. */
+ if ((tmp = strdup (symname)) != NULL)
+ if (ctf_dynhash_insert (wrapper->ctfi_symnamedicts, tmp, &enosym) < 0)
+ free (tmp);
+ }
+ no_sym:
if (errp)
*errp = ECTF_NOTYPEDAT;
if (typep)
@@ -911,6 +982,23 @@ ctf_arc_lookup_symbol (ctf_archive_t *wrapper, unsigned long symidx,
return NULL;
}
+/* The public API for looking up a symbol by index. */
+ctf_dict_t *
+ctf_arc_lookup_symbol (ctf_archive_t *wrapper, unsigned long symidx,
+ ctf_id_t *typep, int *errp)
+{
+ return ctf_arc_lookup_sym_or_name (wrapper, symidx, NULL, typep, errp);
+}
+
+/* The public API for looking up a symbol by name. */
+
+ctf_dict_t *
+ctf_arc_lookup_symbol_name (ctf_archive_t *wrapper, const char *symname,
+ ctf_id_t *typep, int *errp)
+{
+ return ctf_arc_lookup_sym_or_name (wrapper, 0, symname, typep, errp);
+}
+
/* Raw iteration over all CTF files in an archive. We pass the raw data for all
CTF files in turn to the specified callback function. */
static int
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index 0a508eb..a6e1da5 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -382,6 +382,8 @@ struct ctf_dict
ctf_sect_t ctf_symtab; /* Symbol table from object file. */
ctf_sect_t ctf_strtab; /* String table from object file. */
int ctf_symsect_little_endian; /* Endianness of the ctf_symtab. */
+ ctf_dynhash_t *ctf_symhash; /* (partial) hash, symsect name -> idx. */
+ size_t ctf_symhash_latest; /* Amount of symsect scanned so far. */
ctf_dynhash_t *ctf_prov_strtab; /* Maps provisional-strtab offsets
to names. */
ctf_dynhash_t *ctf_syn_ext_strtab; /* Maps ext-strtab offsets to names. */
@@ -508,8 +510,9 @@ struct ctf_archive_internal
ctf_dict_t *ctfi_dict;
struct ctf_archive *ctfi_archive;
ctf_dynhash_t *ctfi_dicts; /* Dicts we have opened and cached. */
+ ctf_dict_t *ctfi_crossdict_cache; /* Cross-dict caching. */
ctf_dict_t **ctfi_symdicts; /* Array of index -> ctf_dict_t *. */
- ctf_id_t *ctfi_syms; /* Array of index -> ctf_id_t. */
+ ctf_dynhash_t *ctfi_symnamedicts; /* Hash of name -> ctf_dict_t *. */
ctf_sect_t ctfi_symsect;
int ctfi_symsect_little_endian; /* -1 for unknown / do not set. */
ctf_sect_t ctfi_strsect;
@@ -784,7 +787,6 @@ extern ctf_link_sym_t *ctf_elf32_to_link_sym (ctf_dict_t *fp, ctf_link_sym_t *ds
const Elf32_Sym *src, uint32_t symidx);
extern ctf_link_sym_t *ctf_elf64_to_link_sym (ctf_dict_t *fp, ctf_link_sym_t *dst,
const Elf64_Sym *src, uint32_t symidx);
-extern const char *ctf_lookup_symbol_name (ctf_dict_t *fp, unsigned long symidx);
/* Variables, all underscore-prepended. */
diff --git a/libctf/ctf-lookup.c b/libctf/ctf-lookup.c
index 72f6a2a..6e17e5f 100644
--- a/libctf/ctf-lookup.c
+++ b/libctf/ctf-lookup.c
@@ -459,7 +459,7 @@ ctf_symidx_sort (ctf_dict_t *fp, uint32_t *idx, size_t *nidx,
/* Given a symbol index, return the name of that symbol from the table provided
by ctf_link_shuffle_syms, or failing that from the secondary string table, or
the null string. */
-const char *
+static const char *
ctf_lookup_symbol_name (ctf_dict_t *fp, unsigned long symidx)
{
const ctf_sect_t *sp = &fp->ctf_symtab;
@@ -512,7 +512,13 @@ ctf_lookup_symbol_name (ctf_dict_t *fp, unsigned long symidx)
try_parent:
if (fp->ctf_parent)
- return ctf_lookup_symbol_name (fp->ctf_parent, symidx);
+ {
+ const char *ret;
+ ret = ctf_lookup_symbol_name (fp->ctf_parent, symidx);
+ if (ret == NULL)
+ ctf_set_errno (fp, ctf_errno (fp->ctf_parent));
+ return ret;
+ }
else
{
ctf_set_errno (fp, err);
@@ -520,6 +526,116 @@ ctf_lookup_symbol_name (ctf_dict_t *fp, unsigned long symidx)
}
}
+/* Given a symbol name, return the index of that symbol, or -1 on error or if
+ not found. */
+static unsigned long
+ctf_lookup_symbol_idx (ctf_dict_t *fp, const char *symname)
+{
+ const ctf_sect_t *sp = &fp->ctf_symtab;
+ ctf_link_sym_t sym;
+ void *known_idx;
+ int err;
+ ctf_dict_t *cache = fp;
+
+ if (fp->ctf_dynsyms)
+ {
+ err = EINVAL;
+
+ ctf_link_sym_t *symp;
+
+ if ((symp = ctf_dynhash_lookup (fp->ctf_dynsyms, symname)) == NULL)
+ goto try_parent;
+
+ return symp->st_symidx;
+ }
+
+ err = ECTF_NOSYMTAB;
+ if (sp->cts_data == NULL)
+ goto try_parent;
+
+ /* First, try a hash lookup to see if we have already spotted this symbol
+ during a past iteration: create the hash first if need be. The lifespan
+ of the strings is equal to the lifespan of the cts_data, so we don't
+ need to strdup them. If this dict was opened as part of an archive,
+ and this archive has designed a crossdict_cache to cache results that
+ are the same across all dicts in an archive, use it. */
+
+ if (fp->ctf_archive && fp->ctf_archive->ctfi_crossdict_cache)
+ cache = fp->ctf_archive->ctfi_crossdict_cache;
+
+ if (!cache->ctf_symhash)
+ if ((cache->ctf_symhash = ctf_dynhash_create (ctf_hash_string,
+ ctf_hash_eq_string,
+ NULL, NULL)) == NULL)
+ goto oom;
+
+ if (ctf_dynhash_lookup_kv (cache->ctf_symhash, symname, NULL, &known_idx))
+ return (unsigned long) (uintptr_t) known_idx;
+
+ /* Hash lookup unsuccessful: linear search, populating the hashtab for later
+ lookups as we go. */
+
+ for (; cache->ctf_symhash_latest < sp->cts_size / sp->cts_entsize;
+ cache->ctf_symhash_latest++)
+ {
+ switch (sp->cts_entsize)
+ {
+ case sizeof (Elf64_Sym):
+ {
+ Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data;
+ ctf_elf64_to_link_sym (fp, &sym, &symp[cache->ctf_symhash_latest],
+ cache->ctf_symhash_latest);
+ if (!ctf_dynhash_lookup_kv (cache->ctf_symhash, sym.st_name,
+ NULL, NULL))
+ if (ctf_dynhash_cinsert (cache->ctf_symhash, sym.st_name,
+ (const void *) (uintptr_t)
+ cache->ctf_symhash_latest) < 0)
+ goto oom;
+ if (strcmp (sym.st_name, symname) == 0)
+ return cache->ctf_symhash_latest++;
+ }
+ break;
+ case sizeof (Elf32_Sym):
+ {
+ Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data;
+ ctf_elf32_to_link_sym (fp, &sym, &symp[cache->ctf_symhash_latest],
+ cache->ctf_symhash_latest);
+ if (!ctf_dynhash_lookup_kv (cache->ctf_symhash, sym.st_name,
+ NULL, NULL))
+ if (ctf_dynhash_cinsert (cache->ctf_symhash, sym.st_name,
+ (const void *) (uintptr_t)
+ cache->ctf_symhash_latest) < 0)
+ goto oom;
+ if (strcmp (sym.st_name, symname) == 0)
+ return cache->ctf_symhash_latest++;
+ }
+ break;
+ default:
+ ctf_set_errno (fp, ECTF_SYMTAB);
+ return (unsigned long) -1;
+ }
+ }
+
+ /* Searched everything, still not found. */
+
+ return (unsigned long) -1;
+
+ try_parent:
+ if (fp->ctf_parent)
+ return ctf_lookup_symbol_idx (fp->ctf_parent, symname);
+ else
+ {
+ ctf_set_errno (fp, err);
+ return (unsigned long) -1;
+ }
+oom:
+ ctf_set_errno (fp, ENOMEM);
+ ctf_err_warn (fp, 0, ENOMEM, _("cannot allocate memory for symbol "
+ "lookup hashtab"));
+ return (unsigned long) -1;
+
+}
+
/* Iterate over all symbols with types: if FUNC, function symbols, otherwise,
data symbols. The name argument is not optional. The return order is
arbitrary, though is likely to be in symbol index or name order. You can
@@ -664,20 +780,24 @@ ctf_lookup_idx_name (const void *key_, const void *idx_)
return (strcmp (key->clik_name, ctf_strptr (key->clik_fp, key->clik_names[*idx])));
}
-/* Given a symbol number, look up that symbol in the function or object
- index table (which must exist). Return 0 if not found there (or pad). */
+/* Given a symbol name or (failing that) number, look up that symbol in the
+ function or object index table (which must exist). Return 0 if not found
+ there (or pad). */
static ctf_id_t
-ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx, int is_function)
+ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx,
+ const char *symname, int is_function)
{
- const char *symname = ctf_lookup_symbol_name (fp, symidx);
struct ctf_header *hp = fp->ctf_header;
uint32_t *symtypetab;
uint32_t *names;
uint32_t *sxlate;
size_t nidx;
- ctf_dprintf ("Looking up type of object with symtab idx %lx (%s) in "
+ if (symname == NULL)
+ symname = ctf_lookup_symbol_name (fp, symidx);
+
+ ctf_dprintf ("Looking up type of object with symtab idx %lx or name %s in "
"indexed symtypetab\n", symidx, symname);
if (symname[0] == '\0')
@@ -745,13 +865,15 @@ ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx, int is_function)
return symtypetab[*idx];
}
-/* Given a symbol table index, return the type of the function or data object
- described by the corresponding entry in the symbol table. We can only return
- symbols in read-only dicts and in dicts for which ctf_link_shuffle_syms has
- been called to assign symbol indexes to symbol names. */
+/* Given a symbol name or (if NULL) symbol index, return the type of the
+ function or data object described by the corresponding entry in the symbol
+ table. We can only return symbols in read-only dicts and in dicts for which
+ ctf_link_shuffle_syms has been called to assign symbol indexes to symbol
+ names. */
-ctf_id_t
-ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx)
+static ctf_id_t
+ctf_lookup_by_sym_or_name (ctf_dict_t *fp, unsigned long symidx,
+ const char *symname)
{
const ctf_sect_t *sp = &fp->ctf_symtab;
ctf_id_t type = 0;
@@ -762,38 +884,62 @@ ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx)
{
const ctf_link_sym_t *sym;
- ctf_dprintf ("Looking up type of object with symtab idx %lx in "
- "writable dict symtypetab\n", symidx);
+ if (symname)
+ ctf_dprintf ("Looking up type of object with symname %s in "
+ "writable dict symtypetab\n", symname);
+ else
+ ctf_dprintf ("Looking up type of object with symtab idx %lx in "
+ "writable dict symtypetab\n", symidx);
/* The dict must be dynamic. */
if (!ctf_assert (fp, fp->ctf_flags & LCTF_RDWR))
return CTF_ERR;
- err = EINVAL;
- if (symidx > fp->ctf_dynsymmax)
- goto try_parent;
+ /* No name? Need to look it up. */
+ if (!symname)
+ {
+ err = EINVAL;
+ if (symidx > fp->ctf_dynsymmax)
+ goto try_parent;
- sym = fp->ctf_dynsymidx[symidx];
- err = ECTF_NOTYPEDAT;
- if (!sym || (sym->st_shndx != STT_OBJECT && sym->st_shndx != STT_FUNC))
- goto try_parent;
+ sym = fp->ctf_dynsymidx[symidx];
+ err = ECTF_NOTYPEDAT;
+ if (!sym || (sym->st_shndx != STT_OBJECT && sym->st_shndx != STT_FUNC))
+ goto try_parent;
- if (!ctf_assert (fp, !sym->st_nameidx_set))
- return CTF_ERR;
+ if (!ctf_assert (fp, !sym->st_nameidx_set))
+ return CTF_ERR;
+ symname = sym->st_name;
+ }
if (fp->ctf_objthash == NULL
|| ((type = (ctf_id_t) (uintptr_t)
- ctf_dynhash_lookup (fp->ctf_objthash, sym->st_name)) == 0))
+ ctf_dynhash_lookup (fp->ctf_objthash, symname)) == 0))
{
if (fp->ctf_funchash == NULL
|| ((type = (ctf_id_t) (uintptr_t)
- ctf_dynhash_lookup (fp->ctf_funchash, sym->st_name)) == 0))
+ ctf_dynhash_lookup (fp->ctf_funchash, symname)) == 0))
goto try_parent;
}
return type;
}
+ /* Lookup by name in a dynamic dict: just do it directly. */
+ if (symname && fp->ctf_flags & LCTF_RDWR)
+ {
+ if (fp->ctf_objthash == NULL
+ || ((type = (ctf_id_t) (uintptr_t)
+ ctf_dynhash_lookup (fp->ctf_objthash, symname)) == 0))
+ {
+ if (fp->ctf_funchash == NULL
+ || ((type = (ctf_id_t) (uintptr_t)
+ ctf_dynhash_lookup (fp->ctf_funchash, symname)) == 0))
+ goto try_parent;
+ }
+ return type;
+ }
+
err = ECTF_NOSYMTAB;
if (sp->cts_data == NULL)
goto try_parent;
@@ -801,17 +947,17 @@ ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx)
/* This covers both out-of-range lookups and a dynamic dict which hasn't been
shuffled yet. */
err = EINVAL;
- if (symidx >= fp->ctf_nsyms)
+ if (symname == NULL && symidx >= fp->ctf_nsyms)
goto try_parent;
if (fp->ctf_objtidx_names)
{
- if ((type = ctf_try_lookup_indexed (fp, symidx, 0)) == CTF_ERR)
+ if ((type = ctf_try_lookup_indexed (fp, symidx, symname, 0)) == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
}
if (type == 0 && fp->ctf_funcidx_names)
{
- if ((type = ctf_try_lookup_indexed (fp, symidx, 1)) == CTF_ERR)
+ if ((type = ctf_try_lookup_indexed (fp, symidx, symname, 1)) == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
}
if (type != 0)
@@ -825,6 +971,10 @@ ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx)
ctf_dprintf ("Looking up object type %lx in 1:1 dict symtypetab\n", symidx);
+ if (symname != NULL)
+ if ((symidx = ctf_lookup_symbol_idx (fp, symname)) == (unsigned long) -1)
+ goto try_parent;
+
if (fp->ctf_sxlate[symidx] == -1u)
goto try_parent;
@@ -836,11 +986,33 @@ ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx)
return type;
try_parent:
if (fp->ctf_parent)
- return ctf_lookup_by_symbol (fp->ctf_parent, symidx);
+ {
+ ctf_id_t ret = ctf_lookup_by_sym_or_name (fp->ctf_parent, symidx,
+ symname);
+ if (ret == CTF_ERR)
+ ctf_set_errno (fp, ctf_errno (fp->ctf_parent));
+ return ret;
+ }
else
return (ctf_set_errno (fp, err));
}
+/* Given a symbol table index, return the type of the function or data object
+ described by the corresponding entry in the symbol table. */
+ctf_id_t
+ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx)
+{
+ return ctf_lookup_by_sym_or_name (fp, symidx, NULL);
+}
+
+/* Given a symbol name, return the type of the function or data object described
+ by the corresponding entry in the symbol table. */
+ctf_id_t
+ctf_lookup_by_symbol_name (ctf_dict_t *fp, const char *symname)
+{
+ return ctf_lookup_by_sym_or_name (fp, 0, symname);
+}
+
/* Given a symbol table index, return the info for the function described
by the corresponding entry in the symbol table, which may be a function
symbol or may be a data symbol that happens to be a function pointer. */
diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c
index 67d9f84..c2d9a33 100644
--- a/libctf/ctf-open.c
+++ b/libctf/ctf-open.c
@@ -1737,6 +1737,7 @@ ctf_dict_close (ctf_dict_t *fp)
}
ctf_dynhash_destroy (fp->ctf_dvhash);
+ ctf_dynhash_destroy (fp->ctf_symhash);
free (fp->ctf_funcidx_sxlate);
free (fp->ctf_objtidx_sxlate);
ctf_dynhash_destroy (fp->ctf_objthash);
diff --git a/libctf/libctf.ver b/libctf/libctf.ver
index 2137c5b..8c362f3 100644
--- a/libctf/libctf.ver
+++ b/libctf/libctf.ver
@@ -196,3 +196,9 @@ LIBCTF_1.1 {
ctf_symsect_endianness;
ctf_arc_symsect_endianness;
} LIBCTF_1.0;
+
+LIBCTF_1.2 {
+ global:
+ ctf_lookup_by_symbol_name;
+ ctf_arc_lookup_symbol_name;
+} LIBCTF_1.1;
diff --git a/libctf/testsuite/libctf-lookup/conflicting-type-syms-a.c b/libctf/testsuite/libctf-lookup/conflicting-type-syms-a.c
new file mode 100644
index 0000000..6541487
--- /dev/null
+++ b/libctf/testsuite/libctf-lookup/conflicting-type-syms-a.c
@@ -0,0 +1,5 @@
+typedef long a_t;
+typedef long b_t;
+
+a_t *a;
+b_t ignore2;
diff --git a/libctf/testsuite/libctf-lookup/conflicting-type-syms-b.c b/libctf/testsuite/libctf-lookup/conflicting-type-syms-b.c
new file mode 100644
index 0000000..e458021
--- /dev/null
+++ b/libctf/testsuite/libctf-lookup/conflicting-type-syms-b.c
@@ -0,0 +1,5 @@
+typedef long a_t;
+typedef long b_t;
+
+a_t b;
+b_t ignore1;
diff --git a/libctf/testsuite/libctf-lookup/conflicting-type-syms.c b/libctf/testsuite/libctf-lookup/conflicting-type-syms.c
new file mode 100644
index 0000000..ffe6983
--- /dev/null
+++ b/libctf/testsuite/libctf-lookup/conflicting-type-syms.c
@@ -0,0 +1,99 @@
+#include "config.h"
+#include <ctf-api.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main (int argc, char *argv[])
+{
+ ctf_archive_t *ctf;
+ ctf_dict_t *a_fp, *ignore1_fp, *b_fp, *ignore2_fp, *tmp_fp;
+ int err;
+ ctf_id_t a, b, ignore1, ignore2, tmp;
+ char *foo;
+ ctf_next_t *i = NULL;
+ const char *name;
+ int val;
+
+ if (argc != 2)
+ {
+ fprintf (stderr, "Syntax: %s PROGRAM\n", argv[0]);
+ exit(1);
+ }
+
+ if ((ctf = ctf_open (argv[1], NULL, &err)) == NULL)
+ goto open_err;
+
+ /* Fish out each symbol in turn: also try to fish out a nonexistent one. */
+
+ if ((a_fp = ctf_arc_lookup_symbol_name (ctf, "a", &a, &err)) == NULL)
+ goto sym_err;
+ printf ("Type of a is %s\n", foo = ctf_type_aname (a_fp, a));
+
+ if ((b_fp = ctf_arc_lookup_symbol_name (ctf, "b", &b, &err)) == NULL)
+ goto sym_err;
+ printf ("Type of b is %s\n", foo = ctf_type_aname (b_fp, b));
+
+ if ((ignore1_fp = ctf_arc_lookup_symbol_name (ctf, "ignore1", &ignore1, &err)) == NULL)
+ goto sym_err;
+ printf ("Type of ignore1 is %s\n", foo = ctf_type_aname (ignore1_fp, ignore1));
+
+ if ((ignore2_fp = ctf_arc_lookup_symbol_name (ctf, "ignore2", &ignore2, &err)) == NULL)
+ goto sym_err;
+ printf ("Type of ignore2 is %s\n", foo = ctf_type_aname (ignore2_fp, ignore1));
+
+ /* Try a call in just-get-the-dict mode and make sure it doesn't fail. */
+ if ((tmp_fp = ctf_arc_lookup_symbol_name (ctf, "ignore2", NULL, &err)) == NULL)
+ goto sym_err;
+ ctf_dict_close (tmp_fp);
+
+ /* Make sure failures fail. */
+ if ((ctf_arc_lookup_symbol_name (ctf, "nonexistent", NULL, &err) != NULL)
+ || err != ECTF_NOTYPEDAT)
+ goto nosym_err;
+
+ /* Fish them out again to check the caching layer. */
+ if (((tmp_fp = ctf_arc_lookup_symbol_name (ctf, "a", &tmp, &err)) != a_fp)
+ || (tmp != a))
+ goto sym_cache_err;
+ ctf_dict_close (tmp_fp);
+
+ if (((tmp_fp = ctf_arc_lookup_symbol_name (ctf, "b", &tmp, &err)) != b_fp)
+ || (tmp != b))
+ goto sym_cache_err;
+ ctf_dict_close (tmp_fp);
+
+ if (((tmp_fp = ctf_arc_lookup_symbol_name (ctf, "ignore1", &tmp, &err)) != ignore1_fp)
+ || (tmp != ignore1))
+ goto sym_cache_err;
+ ctf_dict_close (tmp_fp);
+
+ if (((tmp_fp = ctf_arc_lookup_symbol_name (ctf, "ignore2", &tmp, &err)) != ignore2_fp)
+ || (tmp != ignore2))
+ goto sym_cache_err;
+ ctf_dict_close (tmp_fp);
+
+ ctf_dict_close (a_fp);
+ ctf_dict_close (b_fp);
+ ctf_dict_close (ignore1_fp);
+ ctf_dict_close (ignore2_fp);
+ ctf_close (ctf);
+
+ return 0;
+
+ open_err:
+ fprintf (stderr, "%s: cannot open: %s\n", argv[0], ctf_errmsg (err));
+ return 1;
+ sym_err:
+ fprintf (stderr, "%s: Symbol lookup error: %s\n", argv[0], ctf_errmsg (err));
+ return 1;
+ nosym_err:
+ fprintf (stderr, "%s: Nonexistent symbol lookup unexpected error: %s\n", argv[0],
+ ctf_errmsg (err));
+ return 1;
+ sym_cache_err:
+ fprintf (stderr, "%s: Symbol re-lookup error (caching bug): %s\n", argv[0],
+ ctf_errmsg (err));
+ return 1;
+}
diff --git a/libctf/testsuite/libctf-lookup/conflicting-type-syms.lk b/libctf/testsuite/libctf-lookup/conflicting-type-syms.lk
new file mode 100644
index 0000000..09b41df
--- /dev/null
+++ b/libctf/testsuite/libctf-lookup/conflicting-type-syms.lk
@@ -0,0 +1,7 @@
+# lookup: conflicting-type-syms.c
+# source: conflicting-type-syms-a.c
+# source: conflicting-type-syms-b.c
+Type of a is a_t \*
+Type of b is a_t
+Type of ignore1 is b_t
+Type of ignore2 is b_t
diff --git a/libctf/testsuite/libctf-lookup/enum-symbol-obj.lk b/libctf/testsuite/libctf-lookup/enum-symbol-obj.lk
new file mode 100644
index 0000000..548d67b
--- /dev/null
+++ b/libctf/testsuite/libctf-lookup/enum-symbol-obj.lk
@@ -0,0 +1,5 @@
+# lookup: enum-symbol.c
+# source: enum-symbol-ctf.c
+red1 has value 0
+green1 has value 1
+blue1 has value 2
diff --git a/libctf/testsuite/libctf-lookup/enum-symbol.c b/libctf/testsuite/libctf-lookup/enum-symbol.c
index 4f63b61..c67478f 100644
--- a/libctf/testsuite/libctf-lookup/enum-symbol.c
+++ b/libctf/testsuite/libctf-lookup/enum-symbol.c
@@ -1,71 +1,19 @@
#include "config.h"
-#include <bfd.h>
-#include <elf.h>
#include <ctf-api.h>
-#include <swap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-ssize_t symidx_64 (ctf_sect_t *s, ctf_sect_t *strsect, int little_endian, const char *name)
-{
- const char *strs = (const char *) strsect->cts_data;
- size_t i;
- Elf64_Sym *sym = (Elf64_Sym *) s->cts_data;
- for (i = 0; i < s->cts_size / s->cts_entsize; i++, sym++)
- {
- Elf64_Word nameoff = sym->st_name;
-#ifdef WORDS_BIGENDIAN
- if (little_endian)
- swap_thing (nameoff);
-#else
- if (!little_endian)
- swap_thing (nameoff);
-#endif
- if (strcmp (strs + nameoff, name) == 0)
- return i;
- }
- return -1;
-}
-
-ssize_t symidx_32 (ctf_sect_t *s, ctf_sect_t *strsect, int little_endian, const char *name)
-{
- const char *strs = (const char *) strsect->cts_data;
- size_t i;
- Elf32_Sym *sym = (Elf32_Sym *) s->cts_data;
- for (i = 0; i < s->cts_size / s->cts_entsize; i++, sym++)
- {
- Elf32_Word nameoff = sym->st_name;
-#ifdef WORDS_BIGENDIAN
- if (little_endian)
- swap_thing (nameoff);
-#else
- if (!little_endian)
- swap_thing (nameoff);
-#endif
- if (strcmp (strs + nameoff, name) == 0)
- return i;
- }
- return -1;
-}
-
int
main (int argc, char *argv[])
{
- ctf_dict_t *fp;
- bfd *abfd;
ctf_archive_t *ctf;
- ctf_sect_t symsect;
- ctf_sect_t strsect;
- ssize_t symidx;
+ ctf_dict_t *fp, *tmp_fp;
int err;
- ctf_id_t type;
+ ctf_id_t type, tmp;
ctf_next_t *i = NULL;
const char *name;
int val;
- int little_endian;
-
- ssize_t (*get_sym) (ctf_sect_t *s, ctf_sect_t *strsect, int little_endian, const char *name);
if (argc != 2)
{
@@ -73,53 +21,12 @@ main (int argc, char *argv[])
exit(1);
}
- /* Figure out the endianness of the symtab(s). */
- if ((abfd = bfd_openr (argv[1], NULL)) == NULL
- || !bfd_check_format (abfd, bfd_object))
- goto bfd_open_err;
- little_endian = bfd_little_endian (abfd);
- bfd_close_all_done (abfd);
-
if ((ctf = ctf_open (argv[1], NULL, &err)) == NULL)
goto open_err;
- if ((fp = ctf_dict_open (ctf, NULL, &err)) == NULL)
- goto open_err;
-
- symsect = ctf_getsymsect (fp);
- strsect = ctf_getstrsect (fp);
- if (symsect.cts_data == NULL
- || strsect.cts_data == NULL)
- {
- fprintf (stderr, "%s: no symtab or strtab\n", argv[0]);
- return 1;
- }
-
- ctf_dict_close (fp);
-
- if (symsect.cts_entsize != sizeof (Elf64_Sym) &&
- symsect.cts_entsize != sizeof (Elf32_Sym))
- {
- fprintf (stderr, "%s: unknown symsize: %lx\n", argv[0],
- symsect.cts_size);
- return 1;
- }
-
- switch (symsect.cts_entsize)
- {
- case sizeof (Elf64_Sym): get_sym = symidx_64; break;
- case sizeof (Elf32_Sym): get_sym = symidx_32; break;
- }
-
- if ((symidx = get_sym (&symsect, &strsect, little_endian, "primary1")) < 0)
- {
- fprintf (stderr, "%s: symbol not found: primary1\n", argv[0]);
- return 1;
- }
-
- /* Fish it out, then fish out all its enumerand/value pairs. */
+ /* Fish out the enumerator, then fish out all its enumerand/value pairs. */
- if ((fp = ctf_arc_lookup_symbol (ctf, symidx, &type, &err)) == NULL)
+ if ((fp = ctf_arc_lookup_symbol_name (ctf, "primary1", &type, &err)) == NULL)
goto sym_err;
while ((name = ctf_enum_next (fp, type, &i, &val)) != NULL)
@@ -129,21 +36,27 @@ main (int argc, char *argv[])
if (ctf_errno (fp) != ECTF_NEXT_END)
goto nerr;
+ /* Fish it out again to check the caching layer. */
+ if (((tmp_fp = ctf_arc_lookup_symbol_name (ctf, "primary1", &tmp, &err)) != fp)
+ || (tmp != type))
+ goto sym_cache_err;
+
+ ctf_dict_close (tmp_fp);
ctf_dict_close (fp);
ctf_close (ctf);
return 0;
- bfd_open_err:
- fprintf (stderr, "%s: cannot open: %s\n", argv[0], bfd_errmsg (bfd_get_error ()));
- return 1;
-
open_err:
fprintf (stderr, "%s: cannot open: %s\n", argv[0], ctf_errmsg (err));
return 1;
sym_err:
fprintf (stderr, "%s: Symbol lookup error: %s\n", argv[0], ctf_errmsg (err));
return 1;
+ sym_cache_err:
+ fprintf (stderr, "%s: Symbol re-lookup error (caching bug): %s\n", argv[0],
+ ctf_errmsg (err));
+ return 1;
err:
fprintf (stderr, "Lookup failed: %s\n", ctf_errmsg (ctf_errno (fp)));
return 1;
diff --git a/libctf/testsuite/libctf-writable/symtypetab-nonlinker-writeout.c b/libctf/testsuite/libctf-writable/symtypetab-nonlinker-writeout.c
index d339963..98144de 100644
--- a/libctf/testsuite/libctf-writable/symtypetab-nonlinker-writeout.c
+++ b/libctf/testsuite/libctf-writable/symtypetab-nonlinker-writeout.c
@@ -98,6 +98,21 @@ try_maybe_reporting (int report)
if (ctf_errno (fp) != ECTF_NEXT_END)
goto iter_err;
+ /* Look up all the symbols by name and make sure that works. */
+
+ if (ctf_lookup_by_symbol_name (fp, "data_a") != base2)
+ goto lookup_syms_err;
+ if (ctf_lookup_by_symbol_name (fp, "data_b") != base3)
+ goto lookup_syms_err;
+ if (ctf_lookup_by_symbol_name (fp, "data_c") != base)
+ goto lookup_syms_err;
+ if (ctf_lookup_by_symbol_name (fp, "func_a") != func2)
+ goto lookup_syms_err;
+ if (ctf_lookup_by_symbol_name (fp, "func_b") != func3)
+ goto lookup_syms_err;
+ if (ctf_lookup_by_symbol_name (fp, "func_c") != func)
+ goto lookup_syms_err;
+
/* Possibly report some but not all of the symbols, as if we are a linker (no
real program would do this without using the ctf_link APIs, but it's not
*prohibited*, just useless, and if they do we don't want things to
@@ -121,6 +136,21 @@ try_maybe_reporting (int report)
if (report_sym (fp, &sym, "func_c", 4, 2) < 0 ||
report_sym (fp, &sym, "func_a", 5, 2) < 0)
goto report_err;
+
+ /* Look up all the symbols by name now we have reported symbols. */
+
+ if (ctf_lookup_by_symbol_name (fp, "data_a") != base2)
+ goto lookup_syms_err;
+ if (ctf_lookup_by_symbol_name (fp, "data_b") != base3)
+ goto lookup_syms_err;
+ if (ctf_lookup_by_symbol_name (fp, "data_c") != base)
+ goto lookup_syms_err;
+ if (ctf_lookup_by_symbol_name (fp, "func_a") != func2)
+ goto lookup_syms_err;
+ if (ctf_lookup_by_symbol_name (fp, "func_b") != func3)
+ goto lookup_syms_err;
+ if (ctf_lookup_by_symbol_name (fp, "func_c") != func)
+ goto lookup_syms_err;
}
/* Write out, to memory. */
@@ -203,6 +233,10 @@ try_maybe_reporting (int report)
expected_overshoot_err:
fprintf (stderr, "Too many symbols in post-writeout comparison\n");
exit (1);
+ lookup_syms_err:
+ fprintf (stderr, "Explicit lookup of symbols by name failed: %s\n",
+ ctf_errmsg (ctf_errno (fp)));
+ exit (1);
expected_compar_err:
fprintf (stderr, "Non-dynamic iteration comparison failure: %s "
"(type %lx): expected %s (type %lx)\n", symname, symtype,