mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2026-08-27 00:26:02 -04:00
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:
parent
40324c4034
commit
d2f3633152
15 changed files with 471 additions and 1187 deletions
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue