libctf: v4: symtypetab unifications

The v4 symtypetab design is quite different from v3. Where v3 has a pair
of possibly indexed symtypetabs per dict, v4 uses a pair of symtypetabs
in two ELF sections, one per ELF object: one has straight ctf_id_t's in
it and relates to the parent dict, the other a pair of (index, ctF_id_t)
relating to other dicts.  The symtypetab is always indexed: the old 1:1
"like the symtab if the symtypetab only contained STT_FUNC and
STT_OBJECT symbols, with some symbols dropped" scheme is gone entirely,
and with it all the arbitrary decisions that went with it (when to use
indexed versus 1:1 representation, which symbols to skip, etc) and its
fragility (if a single symbol is assigned to the wrong table, disaster
results: see commit 211bcd0133 for an example of this biting in real
life).

As a first phase, unify the object and function info sections and drop
the indexed/non-indexed representation. Symtypetab support in the
resulting library doesn't work any more, but it didn't work before now
in v4 anyway, so this is no loss.  Future commits will fix this.

Also drop all the caching machinery for symbol lookups: it's only there
because we might need to consult many symtypetabs to look up types of
symbols in child dicts, which will no longer be true after these
changes.

(API changes introduced by this series will be indicated in the last
commit in the series.)
This commit is contained in:
Nick Alcock 2026-06-17 15:46:05 +01:00
parent 40324c4034
commit d2f3633152
15 changed files with 471 additions and 1187 deletions

View file

@ -1081,11 +1081,10 @@ ctf_add_var_cb (ctf_dict_t *fp, const char *name, ctf_id_t id,
set_symbol_address (ccp->of, sym, name);
}
/* Add entries in either data objects or function info section, controlled
by FUNCTIONS. */
/* Add entries in the symtypetab. */
static void
add_stt_entries (struct ctf_context *ccp, ctf_funcobjt_t functions)
add_stt_entries (struct ctf_context *ccp)
{
ctf_next_t *i = nullptr;
const char *tname;
@ -1093,7 +1092,7 @@ add_stt_entries (struct ctf_context *ccp, ctf_funcobjt_t functions)
struct symbol *sym = nullptr;
struct type *type;
while ((tid = ctf_symbol_next (ccp->dict, &i, &tname, functions)) != CTF_ERR)
while ((tid = ctf_symbol_next (ccp->dict, &i, &tname)) != CTF_ERR)
{
type = get_tid_type (ccp->of, tid);
if (type == nullptr)
@ -1101,7 +1100,9 @@ add_stt_entries (struct ctf_context *ccp, ctf_funcobjt_t functions)
sym = new (&ccp->of->objfile_obstack) symbol;
OBJSTAT (ccp->of, n_syms++);
sym->set_type (type);
sym->set_domain (functions ? FUNCTION_DOMAIN : VAR_DOMAIN);
/* XXX use the stt_type. */
sym->set_domain (ctf_type_kind (ccp->dict, tid) == CTF_K_FUNCTION
? FUNCTION_DOMAIN : VAR_DOMAIN);
sym->set_loc_class_index (LOC_STATIC);
sym->compute_and_set_names (tname, false, ccp->of->per_bfd);
add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
@ -1109,22 +1110,6 @@ add_stt_entries (struct ctf_context *ccp, ctf_funcobjt_t functions)
}
}
/* Add entries in data objects section. */
static void
add_stt_obj (struct ctf_context *ccp)
{
add_stt_entries (ccp, CTF_STT_OBJT);
}
/* Add entries in function info section. */
static void
add_stt_func (struct ctf_context *ccp)
{
add_stt_entries (ccp, CTF_STT_FUNC);
}
/* Get text section base for OBJFILE, TSIZE contains the size. */
static CORE_ADDR
@ -1159,27 +1144,33 @@ ctf_psymtab_add_enums (struct ctf_context *ccp, ctf_id_t tid)
ctf_errmsg (ctf_errno (ccp->dict)));
}
/* Add entries in either data objects or function info section, controlled
by FUNCTIONS, to psymtab. */
/* Add entries in the symtypetab to the psymtab. */
static void
ctf_psymtab_add_stt_entries (ctf_dict_t *dict, ctf_psymtab *pst,
struct objfile *of, ctf_funcobjt_t functions)
struct objfile *of)
{
ctf_next_t *i = nullptr;
ctf_id_t tid;
const char *tname;
while ((tid = ctf_symbol_next (dict, &i, &tname, functions)) != CTF_ERR)
while ((tid = ctf_symbol_next (dict, &i, &tname)) != CTF_ERR)
{
ctf_kind_t kind = ctf_type_kind (dict, tid);
location_class loc_class;
domain_enum tdomain = functions ? FUNCTION_DOMAIN : VAR_DOMAIN;
domain_enum tdomain;
if (kind == CTF_K_FUNCTION)
loc_class = LOC_BLOCK;
{
/* XXX should use stt_type. */
tdomain = FUNCTION_DOMAIN;
loc_class = LOC_BLOCK;
}
else
loc_class = LOC_STATIC;
{
tdomain = VAR_DOMAIN;
loc_class = LOC_STATIC;
}
pst->add_psymbol (tname, true,
tdomain, loc_class, -1,
@ -1189,22 +1180,12 @@ ctf_psymtab_add_stt_entries (ctf_dict_t *dict, ctf_psymtab *pst,
}
}
/* Add entries in data objects section to psymtab. */
/* Add entries in symtypetab to psymtab. */
static void
ctf_psymtab_add_stt_obj (ctf_dict_t *dict, ctf_psymtab *pst,
struct objfile *of)
ctf_psymtab_add_stt (ctf_dict_t *dict, ctf_psymtab *pst, struct objfile *of)
{
ctf_psymtab_add_stt_entries (dict, pst, of, CTF_STT_OBJT);
}
/* Add entries in function info section to psymtab. */
static void
ctf_psymtab_add_stt_func (ctf_dict_t *dict, ctf_psymtab *pst,
struct objfile *of)
{
ctf_psymtab_add_stt_entries (dict, pst, of, CTF_STT_FUNC);
ctf_psymtab_add_stt_entries (dict, pst, of);
}
/* Read in full symbols for PST, and anything it depends on. */
@ -1239,9 +1220,8 @@ ctf_psymtab::expand_psymtab (struct objfile *objfile)
complaint (_("ctf_type_kind_next (variables) psymtab_to_symtab failed - %s"),
ctf_errmsg (ctf_errno (ccp->dict)));
/* Add entries in data objects and function info sections. */
add_stt_obj (ccp);
add_stt_func (ccp);
/* Add entries in symtypetab. */
add_stt_entries (ccp);
readin = true;
}
@ -1429,11 +1409,10 @@ scan_partial_symbols (ctf_dict_t *dict, psymtab_storage *partial_symtabs,
complaint (_("ctf_type_kind_next (variables) scan_partial_symbols failed - %s"),
ctf_errmsg (ctf_errno (dict)));
/* Scan CTF object and function sections which correspond to each
STT_FUNC or STT_OBJECT entry in the symbol table,
pick up what init_symtab has done. */
ctf_psymtab_add_stt_obj (dict, pst, of);
ctf_psymtab_add_stt_func (dict, pst, of);
/* Scan CTF symtypetab sections which correspond to each STT_FUNC or
STT_OBJECT entry in the symbol table, pick up what init_symtab has
done. */
ctf_psymtab_add_stt (dict, pst, of);
pst->end ();
}

View file

@ -105,9 +105,9 @@ typedef enum ctf_elfsect_names
filling in ctf_sect_t structures and passing them to ctf_bufopen et al via
the ctf_open_sect_t function.
At read time, the symbol table endianness is derived from the BFD target (if
BFD is in use): if a BFD target is not in use, please call
ctf_symsect_endianness or ctf_arc_symsect_endianness. */
At read time, the symbol table endianness is derived from the BFD target
(if BFD is in use): if a BFD target is not in use, please call
ctf_arc_symsect_endianness. */
typedef struct ctf_sect
{
@ -738,17 +738,10 @@ extern const char **ctf_func_arg_names (ctf_dict_t *, ctf_id_t, size_t *nargs);
extern ctf_linkages_t ctf_type_linkage (ctf_dict_t *, ctf_id_t);
/* Traverse all (function or data) symbols in a dict, one by one, and return the
type of each and (if NAME is non-NULL) optionally its name. */
/* Traverse all symbols in a dict, one by one, and return the type of each
and (if NAME is non-NULL) optionally its name. */
typedef enum ctf_funcobjt
{
CTF_STT_OBJT = 0,
CTF_STT_FUNC = 1
} ctf_funcobjt_t;
extern ctf_id_t ctf_symbol_next (ctf_dict_t *, ctf_next_t **,
const char **name, ctf_funcobjt_t functions);
extern ctf_id_t ctf_symbol_next (ctf_dict_t *, ctf_next_t **, const char **name);
/* Look up an identifier (type or variable) by name: some simple C type parsing
is done, but this is by no means comprehensive. Structures, unions and enums
@ -1226,12 +1219,11 @@ extern ctf_ret_t ctf_array_set_info (ctf_dict_t *, ctf_id_t, const ctf_arinfo_t
extern ctf_ret_t ctf_type_set_conflicting (ctf_dict_t *, ctf_id_t type,
const char *cuname);
/* Add a function or object symbol type with a particular name, without saying
anything about the actual symbol index. (The linker will then associate them
with actual symbol indexes using the ctf_link functions below.) */
/* Add a type for a symbol with a particular name, without saying anything
about the actual symbol index. (The linker will then associate them with
actual symbol indexes using the ctf_link functions below.) */
extern ctf_ret_t ctf_add_funcobjt_sym (ctf_dict_t *fp, ctf_funcobjt_t function,
const char *name, ctf_id_t id);
extern ctf_ret_t ctf_add_sym (ctf_dict_t *fp, const char *name, ctf_id_t id);
/* Snapshot/rollback. Call ctf_snapshot to return a snapshot ID: pass
one of these IDs to ctf_rollback to discard all types added since the
@ -1388,12 +1380,11 @@ typedef char *ctf_link_memb_name_changer_f (ctf_dict_t *,
extern void ctf_link_set_memb_name_changer
(ctf_dict_t *, ctf_link_memb_name_changer_f *, void *);
/* Filter out unwanted variables, which can be very voluminous, and (unlike
symbols) cause the CTF string table to grow to hold their names. The
variable filter should return nonzero if a variable should not appear in the
output. */
typedef ctf_bool_t ctf_link_variable_filter_f (ctf_dict_t *, const char *, ctf_id_t,
void *);
/* Filter out unwanted variables, which can be very voluminous, and cause the
CTF string table to grow to hold their names. The variable filter should
return nonzero if a variable (or symbol) should not appear in the output. */
typedef ctf_bool_t ctf_link_variable_filter_f (ctf_dict_t *, const char *,
ctf_id_t, void *);
extern ctf_bool_t ctf_link_set_variable_filter (ctf_dict_t *,
ctf_link_variable_filter_f *, void *);

View file

@ -50,33 +50,54 @@ extern "C"
typically named .ctf. Data structures are aligned so that a raw CTF file or
CTF ELF section may be manipulated using mmap(2).
The CTF file or section is a superset of BTF, and has the following structure:
The CTF file or section is a superset of BTF, and has a similar structure:
+--------+--------+---------+----------+--------+----------+...
+ BTF | CTF | data | function | object | function |...
| header | header | objects | info | index | index |...
+--------+--------+----------+--------+-------------------+...
...+-------+--------+--------+
...| data | kind | string |
...| types | layout | table |
+-------+--------+--------+
hdr_len->|
+--------+--------+-------+--------+--------+
+ BTF | CTF | data | kind | string |
| header | header | types | layout | table |
+--------+--------+-------+--------+--------+
The file header stores a magic number and version information, encoding
flags, and the byte offset and length of each of the sections relative to
the end of the header itself. There are two headers: the BTF header contains
flags, and the byte offset and length of each of the sections relative to the
end of the header itself. There are two headers: the BTF header contains
offsets relative to the end of the BTF header, and immediately following it
there may be a CTF header containing offsets relative to the end of the CTF
header. If the BTF header is not followed by a CTFv4_MAGIC, no CTF header
is present and this dict is pure BTF (and cannot contain CTF-specific type
kinds).
there may be a CTF header: this header contains no sections at present, just
other non-sectoin fields. If the BTF header is not followed by a
CTFv4_MAGIC, no CTF header is present and this dict is pure BTF (and cannot
contain CTF-specific type kinds).
If the CTF data has been uniquified against another set of CTF data, a
reference to that data also appears in the the header. This reference is the
name of the parent dict containing the types uniquified against.
The data types section is a list of variable size records that represent each
type, in order by their ID. The types themselves form a directed graph,
where each node may contain one or more outgoing edges to other type nodes,
denoted by their ID. Most type nodes are standalone or point backwards to
earlier nodes, but this is not required: nodes can point to later nodes,
particularly structure and union members.
Variables records are stored as in BTF. Unlike in BTF, we can encode
arbitrary variables that way, and usually store either everything, or
everything that has corresponding entries in the symtypetabs. We do not
define how the consumer maps these variable names to addresses or anything
else, or indeed what these names represent: they might be names looked up at
runtime via dlsym() or names extracted at runtime by a debugger or anything
else the consumer likes.
In BTF-compatible mode, strings are recorded as a straight byte offset into
the string table, which is deduplicated against the parent and itself and
sorted into ASCIIbetical order. In BTF-incompatible mode (dict flag of
CTF_DICT_BTF_INCOMPAT), strings are recorded as a string table ID (0 or 1)
and a byte offset into the string table. String table 0 is the internal CTF
string table. String table 1 is the external string table, which is usually
the string table associated with the ELF dynamic symbol table for this
object. CTF does not record any strings that are already in the symbol
table, and the CTF string table does not contain any duplicated strings.
Data object and function records (collectively, "symtypetabs") are stored in
the same order as they appear in the corresponding symbol table, except that
separate ELF sections named the same order as they appear in the corresponding symbol table, except that
symbols marked SHN_UNDEF are not stored and symbols that have no type data
are padded out with zeroes. For each entry in these tables, the type ID (a
small integer) is recorded. (Functions get CTF_K_FUNCTION types, just like
@ -90,29 +111,6 @@ extern "C"
sections a name so that the linker can correlate them with final symtab
entries and reorder them accordingly (dropping the indexes in the process).
Variable records (as distinct from data objects) provide a modicum of support
for non-ELF systems, mapping a variable or function name to a CTF type ID.
The names are sorted into ASCIIbetical order, permitting binary searching.
We do not define how the consumer maps these variable names to addresses or
anything else, or indeed what these names represent: they might be names
looked up at runtime via dlsym() or names extracted at runtime by a debugger
or anything else the consumer likes. Variable records with identically-
named entries in the data object or function index section are removed.
The data types section is a list of variable size records that represent each
type, in order by their ID. The types themselves form a directed graph,
where each node may contain one or more outgoing edges to other type nodes,
denoted by their ID. Most type nodes are standalone or point backwards to
earlier nodes, but this is not required: nodes can point to later nodes,
particularly structure and union members.
Strings are recorded as a string table ID (0 or 1) and a byte offset into the
string table. String table 0 is the internal CTF string table. String table
1 is the external string table, which is the string table associated with the
ELF dynamic symbol table for this object. CTF does not record any strings
that are already in the symbol table, and the CTF string table does not
contain any duplicated strings.
If the CTF data has been merged with another parent CTF object, some outgoing
edges may refer to type nodes that exist in another CTF object. The debugger
and libctf library are responsible for connecting the appropriate objects
@ -289,11 +287,13 @@ typedef struct ctf_header
#define CTF_BTF_VERSION 1
/* All of these flags bar CTF_F_COMPRESS and CTF_F_IDXSORTED are bug-workaround
flags and are valid only in format v3: in v2 and below they cannot occur and
in v4 and later, they will be recycled for other purposes. CTF_F_COMPRESS
is only valid in CTFv3 and below: CTFv4 relies on external compression (such
as ELF compresed sections). */
/* All of these flags bar CTF_F_COMPRESS and CTF_F_IDXSORTED are
bug-workaround flags; all of these flags without exception are valid only
in format v3: in v2 and below they cannot occur and in v4 and later,
their values will be recycled for other purposes. Of the
non-bug-workaround flags, CTFv4 relies on external compression (such as
ELF compresed sections), and libctf figures out whether the index section
is sorted without needing flags to help. */
#define CTF_F_COMPRESS 0x1 /* Data buffer is compressed by libctf. */
#define CTF_F_NEWFUNCINFO 0x2 /* New v3 func info section format. */

View file

@ -167,8 +167,7 @@ ctf_dict_flag (ctf_dict_t *fp, ctf_dict_flags_t flag)
return (fp->ctf_header->cth_objt_len > 0
|| fp->ctf_header->cth_func_len > 0
|| fp->ctf_dynsymidx
|| (fp->ctf_objthash && ctf_dynhash_elements (fp->ctf_objthash) > 0)
|| (fp->ctf_funchash && ctf_dynhash_elements (fp->ctf_funchash) > 0));
|| (fp->ctf_symtypehash && ctf_dynhash_elements (fp->ctf_symtypehash) > 0));
default:
return (ctf_set_errno (fp, ECTF_BADFLAG));
}

View file

@ -949,7 +949,7 @@ ctf_arc_symsect_endianness (struct ctf_archive_internal *arci, int little_endian
{
arci->ctfi_symsect_little_endian = !!little_endian;
if (arci->ctfi_dict)
ctf_symsect_endianness (arci->ctfi_dict, arci->ctfi_symsect_little_endian);
arci->ctfi_dict->ctf_symsect_little_endian = !!little_endian;
}
/* Return various ELF sections related to CTF. The archive counterpart of
@ -1243,8 +1243,7 @@ ctf_arc_set_parent (struct ctf_archive_internal *arci, ctf_dict_t *parent)
static ctf_dict_t *
ctf_dict_open_by_offset (struct ctf_archive_internal *arci,
ctf_open_sect_t *sects, size_t offset, size_t len,
ctf_dict_t *parent, int little_endian_symtab,
ctf_error_t *errp)
ctf_dict_t *parent, ctf_error_t *errp)
{
ctf_sect_t ctfsect = {0};
ctf_dict_t *fp;
@ -1271,8 +1270,8 @@ ctf_dict_open_by_offset (struct ctf_archive_internal *arci,
if (!fp)
return NULL; /* errno is set for us. */
if (little_endian_symtab >= 0)
ctf_symsect_endianness (fp, little_endian_symtab);
if (arci->ctfi_symsect_little_endian >= 0)
fp->ctf_symsect_little_endian = arci->ctfi_symsect_little_endian;
/* Set the CU name if unset, either by looking up the name for the member
at this offset in the strtab, or by using a linker-set default
@ -1355,7 +1354,7 @@ ctf_dict_open_by_index (struct ctf_archive_internal *arci, size_t index,
fp = ctf_dict_open_by_offset (arci, ctf_open_sect (ctf_open_sect (NULL, symsectp), strsectp),
arci->ctfi_members[index], len, parent,
arci->ctfi_symsect_little_endian, errp);
errp);
if (fp)
{
fp->ctf_archive = (struct ctf_archive_internal *) arci;
@ -1424,8 +1423,7 @@ ctf_cached_dict_close (void *fp)
}
/* Return the ctf_dict_t with the given index and cache it in the archive's
ctfi_dicts. If this is the first cached dict, designate it the
crossdict_cache. The archive is already known not to be a wrapper. */
ctfi_dicts. The archive is already known not to be a wrapper. */
static ctf_dict_t *
ctf_dict_open_cached (struct ctf_archive_internal *arci, size_t index,
ctf_error_t *errp)
@ -1464,9 +1462,6 @@ ctf_dict_open_cached (struct ctf_archive_internal *arci, size_t index,
goto oom;
fp->ctf_refcnt++;
if (arci->ctfi_crossdict_cache == NULL)
arci->ctfi_crossdict_cache = fp;
/* If this archive has multiple members, and this is a parent, pretend
that we have opened at least one child. This forces type and string
allocations in the parent to use provisional IDs, permitting you to
@ -1498,7 +1493,6 @@ ctf_arc_flush_caches (struct ctf_archive_internal *arci)
arci->ctfi_symdicts = NULL;
arci->ctfi_symnamedicts = NULL;
arci->ctfi_dicts = NULL;
arci->ctfi_crossdict_cache = NULL;
}
/* Return the number of members in an archive. */

View file

@ -2221,27 +2221,24 @@ ctf_remove_datasec (ctf_dict_t *fp, ctf_id_t type, const char *name,
_("iteration error rolling back addition of variable %s"), name);
}
/* Add a function or object symbol regardless of whether or not it is already
/* Add a type for a symbol regardless of whether or not it is already
present (already existing symbols are silently overwritten).
Internal use only. */
ctf_ret_t
ctf_add_funcobjt_sym_forced (ctf_dict_t *fp, int is_function, const char *name, ctf_id_t id)
ctf_add_sym_forced (ctf_dict_t *fp, const char *name, ctf_id_t id)
{
ctf_dict_t *tmp = fp;
char *dupname;
ctf_dynhash_t *h = is_function ? fp->ctf_funchash : fp->ctf_objthash;
if (ctf_lookup_by_id (&tmp, id, NULL) == NULL)
return -1; /* errno is set for us. */
if (is_function && ctf_type_kind (fp, id) != CTF_K_FUNCTION)
return (ctf_set_errno (fp, ECTF_NOTFUNC));
if ((dupname = strdup (name)) == NULL)
return (ctf_set_errno (fp, ENOMEM));
if (ctf_dynhash_insert (h, dupname, (void *) (uintptr_t) id) < 0)
if (ctf_dynhash_insert (fp->ctf_symtypehash, dupname,
(void *) (uintptr_t) id) < 0)
{
free (dupname);
return (ctf_set_errno (fp, ENOMEM));
@ -2250,14 +2247,14 @@ ctf_add_funcobjt_sym_forced (ctf_dict_t *fp, int is_function, const char *name,
}
ctf_ret_t
ctf_add_funcobjt_sym (ctf_dict_t *fp, ctf_funcobjt_t function, const char *name, ctf_id_t id)
ctf_add_sym (ctf_dict_t *fp, const char *name, ctf_id_t id)
{
if (ctf_lookup_by_sym_or_name (fp, 0, name, 0, function) != CTF_ERR)
if (ctf_lookup_by_sym_or_name (fp, 0, name, 0) != CTF_ERR)
return (ctf_set_errno (fp, ECTF_DUPLICATE));
fp->ctf_serialize.cs_initialized = 0;
return ctf_add_funcobjt_sym_forced (fp, function, name, id);
return ctf_add_sym_forced (fp, name, id);
}
/* Sort function used by ctf_datasec_sort. */

View file

@ -570,23 +570,20 @@ ctf_dump_header (ctf_dict_t *fp, ctf_dump_state_t *state)
return (ctf_set_errno (fp, errno));
}
/* Dump all the object or function entries into the cds_items. */
/* Dump all the symtypetab entries into the cds_items. */
static int
ctf_dump_objts (ctf_dict_t *fp, ctf_dump_state_t *state, ctf_funcobjt_t functions)
ctf_dump_symtypetabs (ctf_dict_t *fp, ctf_dump_state_t *state)
{
const char *name;
ctf_id_t id;
ctf_next_t *i = NULL;
char *str = NULL;
if ((functions && fp->ctf_funcidx_names)
|| (!functions && fp->ctf_objtidx_names))
str = str_append (str, _("Section is indexed.\n"));
else if (fp->ctf_ext_symtab.cts_data == NULL)
if (fp->ctf_ext_symtab.cts_data == NULL)
str = str_append (str, _("No symbol table.\n"));
while ((id = ctf_symbol_next (fp, &i, &name, functions)) != CTF_ERR)
while ((id = ctf_symbol_next (fp, &i, &name)) != CTF_ERR)
{
char *typestr = NULL;
@ -1033,12 +1030,10 @@ ctf_dump (ctf_dict_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect,
case CTF_SECT_HEADER:
ctf_dump_header (fp, state);
break;
/* UPTODO: fix this for ELF-section symtypetabs. */
case CTF_SECT_OBJT:
if (ctf_dump_objts (fp, state, CTF_STT_OBJT) < 0)
goto err; /* errno is set for us. */
break;
case CTF_SECT_FUNC:
if (ctf_dump_objts (fp, state, CTF_STT_FUNC) < 0)
if (ctf_dump_symtypetabs (fp, state) < 0)
goto err; /* errno is set for us. */
break;
case CTF_SECT_VAR:

View file

@ -44,15 +44,6 @@ extern "C"
{
#endif
/* Tuning. */
/* The proportion of symtypetab entries which must be pads before we consider it
worthwhile to emit a symtypetab section as an index. Indexes cost time to
look up, but save space all told. Do not set to 1, since this will cause
indexes to be eschewed completely, even in child dicts, at considerable space
cost. */
#define CTF_INDEX_PAD_THRESHOLD .75
/* Compiler attributes. */
#if defined (__GNUC__)
@ -446,9 +437,6 @@ struct ctf_dict
ctf_sect_t ctf_ext_symtab; /* Symbol table from object file. */
ctf_sect_t ctf_ext_strtab; /* String table from object file. */
int ctf_symsect_little_endian; /* Endianness of the ctf_ext_symtab. */
ctf_dynhash_t *ctf_symhash_func; /* (partial) hash, symsect name -> idx. */
ctf_dynhash_t *ctf_symhash_objt; /* ditto, for object symbols. */
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. */
@ -480,9 +468,6 @@ struct ctf_dict
ctf_btf_layout_t *ctf_layout; /* CTF layout section (if any). */
int ctf_alien; /* True if this dict contains foreign kinds. */
ctf_serialize_t ctf_serialize; /* State internal to ctf-serialize.c. */
uint32_t *ctf_sxlate; /* Translation table for unindexed symtypetab
entries. */
unsigned long ctf_nsyms; /* Number of entries in symtab xlate table. */
ctf_type_t **ctf_txlate; /* Translation table for type IDs. */
uint32_t *ctf_ptrtab; /* Translation table for pointer-to lookups. */
size_t ctf_ptrtab_len; /* Num types storable in ptrtab currently. */
@ -492,15 +477,11 @@ struct ctf_dict
ctf_type_t *ctf_void_type; /* void type, if dynamically constructed. (More
space allocated, due to vlen.) */
ctf_dynset_t *ctf_conflicting_enums; /* Tracks enum constants that conflict. */
uint32_t *ctf_funcidx_names; /* Name of each function symbol in symtypetab
(if indexed). */
uint32_t *ctf_objtidx_names; /* Likewise, for object symbols. */
size_t ctf_nfuncidx; /* Number of funcidx entries. */
uint32_t *ctf_funcidx_sxlate; /* Offsets into funcinfo for a given funcidx. */
uint32_t *ctf_objtidx_sxlate; /* Likewise, for ctf_objtidx. */
size_t ctf_nobjtidx; /* Number of objtidx entries. */
ctf_dynhash_t *ctf_objthash; /* Dynamic: name -> type ID. */
ctf_dynhash_t *ctf_funchash; /* Dynamic: name -> CTF_K_FUNCTION type ID. */
uint32_t *ctf_symtypeidx_names; /* Name of each symbol in symtypetab (if indexed). */
uint32_t *ctf_symtypeidx_alloc; /* Dynamically-allocated ctf_symidx_names. */
size_t ctf_nsymtypeidx; /* Number of indexed type entries. */
uint32_t *ctf_symtypeidx_sxlate;/* Offsets into syminfo for a given symtypeidx. */
ctf_dynhash_t *ctf_symtypehash; /* Dynamic: name -> type ID. */
/* The next three are linker-derived state found in ctf_link targets only. */
@ -619,7 +600,6 @@ struct ctf_archive_internal
int ctfi_has_strtab; /* 1 if this archive has a strtab. */
ctf_dict_t *ctfi_parent; /* Parent dict. */
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_dynhash_t *ctfi_symnamedicts; /* Hash of name -> ctf_dict_t *. */
ctf_sect_t ctfi_symsect;
@ -731,8 +711,7 @@ extern const ctf_type_t *ctf_lookup_by_id (ctf_dict_t **, ctf_id_t,
extern const ctf_type_t *ctf_find_prefix (ctf_dict_t *, const ctf_type_t *,
ctf_kind_t kind);
extern ctf_id_t ctf_lookup_by_sym_or_name (ctf_dict_t *, unsigned long symidx,
const char *symname, int try_parent,
int is_function);
const char *symname, int try_parent);
extern int ctf_refresh_pptrtab (ctf_dict_t *);
extern ctf_id_t ctf_lookup_by_rawname (ctf_dict_t *, ctf_kind_t, const char *);
extern ctf_id_t ctf_lookup_by_symbol (ctf_dict_t *, unsigned long);
@ -740,7 +719,7 @@ extern ctf_id_t ctf_lookup_by_symbol_name (ctf_dict_t *, const char *);
extern void ctf_set_ctl_hashes (ctf_dict_t *);
extern ctf_id_t ctf_symbol_next_static (ctf_dict_t *, ctf_next_t **,
const char **, ctf_funcobjt_t);
const char **);
extern int ctf_symtab_skippable (ctf_link_sym_t *sym);
@ -839,8 +818,7 @@ extern ctf_dtdef_t *ctf_dynamic_type (const ctf_dict_t *, ctf_id_t);
extern ctf_id_t ctf_add_encoded (ctf_dict_t *, const char *,
const ctf_encoding_t *, ctf_kind_t kind);
extern ctf_ret_t ctf_add_funcobjt_sym_forced (ctf_dict_t *, int is_function,
const char *, ctf_id_t);
extern ctf_ret_t ctf_add_sym_forced (ctf_dict_t *, const char *, ctf_id_t);
extern int ctf_insert_type_decl_tag (ctf_dict_t *, ctf_id_t, const char *);
extern int ctf_insert_decl_tag_rmap (ctf_dict_t *fp, ctf_id_t tag_type,
@ -915,7 +893,6 @@ extern ctf_dict_t *ctf_bufopen_len (ctf_open_sect_t *sects,
ctf_archive_t *ctf_archive,
ctf_import_flags_t import_flags,
ctf_error_t *errp);
extern void ctf_symsect_endianness (ctf_dict_t *fp, int little_endian);
extern ctf_ret_t ctf_write_thresholded (ctf_dict_t *fp, int fd, size_t threshold);

View file

@ -859,18 +859,12 @@ ctf_link_deduplicating_close_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names,
nonexistent: 0: already exists. */
static int
check_sym (ctf_dict_t *fp, const char *name, ctf_id_t type, int functions)
check_sym (ctf_dict_t *fp, const char *name, ctf_id_t type)
{
ctf_dynhash_t *thishash = functions ? fp->ctf_funchash : fp->ctf_objthash;
ctf_dynhash_t *thathash = functions ? fp->ctf_objthash : fp->ctf_funchash;
void *value;
/* Wrong type (function when object is wanted, etc). */
if (ctf_dynhash_lookup_kv (thathash, name, NULL, NULL))
return -1;
/* Not present at all yet. */
if (!ctf_dynhash_lookup_kv (thishash, name, NULL, &value))
if (!ctf_dynhash_lookup_kv (fp->ctf_symtypehash, name, NULL, &value))
return 1;
/* Already present. */
@ -881,18 +875,17 @@ check_sym (ctf_dict_t *fp, const char *name, ctf_id_t type, int functions)
return -1;
}
/* Do a deduplicating link of one symtypetab (function info or data object) in
one input dict. */
/* Do a deduplicating link of the symtypetab to one input dict. */
static ctf_ret_t
ctf_link_deduplicating_one_symtypetab (ctf_dict_t *fp, ctf_dict_t *input,
int cu_mapped, int functions)
int cu_mapped)
{
ctf_next_t *it = NULL;
const char *name;
ctf_id_t type;
while ((type = ctf_symbol_next (input, &it, &name, functions)) != CTF_ERR)
while ((type = ctf_symbol_next (input, &it, &name)) != CTF_ERR)
{
ctf_id_t dst_type;
ctf_dict_t *per_cu_out_fp;
@ -908,7 +901,7 @@ ctf_link_deduplicating_one_symtypetab (ctf_dict_t *fp, ctf_dict_t *input,
if (!ctf_assert (fp, ctf_type_isparent (fp, dst_type)))
goto err; /* errno is set for us. */
sym = check_sym (fp, name, dst_type, functions);
sym = check_sym (fp, name, dst_type);
/* Already present: next symbol. */
if (sym == 0)
@ -916,8 +909,7 @@ ctf_link_deduplicating_one_symtypetab (ctf_dict_t *fp, ctf_dict_t *input,
/* Not present: add it. */
else if (sym > 0)
{
if (ctf_add_funcobjt_sym (fp, functions,
name, dst_type) < 0)
if (ctf_add_sym (fp, name, dst_type) < 0)
goto err; /* errno is set for us. */
continue;
}
@ -954,7 +946,7 @@ ctf_link_deduplicating_one_symtypetab (ctf_dict_t *fp, ctf_dict_t *input,
}
}
sym = check_sym (per_cu_out_fp, name, dst_type, functions);
sym = check_sym (per_cu_out_fp, name, dst_type);
/* Already present: next symbol. */
if (sym == 0)
@ -962,8 +954,7 @@ ctf_link_deduplicating_one_symtypetab (ctf_dict_t *fp, ctf_dict_t *input,
/* Not present: add it. */
else if (sym > 0)
{
if (ctf_add_funcobjt_sym (per_cu_out_fp, functions,
name, dst_type) < 0)
if (ctf_add_sym (per_cu_out_fp, name, dst_type) < 0)
goto err; /* errno is set for us. */
}
else
@ -977,9 +968,8 @@ ctf_link_deduplicating_one_symtypetab (ctf_dict_t *fp, ctf_dict_t *input,
}
if (ctf_errno (input) != ECTF_NEXT_END)
{
return ctf_err (link_err_locus (fp, input, -1), 0, functions ?
_("iterating over function symbols") :
_("iterating over data symbols"));
return ctf_err (link_err_locus (fp, input, -1), 0,
_("iterating over symbols"));
}
return 0;
@ -1000,11 +990,7 @@ ctf_link_deduplicating_syms (ctf_dict_t *fp, ctf_dict_t **inputs,
for (i = 0; i < ninputs; i++)
{
if (ctf_link_deduplicating_one_symtypetab (fp, inputs[i],
cu_mapped, 0) < 0)
return -1; /* errno is set for us. */
if (ctf_link_deduplicating_one_symtypetab (fp, inputs[i],
cu_mapped, 1) < 0)
cu_mapped) < 0)
return -1; /* errno is set for us. */
}

View file

@ -17,6 +17,7 @@
along with this program; see the file COPYING. If not see
<http://www.gnu.org/licenses/>. */
#include "ctf-api.h"
#include <ctf-impl.h>
#include <elf.h>
#include <string.h>
@ -687,14 +688,16 @@ sort_symidx_by_name (const void *one_, const void *two_, void *arg_)
/* Sort a symbol index section by name. Takes a 1:1 mapping of names to the
corresponding symbol table. Returns a lexicographically sorted array of idx
indexes (and thus, of indexes into the corresponding func info / data object
section). */
section). The array is only sorted if necessary. Only called once for
any given symbol index section. */
static uint32_t *
ctf_symidx_sort (ctf_dict_t *fp, uint32_t *idx, size_t *nidx,
size_t len)
ctf_symidx_sort (ctf_dict_t *fp, uint32_t *idx, size_t *nidx, size_t len)
{
uint32_t *sorted;
uint32_t *sorted = NULL;
size_t i;
int needs_sort = 0;
const char *last = NULL;
if ((sorted = malloc (len)) == NULL)
{
@ -706,22 +709,35 @@ ctf_symidx_sort (ctf_dict_t *fp, uint32_t *idx, size_t *nidx,
for (i = 0; i < *nidx; i++)
sorted[i] = i;
if (!(fp->ctf_header->cth_flags & CTF_F_IDXSORTED))
/* Avoid resorting if already sorted. */
for (i = 0; i < *nidx; i++)
{
const char *str = ctf_strptr (fp, idx[i]);
if (last && strcmp (last, str) > 0)
{
needs_sort = 1;
break; /* Needs sorting. */
}
last = str;
}
if (needs_sort)
{
ctf_symidx_sort_arg_cb_t arg = { fp, idx };
ctf_dprintf ("Index section unsorted: sorting.\n");
ctf_qsort_r (sorted, *nidx, sizeof (uint32_t), sort_symidx_by_name, &arg);
fp->ctf_header->cth_flags |= CTF_F_IDXSORTED;
}
return sorted;
}
/* 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. */
/* 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; also optionally say whether it's a
function or object symbol. */
static const char *
ctf_lookup_symbol_name (ctf_dict_t *fp, unsigned long symidx)
ctf_lookup_symbol_info (ctf_dict_t *fp, unsigned long symidx)
{
const ctf_sect_t *sp = &fp->ctf_ext_symtab;
ctf_link_sym_t sym;
@ -745,7 +761,7 @@ ctf_lookup_symbol_name (ctf_dict_t *fp, unsigned long symidx)
if (sp->cts_data == NULL)
goto try_parent;
if (symidx >= fp->ctf_nsyms)
if (symidx >= (sp->cts_size / sp->cts_entsize))
goto try_parent;
switch (sp->cts_entsize)
@ -775,8 +791,8 @@ ctf_lookup_symbol_name (ctf_dict_t *fp, unsigned long symidx)
if (fp->ctf_parent)
{
const char *ret;
ret = ctf_lookup_symbol_name (fp->ctf_parent, symidx);
if (ret == NULL)
ret = ctf_lookup_symbol_info (fp->ctf_parent, symidx);
if (ret[0] == '\0')
ctf_set_errno (fp, ctf_errno (fp->ctf_parent));
return ret;
}
@ -787,157 +803,18 @@ 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. If is_function is >= 0, return only function or data object
symbols, respectively. */
static unsigned long
ctf_lookup_symbol_idx (ctf_dict_t *fp, const char *symname, int try_parent,
int is_function)
{
const ctf_sect_t *sp = &fp->ctf_ext_symtab;
ctf_link_sym_t sym;
void *known_idx;
ctf_error_t err;
ctf_dict_t *cache = fp;
ctf_id_t
ctf_symbol_next_static (ctf_dict_t *fp, ctf_next_t **it, const char **name);
if (fp->ctf_dynsyms)
{
err = EINVAL;
ctf_link_sym_t *symp;
if (((symp = ctf_dynhash_lookup (fp->ctf_dynsyms, symname)) == NULL)
|| (symp->st_type != STT_OBJECT && is_function == 0)
|| (symp->st_type != STT_FUNC && is_function == 1))
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 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_func)
if ((cache->ctf_symhash_func = ctf_dynhash_create (ctf_hash_string,
ctf_hash_eq_string,
NULL, NULL)) == NULL)
goto oom;
if (!cache->ctf_symhash_objt)
if ((cache->ctf_symhash_objt = ctf_dynhash_create (ctf_hash_string,
ctf_hash_eq_string,
NULL, NULL)) == NULL)
goto oom;
if (is_function != 0 &&
ctf_dynhash_lookup_kv (cache->ctf_symhash_func, symname, NULL, &known_idx))
return (unsigned long) (uintptr_t) known_idx;
if (is_function != 1 &&
ctf_dynhash_lookup_kv (cache->ctf_symhash_objt, 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++)
{
ctf_dynhash_t *h;
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);
}
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);
break;
}
default:
ctf_set_errno (fp, ECTF_SYMTAB);
return (unsigned long) -1;
}
if (sym.st_type == STT_FUNC)
h = cache->ctf_symhash_func;
else if (sym.st_type == STT_OBJECT)
h = cache->ctf_symhash_objt;
else
continue; /* Not of interest. */
if (!ctf_dynhash_lookup_kv (h, sym.st_name,
NULL, NULL))
if (ctf_dynhash_cinsert (h, 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++;
}
/* Searched everything, still not found. */
return (unsigned long) -1;
try_parent:
if (fp->ctf_parent && try_parent)
{
unsigned long psym;
if ((psym = ctf_lookup_symbol_idx (fp->ctf_parent, symname, try_parent,
is_function))
!= (unsigned long) -1)
return psym;
ctf_set_errno (fp, ctf_errno (fp->ctf_parent));
return (unsigned long) -1;
}
else
{
ctf_set_errno (fp, err);
return (unsigned long) -1;
}
oom:
ctf_err (err_locus (fp), ENOMEM, _("allocating symbol lookup hashtab"));
return (unsigned long) -1;
}
/* Iterate over all symbols with types. The name argument is not optional.
The return order is arbitrary, though is likely to be in symbol index or
name order. Changing the value of 'functions' in the middle of iteration
has unpredictable effects (probably skipping symbols, etc) and is not
recommended. Adding symbols while iteration is underway may also lead to
other symbols being skipped. */
ctf_id_t
ctf_symbol_next_static (ctf_dict_t *fp, ctf_next_t **it, const char **name,
ctf_funcobjt_t functions);
/* 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.
Changing the value of 'functions' in the middle of iteration has
unpredictable effects (probably skipping symbols, etc) and is not
recommended. Adding symbols while iteration is underway may also lead
to other symbols being skipped. */
ctf_id_t
ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name,
ctf_funcobjt_t functions)
ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name)
{
ctf_id_t sym = CTF_ERR;
ctf_next_t *i = *it;
@ -976,13 +853,12 @@ ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name,
finally because it's easier to work out what the name of each symbol is if
we do that. */
ctf_dynhash_t *dynh = functions ? fp->ctf_funchash : fp->ctf_objthash;
void *dyn_name = NULL, *dyn_value = NULL;
size_t dyn_els = dynh ? ctf_dynhash_elements (dynh) : 0;
if (i->ctn_n < dyn_els)
if (i->ctn_n < ctf_dynhash_elements (fp->ctf_symtypehash))
{
err = ctf_dynhash_next (dynh, &i->ctn_next, &dyn_name, &dyn_value);
err = ctf_dynhash_next (fp->ctf_symtypehash, &i->ctn_next,
&dyn_name, &dyn_value);
/* This covers errors and also end-of-iteration. */
if (err != 0)
@ -995,7 +871,7 @@ ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name,
return sym;
}
return ctf_symbol_next_static (fp, it, name, functions);
return ctf_symbol_next_static (fp, it, name);
end:
ctf_next_destroy (i);
@ -1007,15 +883,22 @@ ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name,
implementation detail of ctf_symbol_next, but also used to simplify
serialization. */
ctf_id_t
ctf_symbol_next_static (ctf_dict_t *fp, ctf_next_t **it, const char **name,
ctf_funcobjt_t functions)
ctf_symbol_next_static (ctf_dict_t *fp, ctf_next_t **it, const char **name)
{
ctf_id_t sym = CTF_ERR;
ctf_next_t *i = *it;
ctf_dynhash_t *dynh = functions ? fp->ctf_funchash : fp->ctf_objthash;
size_t dyn_els = dynh ? ctf_dynhash_elements (dynh) : 0;
size_t dyn_els = 0;
ctf_error_t err;
uint32_t *tab = (uint32_t *) (fp->ctf_buf + fp->ctf_header->cth_func_off);
size_t len = fp->ctf_header->cth_funcidx_len / sizeof (uint32_t);
if (!fp->ctf_symtypeidx_names)
return (ctf_set_typed_errno (fp, ECTF_NEXT_END));
if (fp->ctf_symtypehash)
dyn_els = ctf_dynhash_elements (fp->ctf_symtypehash);
/* Only relevant for direct internal-to-library calls, not via
ctf_symbol_next (but important then). */
@ -1042,81 +925,22 @@ ctf_symbol_next_static (ctf_dict_t *fp, ctf_next_t **it, const char **name,
goto end;
}
/* TODO: Indexed after non-indexed portions? */
if ((!functions && fp->ctf_objtidx_names) ||
(functions && fp->ctf_funcidx_names))
do
{
ctf_header_t *hp = fp->ctf_header;
uint32_t *idx = functions ? fp->ctf_funcidx_names : fp->ctf_objtidx_names;
uint32_t *tab;
size_t len;
if (functions)
{
len = hp->cth_funcidx_len / sizeof (uint32_t);
tab = (uint32_t *) (fp->ctf_buf + hp->cth_func_off);
}
else
{
len = hp->cth_objtidx_len / sizeof (uint32_t);
tab = (uint32_t *) (fp->ctf_buf + hp->cth_objt_off);
}
do
{
if (i->ctn_n - dyn_els >= len)
{
err = ECTF_NEXT_END;
goto end;
}
*name = ctf_strptr (fp, idx[i->ctn_n - dyn_els]);
sym = tab[i->ctn_n - dyn_els];
i->ctn_n++;
}
while (sym == -1u || sym == 0);
}
else
{
/* Skip over pads in ctf_sxlate, padding for typeless symbols in the
symtypetab itself, and symbols in the wrong table. */
for (; i->ctn_n - dyn_els < fp->ctf_nsyms; i->ctn_n++)
{
ctf_header_t *hp = fp->ctf_header;
size_t n = i->ctn_n - dyn_els;
if (fp->ctf_sxlate[n] == -1u)
continue;
sym = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[n]);
if (sym == 0)
continue;
if (functions)
{
if (fp->ctf_sxlate[n] >= hp->cth_func_off
&& fp->ctf_sxlate[n] < hp->cth_func_off + hp->cth_func_len)
break;
}
else
{
if (fp->ctf_sxlate[n] >= hp->cth_objt_off
&& fp->ctf_sxlate[n] < hp->cth_objt_off + hp->cth_objt_len)
break;
}
}
if (i->ctn_n - dyn_els >= fp->ctf_nsyms)
if (i->ctn_n - dyn_els >= len)
{
err = ECTF_NEXT_END;
goto end;
}
*name = ctf_lookup_symbol_name (fp, i->ctn_n - dyn_els);
*name = ctf_lookup_symbol_info (fp, i->ctn_n);
if (*name[0] == 0)
continue;
sym = tab[i->ctn_n - dyn_els];
i->ctn_n++;
}
while (sym == -1u || sym == 0);
return sym;
@ -1126,7 +950,7 @@ ctf_symbol_next_static (ctf_dict_t *fp, ctf_next_t **it, const char **name,
return (ctf_set_typed_errno (fp, err));
}
/* A bsearch function for function and object index names. */
/* A bsearch function for symtypetab symbol names. */
static int
ctf_lookup_idx_name (const void *key_, const void *idx_)
@ -1142,17 +966,13 @@ ctf_lookup_idx_name (const void *key_, const void *idx_)
there (or pad). */
static ctf_id_t
ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx,
const char *symname, ctf_funcobjt_t functions)
ctf_try_sym_lookup (ctf_dict_t *fp, unsigned long symidx, const char *symname)
{
struct ctf_header *hp = fp->ctf_header;
uint32_t *symtypetab;
uint32_t *names;
uint32_t *sxlate;
size_t nidx;
uint32_t *symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_func_off);
if (symname == NULL)
symname = ctf_lookup_symbol_name (fp, symidx);
symname = ctf_lookup_symbol_info (fp, symidx);
/* Dynamic dict with no static portion: just return. */
if (!hp)
@ -1167,50 +987,24 @@ ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx,
if (symname[0] == '\0')
return CTF_ERR; /* errno is set for us. */
if (functions)
if (!fp->ctf_symtypeidx_sxlate)
{
if (!fp->ctf_funcidx_sxlate)
if ((fp->ctf_symtypeidx_sxlate
= ctf_symidx_sort (fp, (uint32_t *)
(fp->ctf_buf + hp->cth_funcidx_off),
&fp->ctf_nsymtypeidx, hp->cth_funcidx_len))
== NULL)
{
if ((fp->ctf_funcidx_sxlate
= ctf_symidx_sort (fp, (uint32_t *)
(fp->ctf_buf + hp->cth_funcidx_off),
&fp->ctf_nfuncidx, hp->cth_funcidx_len))
== NULL)
{
ctf_err (err_locus (fp), 0, _("cannot sort function symidx"));
return CTF_ERR; /* errno is set for us. */
}
ctf_err (err_locus (fp), 0, _("cannot sort symtypetab"));
return CTF_ERR; /* errno is set for us. */
}
symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_func_off);
sxlate = fp->ctf_funcidx_sxlate;
names = fp->ctf_funcidx_names;
nidx = fp->ctf_nfuncidx;
}
else
{
if (!fp->ctf_objtidx_sxlate)
{
if ((fp->ctf_objtidx_sxlate
= ctf_symidx_sort (fp, (uint32_t *)
(fp->ctf_buf + hp->cth_objtidx_off),
&fp->ctf_nobjtidx, hp->cth_objtidx_len))
== NULL)
{
ctf_err (err_locus (fp), 0, _("cannot sort object symidx"));
return CTF_ERR; /* errno is set for us. */
}
}
symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_objt_off);
sxlate = fp->ctf_objtidx_sxlate;
names = fp->ctf_objtidx_names;
nidx = fp->ctf_nobjtidx;
}
ctf_lookup_idx_key_t key = { fp, symname, names };
ctf_lookup_idx_key_t key = { fp, symname, fp->ctf_symtypeidx_names };
uint32_t *idx;
idx = bsearch (&key, sxlate, nidx, sizeof (uint32_t), ctf_lookup_idx_name);
idx = bsearch (&key, fp->ctf_symtypeidx_sxlate, fp->ctf_nsymtypeidx,
sizeof (uint32_t), ctf_lookup_idx_name);
if (!idx)
{
@ -1219,7 +1013,7 @@ ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx,
}
/* Should be impossible, but be paranoid. */
if ((idx - sxlate) > (ptrdiff_t) nidx)
if ((idx - fp->ctf_symtypeidx_sxlate) > (ptrdiff_t) fp->ctf_nsymtypeidx)
return (ctf_set_typed_errno (fp, ECTF_CORRUPT));
ctf_dprintf ("Symbol %lx (%s) is of type %x\n", symidx, symname,
@ -1233,15 +1027,11 @@ ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx,
ctf_link_shuffle_syms has been called to assign symbol indexes to symbol
names.
If try_parent is false, do not check the parent dict too.
If is_function is > -1, only look for data objects or functions in
particular. */
If try_parent is false, do not check the parent dict too. */
ctf_id_t
ctf_lookup_by_sym_or_name (ctf_dict_t *fp, unsigned long symidx,
const char *symname, int try_parent,
int is_function)
const char *symname, int try_parent)
{
const ctf_sect_t *sp = &fp->ctf_ext_symtab;
ctf_id_t type = 0;
@ -1272,9 +1062,7 @@ ctf_lookup_by_sym_or_name (ctf_dict_t *fp, unsigned long symidx,
sym = fp->ctf_dynsymidx[symidx];
err = ECTF_NOTYPEDAT;
if (!sym || (sym->st_type != STT_OBJECT && sym->st_type != STT_FUNC)
|| (sym->st_type != STT_OBJECT && is_function == 0)
|| (sym->st_type != STT_FUNC && is_function == 1))
if (!sym || (sym->st_type != STT_OBJECT && sym->st_type != STT_FUNC))
goto try_parent;
if (!ctf_assert (fp, !sym->st_nameidx_set))
@ -1282,89 +1070,41 @@ ctf_lookup_by_sym_or_name (ctf_dict_t *fp, unsigned long symidx,
symname = sym->st_name;
}
if (fp->ctf_objthash == NULL
|| is_function == 1
if (fp->ctf_symtypehash == NULL
|| (type = (ctf_id_t) (uintptr_t)
ctf_dynhash_lookup (fp->ctf_objthash, symname)) == 0)
{
if (fp->ctf_funchash == NULL
|| is_function == 0
|| (type = (ctf_id_t) (uintptr_t)
ctf_dynhash_lookup (fp->ctf_funchash, symname)) == 0)
goto try_parent;
}
ctf_dynhash_lookup (fp->ctf_symtypehash, symname)) == 0)
goto try_parent;
return type;
}
/* Dict not shuffled: look for a dynamic sym first, and look it up
directly. */
if (symname)
{
if (fp->ctf_objthash != NULL
&& is_function != 1
&& ((type = (ctf_id_t) (uintptr_t)
ctf_dynhash_lookup (fp->ctf_objthash, symname)) != 0))
return type;
if (fp->ctf_funchash != NULL
&& is_function != 0
&& ((type = (ctf_id_t) (uintptr_t)
ctf_dynhash_lookup (fp->ctf_funchash, symname)) != 0))
return type;
}
/* Dict not shuffled: look for a dynamic sym. */
if (symname && fp->ctf_symtypehash != NULL
&& ((type = (ctf_id_t) (uintptr_t)
ctf_dynhash_lookup (fp->ctf_symtypehash, symname)) != 0))
return type;
err = ECTF_NOSYMTAB;
if (sp->cts_data == NULL && symname == NULL &&
((is_function && !fp->ctf_funcidx_names) ||
(!is_function && !fp->ctf_objtidx_names)))
!fp->ctf_symtypeidx_names)
goto try_parent;
/* This covers both out-of-range lookups by index and a dynamic dict which
hasn't been shuffled yet. */
err = EINVAL;
if (symname == NULL && symidx >= fp->ctf_nsyms)
if (symname == NULL)
goto try_parent;
/* Try an indexed lookup. We can only do indexed lookups if we have a string
table. */
if (fp->ctf_objtidx_names && is_function != 1)
{
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 && is_function != 0)
{
if ((type = ctf_try_lookup_indexed (fp, symidx, symname, 1)) == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
}
if ((type = ctf_try_sym_lookup (fp, symidx, symname)) == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
if (type != 0)
return type;
/* Indexed but no symbol found -> not present, try the parent. */
/* No symbol found? Not present, try the parent. */
err = ECTF_NOTYPEDAT;
if (fp->ctf_objtidx_names && fp->ctf_funcidx_names)
goto try_parent;
/* Table must be nonindexed. */
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, try_parent, is_function))
== (unsigned long) -1)
goto try_parent;
if (fp->ctf_sxlate[symidx] == -1u)
goto try_parent;
type = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]);
if (type == 0)
goto try_parent;
return type;
try_parent:
if (!try_parent)
@ -1373,8 +1113,7 @@ ctf_lookup_by_sym_or_name (ctf_dict_t *fp, unsigned long symidx,
if (fp->ctf_parent)
{
ctf_id_t ret = ctf_lookup_by_sym_or_name (fp->ctf_parent, symidx,
symname, try_parent,
is_function);
symname, try_parent);
if (ret == CTF_ERR)
ctf_set_errno (fp, ctf_errno (fp->ctf_parent));
return ret;
@ -1388,7 +1127,7 @@ ctf_lookup_by_sym_or_name (ctf_dict_t *fp, unsigned long symidx,
ctf_id_t
ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx)
{
return ctf_lookup_by_sym_or_name (fp, symidx, NULL, 1, -1);
return ctf_lookup_by_sym_or_name (fp, symidx, NULL, 1);
}
/* Given a symbol name, return the type of the function or data object described
@ -1396,5 +1135,5 @@ ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx)
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, 1, -1);
return ctf_lookup_by_sym_or_name (fp, 0, symname, 1);
}

View file

@ -536,3 +536,122 @@ flip_vars_v3 (void *start, size_t len)
}
}
/* Initialize the symtab translation table as appropriate for its indexing
state. For unindexed symtypetabs, fill each entry with the offset of the CTF
type or function data corresponding to each STT_FUNC or STT_OBJECT entry in
the symbol table. For indexed symtypetabs, do nothing: the needed
initialization for indexed lookups may be quite expensive, so it is done only
as needed, when lookups happen. (In particular, the majority of indexed
symtypetabs come from the compiler, and all the linker does is iteration over
all entries, which doesn't need this initialization.)
The SP symbol table section may be NULL if there is no symtab.
If init_symtab works on one call, it cannot fail on future calls to the same
fp: ctf_symsect_endianness relies on this. */
ctf_error_t
upgrade_symtab_v3 (ctf_dict_t *fp, const ctf_header_t *hp, const ctf_sect_t *sp)
{
const unsigned char *symp;
int skip_func_info = 0;
int i;
uint32_t *xp = fp->ctf_sxlate;
uint32_t *xend = PTR_ADD (xp, fp->ctf_nsyms);
uint32_t objtoff = hp->cth_objt_off;
uint32_t funcoff = hp->cth_func_off;
/* If this is a v3 dict, and the CTF_F_NEWFUNCINFO flag is not set, pretend
the func info section is empty: this compiler is too old to emit a function
info section we understand. */
if (fp->ctf_v3_header && !(fp->ctf_v3_header->cth_flags & CTF_F_NEWFUNCINFO))
skip_func_info = 1;
if (hp->cth_symidx_len > 0)
fp->ctf_symidx_names = (uint32_t *) (fp->ctf_buf + hp->cth_funcidx_off);
if (hp->cth_funcidx_len > 0 && !skip_func_info)
fp->ctf_funcidx_names = (uint32_t *) (fp->ctf_buf + hp->cth_funcidx_off);
/* Don't bother doing the rest if everything is indexed, or if we don't have a
symbol table: we will never use it. */
if ((fp->ctf_objtidx_names && fp->ctf_funcidx_names) || !sp || !sp->cts_data)
return 0;
/* The CTF data object and function type sections are ordered to match the
relative order of the respective symbol types in the symtab, unless there
is an index section, in which case the order is arbitrary and the index
gives the mapping. If no type information is available for a symbol table
entry, a pad is inserted in the CTF section. As a further optimization,
anonymous or undefined symbols are omitted from the CTF data. If an
index is available for function symbols but not object symbols, or vice
versa, we populate the xslate table for the unindexed symbols only. */
for (i = 0, symp = sp->cts_data; xp < xend; xp++, symp += sp->cts_entsize,
i++)
{
ctf_link_sym_t sym;
switch (sp->cts_entsize)
{
case sizeof (Elf64_Sym):
{
const Elf64_Sym *symp64 = (Elf64_Sym *) (uintptr_t) symp;
ctf_elf64_to_link_sym (fp, &sym, symp64, i);
}
break;
case sizeof (Elf32_Sym):
{
const Elf32_Sym *symp32 = (Elf32_Sym *) (uintptr_t) symp;
ctf_elf32_to_link_sym (fp, &sym, symp32, i);
}
break;
default:
return ECTF_SYMTAB;
}
/* This call may be led astray if our idea of the symtab's endianness is
wrong, but when this is fixed by a call to ctf_symsect_endianness,
init_symtab will be called again with the right endianness in
force. */
if (ctf_symtab_skippable (&sym))
{
*xp = -1u;
continue;
}
switch (sym.st_type)
{
case STT_OBJECT:
if (fp->ctf_objtidx_names || (objtoff - hp->cth_objt_off) >= hp->cth_objt_len)
{
*xp = -1u;
break;
}
*xp = objtoff;
objtoff += sizeof (uint32_t);
break;
case STT_FUNC:
if (fp->ctf_funcidx_names || (funcoff - hp->cth_func_off) >= hp->cth_func_len
|| skip_func_info)
{
*xp = -1u;
break;
}
*xp = funcoff;
funcoff += sizeof (uint32_t);
break;
default:
*xp = -1u;
break;
}
}
ctf_dprintf ("loaded %lu symtab entries\n", fp->ctf_nsyms);
return 0;
}

View file

@ -458,126 +458,6 @@ static const ctf_dictops_t ctf_dictops[] = {
get_prefixed_vlen_v4, get_ctt_size_v4, get_vbytes_v4},
};
/* Initialize the symtab translation table as appropriate for its indexing
state. For unindexed symtypetabs, fill each entry with the offset of the CTF
type or function data corresponding to each STT_FUNC or STT_OBJECT entry in
the symbol table. For indexed symtypetabs, do nothing: the needed
initialization for indexed lookups may be quite expensive, so it is done only
as needed, when lookups happen. (In particular, the majority of indexed
symtypetabs come from the compiler, and all the linker does is iteration over
all entries, which doesn't need this initialization.)
The SP symbol table section may be NULL if there is no symtab.
If init_symtab works on one call, it cannot fail on future calls to the same
fp: ctf_symsect_endianness relies on this. */
static ctf_error_t
init_symtab (ctf_dict_t *fp, const ctf_header_t *hp, const ctf_sect_t *sp)
{
const unsigned char *symp;
int skip_func_info = 0;
int i;
uint32_t *xp = fp->ctf_sxlate;
uint32_t *xend = PTR_ADD (xp, fp->ctf_nsyms);
uint32_t objtoff = hp->cth_objt_off;
uint32_t funcoff = hp->cth_func_off;
/* If this is a v3 dict, and the CTF_F_NEWFUNCINFO flag is not set, pretend
the func info section is empty: this compiler is too old to emit a function
info section we understand. */
if (fp->ctf_v3_header && !(fp->ctf_v3_header->cth_flags & CTF_F_NEWFUNCINFO))
skip_func_info = 1;
if (hp->cth_objtidx_len > 0)
fp->ctf_objtidx_names = (uint32_t *) (fp->ctf_buf + hp->cth_objtidx_off);
if (hp->cth_funcidx_len > 0 && !skip_func_info)
fp->ctf_funcidx_names = (uint32_t *) (fp->ctf_buf + hp->cth_funcidx_off);
/* Don't bother doing the rest if everything is indexed, or if we don't have a
symbol table: we will never use it. */
if ((fp->ctf_objtidx_names && fp->ctf_funcidx_names) || !sp || !sp->cts_data)
return 0;
/* The CTF data object and function type sections are ordered to match the
relative order of the respective symbol types in the symtab, unless there
is an index section, in which case the order is arbitrary and the index
gives the mapping. If no type information is available for a symbol table
entry, a pad is inserted in the CTF section. As a further optimization,
anonymous or undefined symbols are omitted from the CTF data. If an
index is available for function symbols but not object symbols, or vice
versa, we populate the xslate table for the unindexed symbols only. */
for (i = 0, symp = sp->cts_data; xp < xend; xp++, symp += sp->cts_entsize,
i++)
{
ctf_link_sym_t sym;
switch (sp->cts_entsize)
{
case sizeof (Elf64_Sym):
{
const Elf64_Sym *symp64 = (Elf64_Sym *) (uintptr_t) symp;
ctf_elf64_to_link_sym (fp, &sym, symp64, i);
}
break;
case sizeof (Elf32_Sym):
{
const Elf32_Sym *symp32 = (Elf32_Sym *) (uintptr_t) symp;
ctf_elf32_to_link_sym (fp, &sym, symp32, i);
}
break;
default:
return ECTF_SYMTAB;
}
/* This call may be led astray if our idea of the symtab's endianness is
wrong, but when this is fixed by a call to ctf_symsect_endianness,
init_symtab will be called again with the right endianness in
force. */
if (ctf_symtab_skippable (&sym))
{
*xp = -1u;
continue;
}
switch (sym.st_type)
{
case STT_OBJECT:
if (fp->ctf_objtidx_names || (objtoff - hp->cth_objt_off) >= hp->cth_objt_len)
{
*xp = -1u;
break;
}
*xp = objtoff;
objtoff += sizeof (uint32_t);
break;
case STT_FUNC:
if (fp->ctf_funcidx_names || (funcoff - hp->cth_func_off) >= hp->cth_func_len
|| skip_func_info)
{
*xp = -1u;
break;
}
*xp = funcoff;
funcoff += sizeof (uint32_t);
break;
default:
*xp = -1u;
break;
}
}
ctf_dprintf ("loaded %lu symtab entries\n", fp->ctf_nsyms);
return 0;
}
/* Reset the CTF base pointer and derive the buf pointer from it, initializing
everything in the ctf_dict that depends on the base or buf pointers.
@ -2497,13 +2377,10 @@ ctf_bufopen_len (ctf_open_sect_t *sects, ssize_t *len, ctf_dict_t *parent,
NULL, NULL);
fp->ctf_snapshots = 1;
fp->ctf_objthash = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
free, NULL);
fp->ctf_funchash = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
free, NULL);
fp->ctf_symtypehash = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
free, NULL);
if (!fp->ctf_dthash || !fp->ctf_snapshots || !fp->ctf_objthash
|| !fp->ctf_funchash)
if (!fp->ctf_dthash || !fp->ctf_snapshots || !fp->ctf_symtypehash)
{
err = ENOMEM;
goto bad;
@ -2532,34 +2409,14 @@ ctf_bufopen_len (ctf_open_sect_t *sects, ssize_t *len, ctf_dict_t *parent,
format == IS_BTF)) != 0)
goto bad;
/* Allocate and initialize the symtab translation table, pointed to by
ctf_sxlate, and the corresponding index sections. This table may be too
large for the actual size of the object and function info sections: if so,
ctf_nsyms will be adjusted and the excess will never be used. It's
possible to do indexed symbol lookups even without a symbol table, so check
even in that case. Initially, we assume the symtab is native-endian: if it
isn't, the caller will inform us later by calling ctf_symsect_endianness. */
/* Initially, we assume the symtab is native-endian: if it isn't, the
caller will inform us later by calling ctf_symsect_endianness. */
#ifdef WORDS_BIGENDIAN
fp->ctf_symsect_little_endian = 0;
#else
fp->ctf_symsect_little_endian = 1;
#endif
if (symsect != NULL)
{
fp->ctf_nsyms = symsect->cts_size / symsect->cts_entsize;
fp->ctf_sxlate = malloc (fp->ctf_nsyms * sizeof (uint32_t));
if (fp->ctf_sxlate == NULL)
{
err = ENOMEM;
goto bad;
}
}
if ((err = init_symtab (fp, hp, symsect)) != 0)
goto bad;
ctf_set_ctl_hashes (fp);
/* Set the data model from the archive (if recorded: V1 archives only), or
@ -2701,12 +2558,8 @@ ctf_dict_close (ctf_dict_t *fp)
ctf_dynhash_destroy (fp->ctf_var_datasecs);
ctf_dynhash_destroy (fp->ctf_decl_tag_map);
ctf_dynhash_destroy (fp->ctf_symhash_func);
ctf_dynhash_destroy (fp->ctf_symhash_objt);
free (fp->ctf_funcidx_sxlate);
free (fp->ctf_objtidx_sxlate);
ctf_dynhash_destroy (fp->ctf_objthash);
ctf_dynhash_destroy (fp->ctf_funchash);
ctf_dynhash_destroy (fp->ctf_symtypehash);
free (fp->ctf_symtypeidx_sxlate);
free (fp->ctf_dynsymidx);
ctf_dynhash_destroy (fp->ctf_dynsyms);
for (did = ctf_list_next (&fp->ctf_in_flight_dynsyms); did != NULL; did = nid)
@ -2760,7 +2613,6 @@ ctf_dict_close (ctf_dict_t *fp)
}
free (fp->ctf_void_type);
free (fp->ctf_sxlate);
free (fp->ctf_txlate);
free (fp->ctf_ptrtab);
free (fp->ctf_pptrtab);
@ -2863,27 +2715,6 @@ ctf_elf_sect (const ctf_dict_t *fp, ctf_elfsect_names_t sect)
}
}
/* Set the endianness of the symbol table attached to FP. */
void
ctf_symsect_endianness (ctf_dict_t *fp, int little_endian)
{
int old_endianness = fp->ctf_symsect_little_endian;
fp->ctf_symsect_little_endian = !!little_endian;
/* Propagate to the archive iff it's a wrapper for this dict alone. */
if (fp->ctf_archive && fp->ctf_archive->ctfi_dict)
fp->ctf_archive->ctfi_symsect_little_endian = fp->ctf_symsect_little_endian;
/* If we already have a symtab translation table, we need to repopulate it if
our idea of the endianness has changed. */
if (old_endianness != fp->ctf_symsect_little_endian
&& fp->ctf_sxlate != NULL && fp->ctf_ext_symtab.cts_data != NULL)
assert (init_symtab (fp, fp->ctf_header, &fp->ctf_ext_symtab) == 0);
}
/* Return the size in bytes of a given CTF section, 0 if none, or -1 on
error. */

View file

@ -41,9 +41,7 @@
/* Symtypetab emission flags. */
#define CTF_SYMTYPETAB_EMIT_FUNCTION 0x1
#define CTF_SYMTYPETAB_EMIT_PAD 0x2
#define CTF_SYMTYPETAB_FORCE_INDEXED 0x4
#define CTF_SYMTYPETAB_NO_FILTERING 0x1
/* Properties of symtypetab emission, shared by symtypetab section
sizing and symtypetab emission itself. */
@ -63,12 +61,6 @@ typedef struct emit_symtypetab_state
/* The dict to which the linker has reported symbols. */
ctf_dict_t *symfp;
/* The maximum number of objects seen. */
size_t maxobjt;
/* The maximum number of func info entris seen. */
size_t maxfunc;
} emit_symtypetab_state_t;
/* Emit a ref to a type in this dict. As with string refs, this ref can be
@ -120,7 +112,9 @@ ctf_type_purge_refs (ctf_dict_t *fp)
}
/* Determine if a symbol is "skippable" and should never appear in the
symtypetab sections. */
symtypetab sections. We skip only symbols which cannot possibly have
types (even if the linker should somehow provide some) and are not
platform-dependent. */
int
ctf_symtab_skippable (ctf_link_sym_t *sym)
@ -129,220 +123,39 @@ ctf_symtab_skippable (ctf_link_sym_t *sym)
if (sym->st_nameidx_set)
return 0;
/* Always skip non-function, non-object symbols. */
if (sym->st_type != STT_FUNC && sym->st_type != STT_OBJECT)
return 1;
return (sym->st_name == NULL || sym->st_name[0] == 0
|| sym->st_shndx == SHN_UNDEF
|| strcmp (sym->st_name, "_START_") == 0
|| strcmp (sym->st_name, "_END_") == 0
|| strcmp (sym->st_name, "_DYNAMIC") == 0
|| strcmp (sym->st_name, "_GLOBAL_OFFSET_TABLE_") == 0
|| strcmp (sym->st_name, "_PROCEDURE_LINKAGE_TABLE_") == 0
|| strcmp (sym->st_name, "_edata") == 0
|| strcmp (sym->st_name, "_end") == 0
|| strcmp (sym->st_name, "_etext") == 0
|| (sym->st_type == STT_OBJECT && sym->st_shndx == SHN_EXTABS
&& sym->st_value == 0));
}
/* Get the number of symbols in a symbol hash, the count of symbols, the maximum
seen, the eventual size, without any padding elements, of the func/data and
(if generated) index sections, and the size of accumulated padding elements.
The linker-reported set of symbols is found in SYMFP: it may be NULL if
symbol filtering is not desired, in which case CTF_SYMTYPETAB_FORCE_INDEXED
will always be set in the flags.
Also figure out if any symbols need to be moved to the variable section, and
add them (if not already present).
This is a sizing function, called before the output buffer is
constructed. Do not add any refs in this function! */
_libctf_nonnull_ ((1,3,4,5,6,7,8))
static ctf_ret_t
symtypetab_density (ctf_dict_t *fp, ctf_dict_t *symfp, ctf_dynhash_t *symhash,
size_t *count, size_t *max, size_t *unpadsize,
size_t *padsize, size_t *idxsize, int flags)
{
ctf_next_t *i = NULL;
const void *name;
const void *ctf_sym;
ctf_dynhash_t *linker_known = NULL;
ctf_error_t err;
int beyond_max = 0;
*count = 0;
*max = 0;
*unpadsize = 0;
*idxsize = 0;
*padsize = 0;
if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED))
{
/* Make a dynhash citing only symbols reported by the linker of the
appropriate type, then traverse all potential-symbols we know the types
of, removing them from linker_known as we go. Once this is done, the
only symbols remaining in linker_known are symbols we don't know the
types of: we must emit pads for those symbols that are below the
maximum symbol we will emit (any beyond that are simply skipped).
If there are none, this symtypetab will be empty: just report that. */
if (!symfp->ctf_dynsyms)
return 0;
if ((linker_known = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
NULL, NULL)) == NULL)
return (ctf_set_errno (fp, ENOMEM));
while ((err = ctf_dynhash_cnext (symfp->ctf_dynsyms, &i,
&name, &ctf_sym)) == 0)
{
ctf_link_sym_t *sym = (ctf_link_sym_t *) ctf_sym;
if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& sym->st_type != STT_FUNC)
|| (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& sym->st_type != STT_OBJECT))
continue;
if (ctf_symtab_skippable (sym))
continue;
/* This should only be true briefly before all the names are
finalized, long before we get this far. */
if (!ctf_assert (fp, !sym->st_nameidx_set))
{
ctf_dynhash_destroy (linker_known);
ctf_next_destroy (i);
return -1; /* errno is set for us. */
}
if (ctf_dynhash_cinsert (linker_known, name, ctf_sym) < 0)
{
ctf_dynhash_destroy (linker_known);
return (ctf_set_errno (fp, ENOMEM));
}
}
if (err != ECTF_NEXT_END)
{
ctf_dynhash_destroy (linker_known);
return ctf_err (err_locus (fp), err,
_("iterating over linker-known symbols during serialization"));
}
}
while ((err = ctf_dynhash_cnext (symhash, &i, &name, NULL)) == 0)
{
ctf_link_sym_t *sym;
if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED))
{
/* Linker did not report symbol in symtab. Remove it from the
set of known data symbols and continue. */
if ((sym = ctf_dynhash_lookup (symfp->ctf_dynsyms, name)) == NULL)
{
ctf_dynhash_remove (symhash, name);
continue;
}
/* We don't remove skippable symbols from the symhash because we don't
want them to be migrated into variables. */
if (ctf_symtab_skippable (sym))
continue;
if ((flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& sym->st_type != STT_FUNC)
{
ctf_warn (type_err_locus (fp, sym->st_symidx), 0,
_("symbol %s added to CTF as a function but is of type %x. "
"The symbol type lookup tables are probably corrupted"),
sym->st_name, sym->st_type);
ctf_dynhash_remove (symhash, name);
continue;
}
else if (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& sym->st_type != STT_OBJECT)
{
ctf_warn (type_err_locus (fp, sym->st_symidx), 0,
_("symbol %s added to CTF as a data object but is of type %x. "
"The symbol type lookup tables are probably corrupted"),
sym->st_name, sym->st_type);
ctf_dynhash_remove (symhash, name);
continue;
}
ctf_dynhash_remove (linker_known, name);
if (*max < sym->st_symidx)
*max = sym->st_symidx;
}
else
(*max)++;
*unpadsize += sizeof (uint32_t);
(*count)++;
}
if (err != ECTF_NEXT_END)
{
ctf_dynhash_destroy (linker_known);
return ctf_err (err_locus (fp), err, _("iterating over CTF symtypetab during "
"serialization"));
}
if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED))
{
while ((err = ctf_dynhash_cnext (linker_known, &i, NULL, &ctf_sym)) == 0)
{
ctf_link_sym_t *sym = (ctf_link_sym_t *) ctf_sym;
if (sym->st_symidx > *max)
beyond_max++;
}
if (err != ECTF_NEXT_END)
{
ctf_dynhash_destroy (linker_known);
return ctf_err (err_locus (fp), err, _("iterating over linker-known symbols "
"during CTF serialization"));
}
}
*idxsize = *count * sizeof (uint32_t);
if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED))
*padsize = (ctf_dynhash_elements (linker_known) - beyond_max) * sizeof (uint32_t);
ctf_dynhash_destroy (linker_known);
return 0;
}
/* Emit an objt or func symtypetab into DP in a particular order defined by an
array of ctf_link_sym_t or symbol names passed in. The index has NIDX
elements in it: unindexed output would terminate at symbol OUTMAX and is in
any case no larger than SIZE bytes. Some index elements are expected to be
skipped: see symtypetab_density. The linker-reported set of symbols (if any)
is found in SYMFP.
/* Emit the symtypetab into DP in a particular order defined by an array of
ctf_link_sym_t or symbol names passed in. The index has NIDX elements in
it and is SIZE bytes in length. Some index elements are expected to be
skipped: see ctf_link_shuffle_syms. The linker-reported set of symbols
(if any) is found in SYMFP.
Note down type ID refs as we go. */
static ctf_ret_t
emit_symtypetab (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp,
ctf_link_sym_t **idx, const char **nameidx, uint32_t nidx,
uint32_t outmax, int size, int flags)
int size, int flags)
{
uint32_t i;
uint32_t *dpp = dp;
ctf_dynhash_t *symhash;
ctf_dprintf ("Emitting table of size %i, outmax %u, %u symtypetab entries, "
"flags %i\n", size, outmax, nidx, flags);
ctf_dprintf ("Emitting table of size %i, %u symtypetab entries, "
"flags %i\n", size, nidx, flags);
/* Empty table? Nothing to do. */
if (size == 0)
return 0;
if (flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
symhash = fp->ctf_funchash;
else
symhash = fp->ctf_objthash;
for (i = 0; i < nidx; i++)
{
const char *sym_name;
@ -351,7 +164,7 @@ emit_symtypetab (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp,
/* If we have a linker-reported set of symbols, we may be given that set
to work from, or a set of symbol names. In both cases we want to look
at the corresponding linker-reported symbol (if any). */
if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED))
if (!(flags & CTF_SYMTYPETAB_NO_FILTERING))
{
ctf_link_sym_t *this_link_sym;
@ -364,43 +177,19 @@ emit_symtypetab (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp,
if (!this_link_sym)
continue;
/* Symbol of the wrong type, or skippable? This symbol is not in this
table. */
if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& this_link_sym->st_type != STT_FUNC)
|| (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& this_link_sym->st_type != STT_OBJECT))
continue;
/* Symbol skippable? This symbol is not in this table. */
if (ctf_symtab_skippable (this_link_sym))
continue;
sym_name = this_link_sym->st_name;
/* Linker reports symbol of a different type to the symbol we actually
added? Skip the symbol. No pad, since the symbol doesn't actually
belong in this table at all. (Warned about in
symtypetab_density.) */
if ((this_link_sym->st_type == STT_FUNC)
&& (ctf_dynhash_lookup (fp->ctf_objthash, sym_name)))
continue;
if ((this_link_sym->st_type == STT_OBJECT)
&& (ctf_dynhash_lookup (fp->ctf_funchash, sym_name)))
continue;
}
else
sym_name = nameidx[i];
/* Symbol in index but no type set? Silently skip and (optionally)
pad. (In force-indexed mode, this is also where we track symbols of
the wrong type for this round of insertion.) */
if ((type = ctf_dynhash_lookup (symhash, sym_name)) == NULL)
{
if (flags & CTF_SYMTYPETAB_EMIT_PAD)
*dpp++ = 0;
continue;
}
/* Symbol in index but no type set? Silently skip. */
if ((type = ctf_dynhash_lookup (fp->ctf_symtypehash, sym_name)) == NULL)
continue;
if (!ctf_assert (fp, (((char *) dpp) - (char *) dp) < size))
return -1; /* errno is set for us. */
@ -408,11 +197,6 @@ emit_symtypetab (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp,
*dpp = (ctf_id_t) (uintptr_t) type;
if (ctf_type_add_ref (fp, dpp++) < 0)
return -1; /* errno is set for us. */
/* When emitting unindexed output, all later symbols are pads: stop
early. */
if ((flags & CTF_SYMTYPETAB_EMIT_PAD) && idx[i]->st_symidx == outmax)
break;
}
return 0;
@ -427,7 +211,6 @@ emit_symtypetab_index (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp,
{
uint32_t i;
uint32_t *dpp = dp;
ctf_dynhash_t *symhash;
ctf_dprintf ("Emitting index of size %i, %u entries reported by linker, "
"flags %i\n", size, nidx, flags);
@ -436,21 +219,12 @@ emit_symtypetab_index (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp,
if (size == 0)
return 0;
if (flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
symhash = fp->ctf_funchash;
else
symhash = fp->ctf_objthash;
/* Indexes should always be unpadded. */
if (!ctf_assert (fp, !(flags & CTF_SYMTYPETAB_EMIT_PAD)))
return -1; /* errno is set for us. */
for (i = 0; i < nidx; i++)
{
const char *sym_name;
void *type;
if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED))
if (!(flags & CTF_SYMTYPETAB_NO_FILTERING))
{
ctf_link_sym_t *this_link_sym;
@ -460,36 +234,19 @@ emit_symtypetab_index (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp,
if (!ctf_assert (fp, this_link_sym != NULL))
return -1; /* errno is set for us. */
/* Symbol of the wrong type, or skippable? This symbol is not in this
table. */
if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& this_link_sym->st_type != STT_FUNC)
|| (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& this_link_sym->st_type != STT_OBJECT))
continue;
/* Symbol askippable? This symbol is not in this table. */
if (ctf_symtab_skippable (this_link_sym))
continue;
sym_name = this_link_sym->st_name;
/* Linker reports symbol of a different type to the symbol we actually
added? Skip the symbol. */
if ((this_link_sym->st_type == STT_FUNC)
&& (ctf_dynhash_lookup (fp->ctf_objthash, sym_name)))
continue;
if ((this_link_sym->st_type == STT_OBJECT)
&& (ctf_dynhash_lookup (fp->ctf_funchash, sym_name)))
continue;
}
else
sym_name = idx[i];
/* Symbol in index and reported by linker, but no type set? Silently skip
and (optionally) pad. (In force-indexed mode, this is also where we
track symbols of the wrong type for this round of insertion.) */
if ((type = ctf_dynhash_lookup (symhash, sym_name)) == NULL)
/* Symbol in index and reported by linker, but no type set? Silently
skip. */
if ((type = ctf_dynhash_lookup (fp->ctf_symtypehash, sym_name)) == NULL)
continue;
ctf_str_add_ref (fp, sym_name, dpp++);
@ -501,20 +258,23 @@ emit_symtypetab_index (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp,
return 0;
}
/* Figure out the sizes of the symtypetab sections, their indexed state,
etc.
/* Figure out the sizes of the symtypetab sections (and their indexes).
This is a sizing function, called before the output buffer is
constructed. Do not add any refs in this function! */
static ctf_ret_t
ctf_symtypetab_sect_sizes (ctf_dict_t *fp, emit_symtypetab_state_t *s,
ctf_header_t *hdr, size_t *objt_size,
size_t *func_size, size_t *objtidx_size,
size_t *funcidx_size)
size_t *tabsize, size_t *idxsize)
{
size_t nfuncs, nobjts;
size_t objt_unpadsize, func_unpadsize, objt_padsize, func_padsize;
size_t nsyms = 0;
ctf_next_t *i = NULL;
ctf_error_t err;
/* In case of error, we have no symtypetab. */
*tabsize = 0;
*idxsize = 0;
/* If doing a writeout as part of linking, and the link flags request it,
filter out all unreported symbols from the symtypetab sections. (If we are
@ -543,70 +303,46 @@ ctf_symtypetab_sect_sizes (ctf_dict_t *fp, emit_symtypetab_state_t *s,
s->symfp = fp;
}
/* If not filtering, keep all potential symbols in an unsorted, indexed
dict. */
/* Prevent later stages from filtering out unreported symbols if the
linker is not reporting. Also disables sorting. */
if (!s->filter_syms)
s->symflags = CTF_SYMTYPETAB_FORCE_INDEXED;
else
hdr->cth_flags |= CTF_F_IDXSORTED;
s->symflags = CTF_SYMTYPETAB_NO_FILTERING;
if (!ctf_assert (fp, (s->filter_syms && s->symfp)
|| (!s->filter_syms && !s->symfp
&& ((s->symflags & CTF_SYMTYPETAB_FORCE_INDEXED) != 0))))
return -1;
/* Work out the sizes of the object and function sections, and work out the
number of pad (unassigned) symbols in each, and the overall size of the
sections. */
if (symtypetab_density (fp, s->symfp, fp->ctf_objthash, &nobjts, &s->maxobjt,
&objt_unpadsize, &objt_padsize, objtidx_size,
s->symflags) < 0)
&& ((s->symflags & CTF_SYMTYPETAB_NO_FILTERING) != 0))))
return -1; /* errno is set for us. */
ctf_dprintf ("Object symtypetab: %i objects, max %i, unpadded size %i, "
"%i bytes of pads, index size %i\n", (int) nobjts,
(int) s->maxobjt, (int) objt_unpadsize, (int) objt_padsize,
(int) *objtidx_size);
/* Work out the size of the symtypetab section, taking reported symbols
into account. */
if (symtypetab_density (fp, s->symfp, fp->ctf_funchash, &nfuncs, &s->maxfunc,
&func_unpadsize, &func_padsize, funcidx_size,
s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0)
return -1; /* errno is set for us. */
ctf_dprintf ("Function symtypetab: %i functions, max %i, unpadded size %i, "
"%i bytes of pads, index size %i\n", (int) nfuncs,
(int) s->maxfunc, (int) func_unpadsize, (int) func_padsize,
(int) *funcidx_size);
/* It is worth indexing each section if it would save space to do so, due to
reducing the number of pads sufficiently. A pad is the same size as a
single index entry: but index sections compress relatively poorly compared
to constant pads, so it takes a lot of contiguous padding to equal one
index section entry. It would be nice to be able to *verify* whether we
would save space after compression rather than guessing, but this seems
difficult, since it would require complete reserialization. Regardless, if
the linker has not reported any symbols (e.g. if this is not a final link
but just an ld -r), we must emit things in indexed fashion just as the
compiler does. */
*objt_size = objt_unpadsize;
if (!(s->symflags & CTF_SYMTYPETAB_FORCE_INDEXED)
&& ((objt_padsize + objt_unpadsize) * CTF_INDEX_PAD_THRESHOLD
> objt_padsize))
if (!s->symfp->ctf_dynsyms)
nsyms = 0;
else if (s->symflags & CTF_SYMTYPETAB_NO_FILTERING)
nsyms = ctf_dynhash_elements (fp->ctf_symtypehash);
else /* Need to filter out unreported symbols. */
{
*objt_size += objt_padsize;
*objtidx_size = 0;
const void *name;
while ((err = ctf_dynhash_cnext (fp->ctf_symtypehash, &i, &name, NULL)) == 0)
{
/* Linker did not report this symbol. */
if (ctf_dynhash_lookup (fp->ctf_dynsyms, (const char *) name) == NULL)
continue;
nsyms++;
}
if (err != ECTF_NEXT_END)
{
return ctf_err (err_locus (fp), err, _("iterating over CTF symtypetab during "
"serialization"));
}
}
*func_size = func_unpadsize;
if (!(s->symflags & CTF_SYMTYPETAB_FORCE_INDEXED)
&& ((func_padsize + func_unpadsize) * CTF_INDEX_PAD_THRESHOLD
> func_padsize))
{
*func_size += func_padsize;
*funcidx_size = 0;
}
*tabsize = nsyms * sizeof (uint32_t);
*idxsize = *tabsize;
ctf_dprintf ("Symtypetab: %i objects, tab size %i, index size %i\n",
(int) nsyms, (int) *tabsize, (int) *idxsize);
return 0;
}
@ -615,9 +351,8 @@ ctf_symtypetab_sect_sizes (ctf_dict_t *fp, emit_symtypetab_state_t *s,
static ctf_ret_t
ctf_emit_symtypetab_sects (ctf_dict_t *fp, emit_symtypetab_state_t *s,
unsigned char **tptr, size_t objt_size,
size_t func_size, size_t objtidx_size,
size_t funcidx_size)
unsigned char **tptr, size_t symtypetab_size,
size_t symtypeidx_size)
{
unsigned char *t = *tptr;
size_t nsymtypes = 0;
@ -626,7 +361,7 @@ ctf_emit_symtypetab_sects (ctf_dict_t *fp, emit_symtypetab_state_t *s,
/* Sort the linker's symbols into name order if need be. */
if ((objtidx_size != 0) || (funcidx_size != 0))
if (symtypeidx_size != 0)
{
ctf_next_t *i = NULL;
void *symname;
@ -640,8 +375,7 @@ ctf_emit_symtypetab_sects (ctf_dict_t *fp, emit_symtypetab_state_t *s,
nsymtypes = 0;
}
else
nsymtypes = ctf_dynhash_elements (fp->ctf_objthash)
+ ctf_dynhash_elements (fp->ctf_funchash);
nsymtypes = ctf_dynhash_elements (fp->ctf_symtypehash);
if ((sym_name_order = calloc (nsymtypes, sizeof (const char *))) == NULL)
goto oom;
@ -665,18 +399,10 @@ ctf_emit_symtypetab_sects (ctf_dict_t *fp, emit_symtypetab_state_t *s,
{
ctf_hash_sort_f sort_fun = NULL;
/* Since we partition the set of symbols back into objt and func,
we can sort the two independently without harm. */
if (s->sort_syms)
sort_fun = ctf_dynhash_sort_by_name;
while ((err = ctf_dynhash_next_sorted (fp->ctf_objthash, &i, &symname,
NULL, sort_fun, NULL)) == 0)
*walk++ = (const char *) symname;
if (err != ECTF_NEXT_END)
goto symerr;
while ((err = ctf_dynhash_next_sorted (fp->ctf_funchash, &i, &symname,
while ((err = ctf_dynhash_next_sorted (fp->ctf_symtypehash, &i, &symname,
NULL, sort_fun, NULL)) == 0)
*walk++ = (const char *) symname;
if (err != ECTF_NEXT_END)
@ -684,65 +410,21 @@ ctf_emit_symtypetab_sects (ctf_dict_t *fp, emit_symtypetab_state_t *s,
}
}
/* Emit the object and function sections, and if necessary their indexes.
Emission is done in symtab order if there is no index, and in index
(name) order otherwise. */
/* Emit the symtypetab section and its index. Emission is done in index
(name) order. */
if ((objtidx_size == 0) && s->symfp && s->symfp->ctf_dynsymidx)
{
ctf_dprintf ("Emitting unindexed objt symtypetab\n");
if (emit_symtypetab (fp, s->symfp, (uint32_t *) t,
s->symfp->ctf_dynsymidx, NULL,
s->symfp->ctf_dynsymmax + 1, s->maxobjt,
objt_size, s->symflags | CTF_SYMTYPETAB_EMIT_PAD) < 0)
goto err; /* errno is set for us. */
}
else
{
ctf_dprintf ("Emitting indexed objt symtypetab\n");
if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, NULL,
sym_name_order, nsymtypes, s->maxobjt,
objt_size, s->symflags) < 0)
goto err; /* errno is set for us. */
}
ctf_dprintf ("Emitting symtypetab\n");
if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, NULL, sym_name_order,
nsymtypes, symtypeidx_size, s->symflags) < 0)
goto err; /* errno is set for us. */
t += objt_size;
t += symtypetab_size;
if ((funcidx_size == 0) && s->symfp && s->symfp->ctf_dynsymidx)
{
ctf_dprintf ("Emitting unindexed func symtypetab\n");
if (emit_symtypetab (fp, s->symfp, (uint32_t *) t,
s->symfp->ctf_dynsymidx, NULL,
s->symfp->ctf_dynsymmax + 1, s->maxfunc,
func_size, s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION
| CTF_SYMTYPETAB_EMIT_PAD) < 0)
goto err; /* errno is set for us. */
}
else
{
ctf_dprintf ("Emitting indexed func symtypetab\n");
if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, NULL, sym_name_order,
nsymtypes, s->maxfunc, func_size,
s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0)
goto err; /* errno is set for us. */
}
if (emit_symtypetab_index (fp, s->symfp, (uint32_t *) t, sym_name_order,
nsymtypes, symtypeidx_size , s->symflags) < 0)
goto err;
t += func_size;
if (objtidx_size > 0)
if (emit_symtypetab_index (fp, s->symfp, (uint32_t *) t, sym_name_order,
nsymtypes, objtidx_size, s->symflags) < 0)
goto err;
t += objtidx_size;
if (funcidx_size > 0)
if (emit_symtypetab_index (fp, s->symfp, (uint32_t *) t, sym_name_order,
nsymtypes, funcidx_size,
s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0)
goto err;
t += funcidx_size;
t += symtypeidx_size;
free (sym_name_order);
*tptr = t;
@ -1417,14 +1099,13 @@ ctf_preserialize (ctf_dict_t *fp)
{
ctf_header_t hdr;
ctf_dtdef_t *dtd;
int sym_functions = 0;
size_t hdr_len;
int ctf_adjustment = 0;
int force_ctf = 0;
unsigned char *t;
size_t buf_size, type_size, objt_size, func_size;
size_t funcidx_size, objtidx_size;
size_t buf_size, type_size, symtypetab_size;
size_t symtypeidx_size;
unsigned char *buf = NULL;
emit_symtypetab_state_t symstate;
@ -1500,33 +1181,29 @@ ctf_preserialize (ctf_dict_t *fp)
can put them back in the right order during sizing. Symbols already in the
dynamic state, likely due to repeated serialization, are left
unchanged. */
do
{
ctf_next_t *it = NULL;
const char *sym_name;
ctf_id_t sym;
while ((sym = ctf_symbol_next_static (fp, &it, &sym_name,
sym_functions)) != CTF_ERR)
if ((ctf_add_funcobjt_sym_forced (fp, sym_functions, sym_name, sym)) < 0)
if (ctf_errno (fp) != ECTF_DUPLICATE)
{
ctf_next_destroy (it);
return -1; /* errno is set for us. */
}
ctf_next_t *it = NULL;
const char *sym_name;
ctf_id_t sym;
if (ctf_errno (fp) != ECTF_NEXT_END)
return -1; /* errno is set for us. */
} while (sym_functions++ < 1);
while ((sym = ctf_symbol_next_static (fp, &it, &sym_name)) != CTF_ERR)
if ((ctf_add_sym_forced (fp, sym_name, sym)) < 0)
if (ctf_errno (fp) != ECTF_DUPLICATE)
{
ctf_next_destroy (it);
return -1; /* errno is set for us. */
}
/* Figure out how big the symtypetabs are now. */
if (ctf_symtypetab_sect_sizes (fp, &symstate, &hdr, &objt_size, &func_size,
&objtidx_size, &funcidx_size) < 0)
if (ctf_errno (fp) != ECTF_NEXT_END)
return -1; /* errno is set for us. */
if (objt_size != 0 || func_size != 0 || objtidx_size != 0
|| funcidx_size != 0)
/* Figure out how big the symtypetab is now. */
if (ctf_symtypetab_sect_sizes (fp, &symstate, &symtypetab_size,
&symtypeidx_size) < 0)
return -1; /* errno is set for us. */
if (symtypetab_size != 0 || symtypeidx_size != 0)
force_ctf = 1;
if (ctf_serialize_output_format (fp, force_ctf) < 0)
@ -1566,14 +1243,14 @@ ctf_preserialize (ctf_dict_t *fp)
}
hdr.cth_objt_off = 0;
hdr.cth_objt_len = objt_size;
hdr.cth_func_off = hdr.cth_objt_off + objt_size;
hdr.cth_func_len = func_size;
hdr.cth_objtidx_off = hdr.cth_func_off + func_size;
hdr.cth_objtidx_len = objtidx_size;
hdr.cth_funcidx_off = hdr.cth_objtidx_off + objtidx_size;
hdr.cth_funcidx_len = funcidx_size;
hdr.btf.bth_type_off = hdr.cth_funcidx_off + funcidx_size + ctf_adjustment;
hdr.cth_objt_len = 0;
hdr.cth_func_off = hdr.cth_objt_off + 0;
hdr.cth_func_len = symtypetab_size;
hdr.cth_objtidx_off = hdr.cth_func_off + symtypetab_size;
hdr.cth_objtidx_len = 0;
hdr.cth_funcidx_off = hdr.cth_objtidx_off + 0;
hdr.cth_funcidx_len = symtypeidx_size;
hdr.btf.bth_type_off = hdr.cth_funcidx_off + symtypeidx_size + ctf_adjustment;
hdr.btf.bth_type_len = type_size;
hdr.btf.bth_str_off = hdr.btf.bth_type_off + type_size;
hdr.btf.bth_str_len = 0;
@ -1593,7 +1270,7 @@ ctf_preserialize (ctf_dict_t *fp)
fp->ctf_serialize.cs_buf_size = buf_size;
memcpy (buf, &hdr, hdr_len);
t = (unsigned char *) buf + hdr_len + hdr.cth_objt_off;
t = (unsigned char *) buf + hdr_len + hdr.cth_func_off;
if (!fp->ctf_serialize.cs_is_btf)
{
@ -1602,8 +1279,8 @@ ctf_preserialize (ctf_dict_t *fp)
if (fp->ctf_cu_name != NULL)
ctf_str_add_ref (fp, fp->ctf_cu_name, &hdrp->cth_cu_name);
if (ctf_emit_symtypetab_sects (fp, &symstate, &t, objt_size, func_size,
objtidx_size, funcidx_size) < 0)
if (ctf_emit_symtypetab_sects (fp, &symstate, &t, symtypetab_size,
symtypeidx_size) < 0)
goto err;
}
assert (t == (unsigned char *) buf + sizeof (ctf_btf_header_t)

View file

@ -169,7 +169,7 @@ LIBCTF_2.0 {
ctf_link_write;
ctf_link_add_linker_symbol;
ctf_add_funcobjt_sym;
ctf_add_sym;
ctf_dict_set_flag;
ctf_dict_flag;

View file

@ -66,14 +66,14 @@ try_maybe_reporting (int report)
near-inverse order by symbol name, so that we can tell whether the
(necessarily indexed) section was sorted (since the sort is always in
lexicographical sort ordef by name). */
if ((ctf_add_funcobjt_sym (fp, CTF_STT_OBJT, "data_c", base) < 0) ||
(ctf_add_funcobjt_sym (fp, CTF_STT_OBJT, "data_a", base2) < 0) ||
(ctf_add_funcobjt_sym (fp, CTF_STT_OBJT, "data_b", base3) < 0))
if ((ctf_add_sym (fp, CTF_STT_OBJT, "data_c", base) < 0) ||
(ctf_add_sym (fp, CTF_STT_OBJT, "data_a", base2) < 0) ||
(ctf_add_sym (fp, CTF_STT_OBJT, "data_b", base3) < 0))
goto create_syms_err;
if ((ctf_add_funcobjt_sym (fp, CTF_STT_FUNC, "func_c", func) < 0) ||
(ctf_add_funcobjt_sym (fp, CTF_STT_FUNC, "func_a", func2) < 0) ||
(ctf_add_funcobjt_sym (fp, CTF_STT_FUNC, "func_b", func3) < 0))
if ((ctf_add_sym (fp, CTF_STT_FUNC, "func_c", func) < 0) ||
(ctf_add_sym (fp, CTF_STT_FUNC, "func_a", func2) < 0) ||
(ctf_add_sym (fp, CTF_STT_FUNC, "func_b", func3) < 0))
goto create_syms_err;
/* Make sure we can iterate over them in a dynamic dict and that they have the