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.)
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.
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)
{
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));
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;
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. */
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. */
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. */
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,
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;
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)
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
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)
{
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_lookup_by_kind (ctf_dict_t *fp, int kind, 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;
+ ctf_id_t type;
- /* This array is sorted, so we can bsearch for it. */
+ if (kind == CTF_K_TYPE_TAG || kind == CTF_K_DECL_TAG)
+ return (ctf_set_typed_errno (fp, ECTF_NEVERTAG));
- ent = bsearch (&key, fp->ctf_vars, fp->ctf_nvars, sizeof (ctf_varent_t),
- ctf_lookup_var);
+ if ((type = ctf_dynhash_lookup_type (ctf_name_table (fp, kind),
+ name)) != CTF_ERR)
+ return type;
- if (ent == NULL)
- return (ctf_set_typed_errno (fp, ECTF_NOTYPEDAT));
+ if (fp->ctf_parent
+ && (type = ctf_dynhash_lookup_type (ctf_name_table (fp->ctf_parent, kind),
+ name)) != CTF_ERR)
+ return type;
- return ent->ctv_type;
+ return ctf_set_typed_errno (fp, ECTF_NOTYPE);
}
-/* As above, but look in the parent too. */
-
-ctf_id_t
-ctf_lookup_variable (ctf_dict_t *fp, const char *name)
-{
- ctf_id_t type;
-
- if (fp->ctf_flags & LCTF_NO_STR)
- return (ctf_set_typed_errno (fp, ECTF_NOPARENT));
-
- 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)));
- }
-
- return -1; /* errno is set for us. */
- }
-
- return type;
}
/* Look up a single enumerator by enumeration constant name. Returns the ID of
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,
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;
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;
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);
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.
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)
*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;
}
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
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;
ctf_lookup_by_name;
ctf_lookup_by_symbol;
+ ctf_lookup_by_kind;
ctf_symbol_next;
ctf_lookup_by_symbol_name;
ctf_arc_lookup_symbol;