libctf: create, lookup: delete DVDs; ctf_lookup_by_kind

Variable handling in BTF and CTFv4 works quite differently from in CTFv3.
Rather than a separate section containing sorted, bsearchable variables,
they are simply named entities like types, stored in CTF_K_VARs.

As a first stage towards migrating to this, delete most references to
the ctf_varent_t and ctf_dvdef_t, including the DVD lookup code, all
the linking code, and quite a lot of the serialization code.

Note: CTF_LINK_OMIT_VARIABLES_SECTION, and the whole "delete variables that
already exist in the symtypetabs section" stuff, has yet to be
reimplemented.  We can implement CTF_LINK_OMIT_VARIABLES_SECTION by simply
excising all CTF_K_VARs at deduplication time if requested.  (Note:
symtypetabs should still point directly at the type, not at the CTF_K_VAR.)

(Symtypetabs in general need a bit more thought -- perhaps we can now store
them in a separate .ctf.symtypetab section with its own little four-entry
header for the symtypetabs and their indexes, making .ctf even more like
.BTF; the only difference would then be that .ctf could include prefix
types, CTF_K_FLOAT, and external string refs.  For later discussion.)

We also add ctf_lookup_by_kind() at this stage (because it is hopelessly
diff-entangled with ctf_lookup_variable): this looks up a type of a
particular kind, without needing a per-kind lookup function for it,
nor needing to hack around adding string prefixes (so you can do
ctf_lookup_by_kind (fp, CTF_K_STRUCT, "foo") rather than having to
do ctf_lookup_by_name (fp, "struct foo"): often this is more convenient, and
anything that reduces string buffer manipulation in C is good.)
This commit is contained in:
Nick Alcock
2025-04-24 15:58:12 +01:00
parent a93ad066f7
commit 05a2970ad1
8 changed files with 41 additions and 382 deletions

View File

@@ -571,6 +571,14 @@ extern ctf_id_t ctf_lookup_variable (ctf_dict_t *, const char *);
extern ctf_id_t ctf_lookup_enumerator (ctf_dict_t *, const char *,
int64_t *enum_value);
/* Look up a type of a given kind by name. This serves to look up kinds in
their own namespaces which do not have explicit lookup functions above:
datasecs. The only kinds you can't look up with this function are
CTF_K_TYPE_TAG and CTF_K_DECL_TAG, since they may be associated with many
types: use ctf_tag_next. */
extern ctf_id_t ctf_lookup_by_kind (ctf_dict_t *, int kind, const char *);
/* Type lookup functions. */
/* Strip qualifiers and typedefs off a type, returning the base type.

View File

@@ -364,38 +364,10 @@ ctf_static_type (const ctf_dict_t *fp, ctf_id_t type)
return ((unsigned long) idx <= fp->ctf_stypes);
}
int
ctf_dvd_insert (ctf_dict_t *fp, ctf_dvdef_t *dvd)
{
if (ctf_dynhash_insert (fp->ctf_dvhash, dvd->dvd_name, dvd) < 0)
return ctf_set_errno (fp, ENOMEM);
ctf_list_append (&fp->ctf_dvdefs, dvd);
return 0;
}
void
ctf_dvd_delete (ctf_dict_t *fp, ctf_dvdef_t *dvd)
{
ctf_dynhash_remove (fp->ctf_dvhash, dvd->dvd_name);
free (dvd->dvd_name);
ctf_list_delete (&fp->ctf_dvdefs, dvd);
free (dvd);
}
ctf_dvdef_t *
ctf_dvd_lookup (const ctf_dict_t *fp, const char *name)
{
return (ctf_dvdef_t *) ctf_dynhash_lookup (fp->ctf_dvhash, name);
}
/* Discard all of the dynamic type definitions and variable definitions that
have been added to the dict since the last call to ctf_update(). We locate
such types by scanning the dtd list and deleting elements that have type IDs
greater than ctf_dtoldid, which is set by ctf_update(), above, and by
scanning the variable list and deleting elements that have update IDs equal
to the current value of the last-update snapshot count (indicating that they
were added after the most recent call to ctf_update()). */
/* Discard all of the dynamic type definitions that have been added to the dict
since the last call to ctf_update(). We locate such types by scanning the
dtd list and deleting elements that have indexes greater than ctf_dtoldid,
which is set by ctf_update(), above. */
int
ctf_discard (ctf_dict_t *fp)
{
@@ -420,7 +392,6 @@ int
ctf_rollback (ctf_dict_t *fp, ctf_snapshot_id_t id)
{
ctf_dtdef_t *dtd, *ntd;
ctf_dvdef_t *dvd, *nvd;
if (fp->ctf_flags & LCTF_NO_STR)
return (ctf_set_errno (fp, ECTF_NOPARENT));
@@ -454,16 +425,6 @@ ctf_rollback (ctf_dict_t *fp, ctf_snapshot_id_t id)
ctf_dtd_delete (fp, dtd);
}
for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
{
nvd = ctf_list_next (dvd);
if (dvd->dvd_snapshots <= id.snapshot_id)
continue;
ctf_dvd_delete (fp, dvd);
}
fp->ctf_typemax = id.dtd_id;
fp->ctf_snapshots = id.snapshot_id;

View File

@@ -193,14 +193,6 @@ typedef struct ctf_dtdef
int dtd_flags; /* Some of the DTD_F_ flags. */
} ctf_dtdef_t;
typedef struct ctf_dvdef
{
ctf_list_t dvd_list; /* List forward/back pointers. */
char *dvd_name; /* Name associated with variable. */
ctf_id_t dvd_type; /* Type of variable. */
unsigned long dvd_snapshots; /* Snapshot count when inserted. */
} ctf_dvdef_t;
typedef struct ctf_err_warning
{
ctf_list_t cew_list; /* List forward/back pointers. */
@@ -410,7 +402,6 @@ struct ctf_dict
size_t ctf_size; /* Size of CTF header + uncompressed data. */
unsigned char *ctf_serializing_buf; /* CTF buffer in mid-serialization. */
size_t ctf_serializing_buf_size; /* Length of that buffer. */
ctf_varent_t *ctf_serializing_vars; /* Unsorted vars in mid-serialization. */
size_t ctf_serializing_nvars; /* Number of those vars. */
uint32_t *ctf_sxlate; /* Translation table for unindexed symtypetab
entries. */
@@ -462,8 +453,6 @@ struct ctf_dict
int ctf_version; /* CTF data version. */
ctf_dynhash_t *ctf_dthash; /* Hash of dynamic type definitions. */
ctf_list_t ctf_dtdefs; /* List of dynamic type definitions. */
ctf_dynhash_t *ctf_dvhash; /* Hash of dynamic variable mappings. */
ctf_list_t ctf_dvdefs; /* List of dynamic variable definitions. */
unsigned long ctf_dtoldid; /* Oldest id that has been committed. */
unsigned long ctf_snapshots; /* ctf_snapshot() plus ctf_update() count. */
unsigned long ctf_snapshot_lu; /* ctf_snapshot() call count at last update. */
@@ -750,10 +739,6 @@ extern void ctf_dtd_delete (ctf_dict_t *, ctf_dtdef_t *);
extern ctf_dtdef_t *ctf_dtd_lookup (const ctf_dict_t *, ctf_id_t);
extern ctf_dtdef_t *ctf_dynamic_type (const ctf_dict_t *, ctf_id_t);
extern int ctf_dvd_insert (ctf_dict_t *, ctf_dvdef_t *);
extern void ctf_dvd_delete (ctf_dict_t *, ctf_dvdef_t *);
extern ctf_dvdef_t *ctf_dvd_lookup (const ctf_dict_t *, const char *);
extern ctf_id_t ctf_add_encoded (ctf_dict_t *, uint32_t, const char *,
const ctf_encoding_t *, uint32_t kind);
extern ctf_id_t ctf_add_reftype (ctf_dict_t *, uint32_t, ctf_id_t,

View File

@@ -493,114 +493,6 @@ ctf_link_set_variable_filter (ctf_dict_t *fp, ctf_link_variable_filter_f *filter
return 0;
}
/* Check if we can safely add a variable with the given type to this dict. */
static int
check_variable (const char *name, ctf_dict_t *fp, ctf_id_t type,
ctf_dvdef_t **out_dvd)
{
ctf_dvdef_t *dvd;
dvd = ctf_dynhash_lookup (fp->ctf_dvhash, name);
*out_dvd = dvd;
if (!dvd)
return 1;
if (dvd->dvd_type != type)
{
/* Variable here. Wrong type: cannot add. Just skip it, because there is
no way to express this in CTF. Don't even warn: this case is too
common. (This might be the parent, in which case we'll try adding in
the child first, and only then give up.) */
ctf_dprintf ("Inexpressible duplicate variable %s skipped.\n", name);
}
return 0; /* Already exists. */
}
/* Link one variable named NAME of type TYPE found in IN_FP into FP. */
static int
ctf_link_one_variable (ctf_dict_t *fp, ctf_dict_t *in_fp, const char *name,
ctf_id_t type, int cu_mapped)
{
ctf_dict_t *per_cu_out_fp;
ctf_id_t dst_type = 0;
ctf_dvdef_t *dvd;
/* See if this variable is filtered out. */
if (fp->ctf_link_variable_filter)
{
void *farg = fp->ctf_link_variable_filter_arg;
if (fp->ctf_link_variable_filter (in_fp, name, type, farg))
return 0;
}
/* If this type is mapped to a type in the parent dict, we want to try to add
to that first: if it reports a duplicate, or if the type is in a child
already, add straight to the child. */
if ((dst_type = ctf_dedup_type_mapping (fp, in_fp, type)) == CTF_ERR)
return -1; /* errno is set for us. */
if (dst_type != 0)
{
if (!ctf_assert (fp, ctf_type_isparent (fp, dst_type)))
return -1; /* errno is set for us. */
if (check_variable (name, fp, dst_type, &dvd))
{
/* No variable here: we can add it. */
if (ctf_add_variable (fp, name, dst_type) < 0)
return -1; /* errno is set for us. */
return 0;
}
/* Already present? Nothing to do. */
if (dvd && dvd->dvd_type == dst_type)
return 0;
}
/* Can't add to the parent due to a name clash, or because it references a
type only present in the child. Try adding to the child, creating if need
be. If we can't do that, skip it. Don't add to a child if we're doing a
CU-mapped link, since that has only one output. */
if (cu_mapped)
{
ctf_dprintf ("Variable %s in input file %s depends on a type %lx hidden "
"due to conflicts: skipped.\n", name,
ctf_unnamed_cuname (in_fp), type);
return 0;
}
if ((per_cu_out_fp = ctf_create_per_cu (fp, in_fp, NULL)) == NULL)
return -1; /* errno is set for us. */
/* If the type was not found, check for it in the child too. */
if (dst_type == 0)
{
if ((dst_type = ctf_dedup_type_mapping (per_cu_out_fp,
in_fp, type)) == CTF_ERR)
return -1; /* errno is set for us. */
if (dst_type == 0)
{
ctf_err_warn (fp, 1, 0, _("type %lx for variable %s in input file %s "
"not found: skipped"), type, name,
ctf_unnamed_cuname (in_fp));
/* Do not terminate the link: just skip the variable. */
return 0;
}
}
if (check_variable (name, per_cu_out_fp, dst_type, &dvd))
if (ctf_add_variable (per_cu_out_fp, name, dst_type) < 0)
return (ctf_set_errno (fp, ctf_errno (per_cu_out_fp)));
return 0;
}
typedef struct link_sort_inputs_cb_arg
{
int is_cu_mapped;
@@ -934,72 +826,9 @@ ctf_link_deduplicating_close_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names,
return 0;
}
/* Do a deduplicating link of all variables in the inputs.
Also, if we are not omitting the variable section, integrate all symbols from
the symtypetabs into the variable section too. (Duplication with the
symtypetab section in the output will be eliminated at serialization time.) */
static int
ctf_link_deduplicating_variables (ctf_dict_t *fp, ctf_dict_t **inputs,
size_t ninputs, int cu_mapped)
{
size_t i;
for (i = 0; i < ninputs; i++)
{
ctf_next_t *it = NULL;
ctf_id_t type;
const char *name;
/* First the variables on the inputs. */
while ((type = ctf_variable_next (inputs[i], &it, &name)) != CTF_ERR)
{
if (ctf_link_one_variable (fp, inputs[i], name, type, cu_mapped) < 0)
{
ctf_next_destroy (it);
return -1; /* errno is set for us. */
}
}
if (ctf_errno (inputs[i]) != ECTF_NEXT_END)
return ctf_set_errno (fp, ctf_errno (inputs[i]));
/* Next the symbols. We integrate data symbols even though the compiler
is currently doing the same, to allow the compiler to stop in
future. */
while ((type = ctf_symbol_next (inputs[i], &it, &name, 0)) != CTF_ERR)
{
if (ctf_link_one_variable (fp, inputs[i], name, type, 1) < 0)
{
ctf_next_destroy (it);
return -1; /* errno is set for us. */
}
}
if (ctf_errno (inputs[i]) != ECTF_NEXT_END)
return ctf_set_errno (fp, ctf_errno (inputs[i]));
/* Finally the function symbols. */
while ((type = ctf_symbol_next (inputs[i], &it, &name, 1)) != CTF_ERR)
{
if (ctf_link_one_variable (fp, inputs[i], name, type, 1) < 0)
{
ctf_next_destroy (it);
return -1; /* errno is set for us. */
}
}
if (ctf_errno (inputs[i]) != ECTF_NEXT_END)
return ctf_set_errno (fp, ctf_errno (inputs[i]));
}
return 0;
}
/* Check for symbol conflicts during linking. Three possibilities: already
exists, conflicting, or nonexistent. We don't have a dvd structure we can
use as a flag like check_variable does, so we use a tristate return
value instead: -1: conflicting; 1: nonexistent: 0: already exists. */
/* Check for symbol conflicts during linking. Three possibilities: already exists,
conflicting, or nonexistent. We use a tristate return value: -1: conflicting; 1:
nonexistent: 0: already exists. */
static int
check_sym (ctf_dict_t *fp, const char *name, ctf_id_t type, int functions)
@@ -1306,15 +1135,6 @@ ctf_link_deduplicating_per_cu (ctf_dict_t *fp)
goto err_inputs_outputs;
}
if (!(fp->ctf_link_flags & CTF_LINK_OMIT_VARIABLES_SECTION)
&& ctf_link_deduplicating_variables (out, inputs, ninputs, 1) < 0)
{
ctf_set_errno (fp, ctf_errno (out));
ctf_err_warn (fp, 0, 0, _("CU-mapped deduplicating link variable "
"emission failed for %s"), out_name);
goto err_inputs_outputs;
}
ctf_dedup_fini (out, outputs, noutputs);
/* For now, we omit symbol section linking for CU-mapped links, until it
@@ -1492,13 +1312,8 @@ ctf_link_deduplicating (ctf_dict_t *fp)
goto err;
}
if (!(fp->ctf_link_flags & CTF_LINK_OMIT_VARIABLES_SECTION)
&& ctf_link_deduplicating_variables (fp, inputs, ninputs, 0) < 0)
{
ctf_err_warn (fp, 0, 0, _("deduplicating link variable emission failed for "
"%s"), ctf_link_input_name (fp));
goto err_clean_outputs;
}
/* UPTODO: variable section omission, possible integration of symtypetabs (?) et
al */
if (ctf_link_deduplicating_syms (fp, inputs, ninputs, 0) < 0)
{

View File

@@ -449,64 +449,28 @@ typedef struct ctf_lookup_idx_key
uint32_t *clik_names;
} ctf_lookup_idx_key_t;
/* A bsearch function for variable names. */
static int
ctf_lookup_var (const void *key_, const void *lookup_)
{
const ctf_lookup_idx_key_t *key = key_;
const ctf_varent_t *lookup = lookup_;
return (strcmp (key->clik_name, ctf_strptr (key->clik_fp, lookup->ctv_name)));
}
/* Given a variable name, return the type of the variable with that name.
Look only in this dict, not in the parent. */
/* Look up some kind of thing in the name tables. */
ctf_id_t
ctf_lookup_variable_here (ctf_dict_t *fp, const char *name)
{
ctf_dvdef_t *dvd = ctf_dvd_lookup (fp, name);
ctf_varent_t *ent;
ctf_lookup_idx_key_t key = { fp, name, NULL };
if (dvd != NULL)
return dvd->dvd_type;
/* This array is sorted, so we can bsearch for it. */
ent = bsearch (&key, fp->ctf_vars, fp->ctf_nvars, sizeof (ctf_varent_t),
ctf_lookup_var);
if (ent == NULL)
return (ctf_set_typed_errno (fp, ECTF_NOTYPEDAT));
return ent->ctv_type;
}
/* As above, but look in the parent too. */
ctf_id_t
ctf_lookup_variable (ctf_dict_t *fp, const char *name)
ctf_lookup_by_kind (ctf_dict_t *fp, int kind, const char *name)
{
ctf_id_t type;
if (fp->ctf_flags & LCTF_NO_STR)
return (ctf_set_typed_errno (fp, ECTF_NOPARENT));
if (kind == CTF_K_TYPE_TAG || kind == CTF_K_DECL_TAG)
return (ctf_set_typed_errno (fp, ECTF_NEVERTAG));
if ((type = ctf_lookup_variable_here (fp, name)) == CTF_ERR)
{
if (ctf_errno (fp) == ECTF_NOTYPEDAT && fp->ctf_parent != NULL)
{
if ((type = ctf_lookup_variable_here (fp->ctf_parent, name)) != CTF_ERR)
return type;
return (ctf_set_typed_errno (fp, ctf_errno (fp->ctf_parent)));
}
if ((type = ctf_dynhash_lookup_type (ctf_name_table (fp, kind),
name)) != CTF_ERR)
return type;
return -1; /* errno is set for us. */
}
if (fp->ctf_parent
&& (type = ctf_dynhash_lookup_type (ctf_name_table (fp->ctf_parent, kind),
name)) != CTF_ERR)
return type;
return ctf_set_typed_errno (fp, ECTF_NOTYPE);
}
return type;
}
/* Look up a single enumerator by enumeration constant name. Returns the ID of

View File

@@ -2223,8 +2223,6 @@ ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
fp->ctf_dthash = ctf_dynhash_create (ctf_hash_integer, ctf_hash_eq_integer,
NULL, NULL);
fp->ctf_dvhash = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
NULL, NULL);
fp->ctf_snapshots = 1;
fp->ctf_objthash = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
@@ -2232,8 +2230,8 @@ ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
fp->ctf_funchash = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
free, NULL);
if (!fp->ctf_dthash || !fp->ctf_dvhash || !fp->ctf_snapshots ||
!fp->ctf_objthash || !fp->ctf_funchash)
if (!fp->ctf_dthash || !fp->ctf_snapshots || !fp->ctf_objthash
|| !fp->ctf_funchash)
{
err = ENOMEM;
goto bad;
@@ -2334,7 +2332,6 @@ void
ctf_dict_close (ctf_dict_t *fp)
{
ctf_dtdef_t *dtd, *ntd;
ctf_dvdef_t *dvd, *nvd;
ctf_in_flight_dynsym_t *did, *nid;
ctf_err_warning_t *err, *nerr;
@@ -2375,13 +2372,6 @@ ctf_dict_close (ctf_dict_t *fp)
ctf_dynhash_destroy (fp->ctf_datasecs);
ctf_dynhash_destroy (fp->ctf_tags);
ctf_dynhash_destroy (fp->ctf_names);
for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
{
nvd = ctf_list_next (dvd);
ctf_dvd_delete (fp, dvd);
}
ctf_dynhash_destroy (fp->ctf_dvhash);
ctf_dynhash_destroy (fp->ctf_var_datasecs);
ctf_dynhash_destroy (fp->ctf_symhash_func);

View File

@@ -497,33 +497,6 @@ emit_symtypetab_index (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp,
return 0;
}
/* Delete variables with the same name as symbols that have been reported by
the linker from the variable section. Must be called from within
ctf_serialize, because that is the only place you can safely delete
variables without messing up ctf_rollback. */
static int
symtypetab_delete_nonstatics (ctf_dict_t *fp, ctf_dict_t *symfp)
{
ctf_dvdef_t *dvd, *nvd;
ctf_id_t type;
for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
{
nvd = ctf_list_next (dvd);
if ((((type = (ctf_id_t) (uintptr_t)
ctf_dynhash_lookup (fp->ctf_objthash, dvd->dvd_name)) > 0)
|| (type = (ctf_id_t) (uintptr_t)
ctf_dynhash_lookup (fp->ctf_funchash, dvd->dvd_name)) > 0)
&& ctf_dynhash_lookup (symfp->ctf_dynsyms, dvd->dvd_name) != NULL
&& type == dvd->dvd_type)
ctf_dvd_delete (fp, dvd);
}
return 0;
}
/* Figure out the sizes of the symtypetab sections, their indexed state,
etc.
@@ -540,13 +513,13 @@ ctf_symtypetab_sect_sizes (ctf_dict_t *fp, emit_symtypetab_state_t *s,
size_t objt_unpadsize, func_unpadsize, objt_padsize, func_padsize;
/* If doing a writeout as part of linking, and the link flags request it,
filter out reported symbols from the variable section, and filter out all
other symbols from the symtypetab sections. (If we are not linking, the
symbols are sorted; if we are linking, don't bother sorting if we are not
filtering out reported symbols: this is almost certainly an ld -r and only
the linker is likely to consume these symtypetabs again. The linker
doesn't care what order the symtypetab entries are in, since it only
iterates over symbols and does not use the ctf_lookup_by_symbol* API.) */
filter out all unreported symbols from the symtypetab sections. (If we are
not linking, the symbols are sorted; if we are linking, don't bother
sorting if we are not filtering out reported symbols: this is almost
certainly an ld -r and only the linker is likely to consume these
symtypetabs again. The linker doesn't care what order the symtypetab
entries are in, since it only iterates over symbols and does not use the
ctf_lookup_by_symbol* API.) */
s->sort_syms = 1;
if (fp->ctf_flags & LCTF_LINKING)
@@ -631,16 +604,6 @@ ctf_symtypetab_sect_sizes (ctf_dict_t *fp, emit_symtypetab_state_t *s,
*funcidx_size = 0;
}
/* If we are filtering symbols out, those symbols that the linker has not
reported have now been removed from the ctf_objthash and ctf_funchash.
Delete entries from the variable section that duplicate newly-added
symbols. There's no need to migrate new ones in: we do that (if necessary)
in ctf_link_deduplicating_variables. */
if (s->filter_syms && s->symfp->ctf_dynsyms &&
symtypetab_delete_nonstatics (fp, s->symfp) < 0)
return -1;
return 0;
}
@@ -1052,27 +1015,6 @@ ctf_emit_type_sect (ctf_dict_t *fp, unsigned char **tptr)
return 0;
}
/* Variable section. */
/* Sort a newly-constructed static variable array. */
typedef struct ctf_sort_var_arg_cb
{
ctf_dict_t *fp;
ctf_strs_t *strtab;
} ctf_sort_var_arg_cb_t;
static int
ctf_sort_var (const void *one_, const void *two_, void *arg_)
{
const ctf_varent_t *one = one_;
const ctf_varent_t *two = two_;
ctf_sort_var_arg_cb_t *arg = arg_;
return (strcmp (ctf_strraw_explicit (arg->fp, one->ctv_name, arg->strtab),
ctf_strraw_explicit (arg->fp, two->ctv_name, arg->strtab)));
}
/* Overall serialization. */
/* Do all aspects of serialization up to strtab writeout and variable table
@@ -1393,13 +1335,6 @@ ctf_serialize (ctf_dict_t *fp, size_t *bufsiz)
if (strtab == NULL)
goto err;
/* Now the string table is constructed and all the refs updated, we can sort
the buffer of ctf_varent_t's. */
ctf_sort_var_arg_cb_t sort_var_arg = { fp, (ctf_strs_t *) strtab };
ctf_qsort_r (fp->ctf_serializing_vars, fp->ctf_serializing_nvars,
sizeof (ctf_varent_t), ctf_sort_var, &sort_var_arg);
if ((newbuf = realloc (fp->ctf_serializing_buf, fp->ctf_serializing_buf_size
+ strtab->cts_len)) == NULL)
goto oom;

View File

@@ -57,6 +57,7 @@ LIBCTF_2.0 {
ctf_lookup_by_name;
ctf_lookup_by_symbol;
ctf_lookup_by_kind;
ctf_symbol_next;
ctf_lookup_by_symbol_name;
ctf_arc_lookup_symbol;