libctf: map from old to corresponding newly-added types in ctf_add_type
This lets you call ctf_type_mapping (dest_fp, src_fp, src_type_id) and get told what type ID the corresponding type has in the target ctf_file_t. This works even if it was added by a recursive call, and because it is stored in the target ctf_file_t it works even if we had to add one type to multiple ctf_file_t's as part of conflicting type handling. We empty out this mapping after every archive is linked: because it maps input to output fps, and we only visit each input fp once, its contents are rendered entirely useless every time the source fp changes. v3: add several missing mapping additions. Add ctf_dynhash_empty, and empty after every input archive. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t): New field ctf_link_type_mapping. (struct ctf_link_type_mapping_key): New. (ctf_hash_type_mapping_key): Likewise. (ctf_hash_eq_type_mapping_key): Likewise. (ctf_add_type_mapping): Likewise. (ctf_type_mapping): Likewise. (ctf_dynhash_empty): Likewise. * ctf-open.c (ctf_file_close): Update accordingly. * ctf-create.c (ctf_update): Likewise. (ctf_add_type): Populate the mapping. * ctf-hash.c (ctf_hash_type_mapping_key): Hash a type mapping key. (ctf_hash_eq_type_mapping_key): Check the key for equality. (ctf_dynhash_insert): Fix comment typo. (ctf_dynhash_empty): New. * ctf-link.c (ctf_add_type_mapping): New. (ctf_type_mapping): Likewise. (empty_link_type_mapping): New. (ctf_link_one_input_archive): Call it.
This commit is contained in:
parent
72c83edd92
commit
886453cbbc
@ -1,3 +1,24 @@
|
||||
2019-07-13 Nick Alcock <nick.alcock@oracle.com>
|
||||
|
||||
* ctf-impl.h (ctf_file_t): New field ctf_link_type_mapping.
|
||||
(struct ctf_link_type_mapping_key): New.
|
||||
(ctf_hash_type_mapping_key): Likewise.
|
||||
(ctf_hash_eq_type_mapping_key): Likewise.
|
||||
(ctf_add_type_mapping): Likewise.
|
||||
(ctf_type_mapping): Likewise.
|
||||
(ctf_dynhash_empty): Likewise.
|
||||
* ctf-open.c (ctf_file_close): Update accordingly.
|
||||
* ctf-create.c (ctf_update): Likewise.
|
||||
(ctf_add_type): Populate the mapping.
|
||||
* ctf-hash.c (ctf_hash_type_mapping_key): Hash a type mapping key.
|
||||
(ctf_hash_eq_type_mapping_key): Check the key for equality.
|
||||
(ctf_dynhash_insert): Fix comment typo.
|
||||
(ctf_dynhash_empty): New.
|
||||
* ctf-link.c (ctf_add_type_mapping): New.
|
||||
(ctf_type_mapping): Likewise.
|
||||
(empty_link_type_mapping): New.
|
||||
(ctf_link_one_input_archive): Call it.
|
||||
|
||||
2019-07-13 Nick Alcock <nick.alcock@oracle.com>
|
||||
|
||||
* ctf-link.c: New file, linking of the string and type sections.
|
||||
|
@ -473,6 +473,7 @@ ctf_update (ctf_file_t *fp)
|
||||
nfp->ctf_link_inputs = fp->ctf_link_inputs;
|
||||
nfp->ctf_link_outputs = fp->ctf_link_outputs;
|
||||
nfp->ctf_syn_ext_strtab = fp->ctf_syn_ext_strtab;
|
||||
nfp->ctf_link_type_mapping = fp->ctf_link_type_mapping;
|
||||
|
||||
nfp->ctf_snapshot_lu = fp->ctf_snapshots;
|
||||
|
||||
@ -485,6 +486,7 @@ ctf_update (ctf_file_t *fp)
|
||||
fp->ctf_link_inputs = NULL;
|
||||
fp->ctf_link_outputs = NULL;
|
||||
fp->ctf_syn_ext_strtab = NULL;
|
||||
fp->ctf_link_type_mapping = NULL;
|
||||
|
||||
fp->ctf_dvhash = NULL;
|
||||
memset (&fp->ctf_dvdefs, 0, sizeof (ctf_list_t));
|
||||
@ -1557,6 +1559,7 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
|
||||
ctf_funcinfo_t ctc;
|
||||
|
||||
ctf_hash_t *hp;
|
||||
ctf_id_t orig_src_type = src_type;
|
||||
|
||||
if (!(dst_fp->ctf_flags & LCTF_RDWR))
|
||||
return (ctf_set_errno (dst_fp, ECTF_RDONLY));
|
||||
@ -1640,7 +1643,10 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
|
||||
if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0)
|
||||
{
|
||||
if (kind != CTF_K_SLICE)
|
||||
return dst_type;
|
||||
{
|
||||
ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
|
||||
return dst_type;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1679,7 +1685,10 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
|
||||
int match; /* Do the encodings match? */
|
||||
|
||||
if (kind != CTF_K_INTEGER && kind != CTF_K_FLOAT && kind != CTF_K_SLICE)
|
||||
return dtd->dtd_type;
|
||||
{
|
||||
ctf_add_type_mapping (src_fp, src_type, dst_fp, dtd->dtd_type);
|
||||
return dtd->dtd_type;
|
||||
}
|
||||
|
||||
sroot = (flag & CTF_ADD_ROOT);
|
||||
droot = (LCTF_INFO_ISROOT (dst_fp,
|
||||
@ -1698,7 +1707,10 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
|
||||
if (match && sroot == droot)
|
||||
{
|
||||
if (kind != CTF_K_SLICE)
|
||||
return dtd->dtd_type;
|
||||
{
|
||||
ctf_add_type_mapping (src_fp, src_type, dst_fp, dtd->dtd_type);
|
||||
return dtd->dtd_type;
|
||||
}
|
||||
}
|
||||
else if (!match && sroot && droot)
|
||||
{
|
||||
@ -1939,6 +1951,8 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
|
||||
return (ctf_set_errno (dst_fp, ECTF_CORRUPT));
|
||||
}
|
||||
|
||||
if (dst_type != CTF_ERR)
|
||||
ctf_add_type_mapping (src_fp, orig_src_type, dst_fp, dst_type);
|
||||
return dst_type;
|
||||
}
|
||||
|
||||
|
@ -82,6 +82,28 @@ ctf_hash_eq_string (const void *a, const void *b)
|
||||
return !strcmp((const char *) hep_a->key, (const char *) hep_b->key);
|
||||
}
|
||||
|
||||
/* Hash a type_mapping_key. */
|
||||
unsigned int
|
||||
ctf_hash_type_mapping_key (const void *ptr)
|
||||
{
|
||||
ctf_helem_t *hep = (ctf_helem_t *) ptr;
|
||||
ctf_link_type_mapping_key_t *k = (ctf_link_type_mapping_key_t *) hep->key;
|
||||
|
||||
return htab_hash_pointer (k->cltm_fp) + 59 * htab_hash_pointer ((void *) k->cltm_idx);
|
||||
}
|
||||
|
||||
int
|
||||
ctf_hash_eq_type_mapping_key (const void *a, const void *b)
|
||||
{
|
||||
ctf_helem_t *hep_a = (ctf_helem_t *) a;
|
||||
ctf_helem_t *hep_b = (ctf_helem_t *) b;
|
||||
ctf_link_type_mapping_key_t *key_a = (ctf_link_type_mapping_key_t *) hep_a->key;
|
||||
ctf_link_type_mapping_key_t *key_b = (ctf_link_type_mapping_key_t *) hep_b->key;
|
||||
|
||||
return (key_a->cltm_fp == key_b->cltm_fp)
|
||||
&& (key_a->cltm_idx == key_b->cltm_idx);
|
||||
}
|
||||
|
||||
/* The dynhash, used for hashes whose size is not known at creation time. */
|
||||
|
||||
/* Free a single ctf_helem. */
|
||||
@ -164,7 +186,7 @@ ctf_dynhash_insert (ctf_dynhash_t *hp, void *key, void *value)
|
||||
return errno;
|
||||
|
||||
/* We need to keep the key_free and value_free around in each item because the
|
||||
del function has no visiblity into the hash as a whole, only into the
|
||||
del function has no visibility into the hash as a whole, only into the
|
||||
individual items. */
|
||||
|
||||
slot->key_free = hp->key_free;
|
||||
@ -180,6 +202,12 @@ ctf_dynhash_remove (ctf_dynhash_t *hp, const void *key)
|
||||
htab_remove_elt (hp->htab, &hep);
|
||||
}
|
||||
|
||||
void
|
||||
ctf_dynhash_empty (ctf_dynhash_t *hp)
|
||||
{
|
||||
htab_empty (hp->htab);
|
||||
}
|
||||
|
||||
void *
|
||||
ctf_dynhash_lookup (ctf_dynhash_t *hp, const void *key)
|
||||
{
|
||||
|
@ -204,6 +204,17 @@ typedef struct ctf_str_atom_ref
|
||||
uint32_t *caf_ref; /* A single ref to this string. */
|
||||
} ctf_str_atom_ref_t;
|
||||
|
||||
/* The structure used as the key in a ctf_link_type_mapping, which lets the
|
||||
linker machinery determine which type IDs on the input side of a link map to
|
||||
which types on the output side. (The value is a ctf_id_t: another
|
||||
index, not a type.) */
|
||||
|
||||
typedef struct ctf_link_type_mapping_key
|
||||
{
|
||||
ctf_file_t *cltm_fp;
|
||||
ctf_id_t cltm_idx;
|
||||
} ctf_link_type_mapping_key_t;
|
||||
|
||||
/* The ctf_file is the structure used to represent a CTF container to library
|
||||
clients, who see it only as an opaque pointer. Modifications can therefore
|
||||
be made freely to this structure without regard to client versioning. The
|
||||
@ -269,6 +280,7 @@ struct ctf_file
|
||||
ctf_archive_t *ctf_archive; /* Archive this ctf_file_t came from. */
|
||||
ctf_dynhash_t *ctf_link_inputs; /* Inputs to this link. */
|
||||
ctf_dynhash_t *ctf_link_outputs; /* Additional outputs from this link. */
|
||||
ctf_dynhash_t *ctf_link_type_mapping; /* Map input types to output types. */
|
||||
char *ctf_tmp_typeslice; /* Storage for slicing up type names. */
|
||||
size_t ctf_tmp_typeslicelen; /* Size of the typeslice. */
|
||||
void *ctf_specific; /* Data for ctf_get/setspecific(). */
|
||||
@ -328,10 +340,12 @@ extern const ctf_type_t *ctf_lookup_by_id (ctf_file_t **, ctf_id_t);
|
||||
typedef unsigned int (*ctf_hash_fun) (const void *ptr);
|
||||
extern unsigned int ctf_hash_integer (const void *ptr);
|
||||
extern unsigned int ctf_hash_string (const void *ptr);
|
||||
extern unsigned int ctf_hash_type_mapping_key (const void *ptr);
|
||||
|
||||
typedef int (*ctf_hash_eq_fun) (const void *, const void *);
|
||||
extern int ctf_hash_eq_integer (const void *, const void *);
|
||||
extern int ctf_hash_eq_string (const void *, const void *);
|
||||
extern int ctf_hash_eq_type_mapping_key (const void *, const void *);
|
||||
|
||||
typedef void (*ctf_hash_free_fun) (void *);
|
||||
|
||||
@ -349,6 +363,7 @@ extern ctf_dynhash_t *ctf_dynhash_create (ctf_hash_fun, ctf_hash_eq_fun,
|
||||
ctf_hash_free_fun, ctf_hash_free_fun);
|
||||
extern int ctf_dynhash_insert (ctf_dynhash_t *, void *, void *);
|
||||
extern void ctf_dynhash_remove (ctf_dynhash_t *, const void *);
|
||||
extern void ctf_dynhash_empty (ctf_dynhash_t *);
|
||||
extern void *ctf_dynhash_lookup (ctf_dynhash_t *, const void *);
|
||||
extern void ctf_dynhash_destroy (ctf_dynhash_t *);
|
||||
extern void ctf_dynhash_iter (ctf_dynhash_t *, ctf_hash_iter_f, void *);
|
||||
@ -371,6 +386,11 @@ extern int ctf_dvd_insert (ctf_file_t *, ctf_dvdef_t *);
|
||||
extern void ctf_dvd_delete (ctf_file_t *, ctf_dvdef_t *);
|
||||
extern ctf_dvdef_t *ctf_dvd_lookup (const ctf_file_t *, const char *);
|
||||
|
||||
extern void ctf_add_type_mapping (ctf_file_t *src_fp, ctf_id_t src_type,
|
||||
ctf_file_t *dst_fp, ctf_id_t dst_type);
|
||||
extern ctf_id_t ctf_type_mapping (ctf_file_t *src_fp, ctf_id_t src_type,
|
||||
ctf_file_t **dst_fp);
|
||||
|
||||
extern void ctf_decl_init (ctf_decl_t *);
|
||||
extern void ctf_decl_fini (ctf_decl_t *);
|
||||
extern void ctf_decl_push (ctf_decl_t *, ctf_file_t *, ctf_id_t);
|
||||
|
@ -20,6 +20,104 @@
|
||||
#include <ctf-impl.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Type tracking machinery. */
|
||||
|
||||
/* Record the correspondence between a source and ctf_add_type()-added
|
||||
destination type: both types are translated into parent type IDs if need be,
|
||||
so they relate to the actual container they are in. Outside controlled
|
||||
circumstances (like linking) it is probably not useful to do more than
|
||||
compare these pointers, since there is nothing stopping the user closing the
|
||||
source container whenever they want to.
|
||||
|
||||
Our OOM handling here is just to not do anything, because this is called deep
|
||||
enough in the call stack that doing anything useful is painfully difficult:
|
||||
the worst consequence if we do OOM is a bit of type duplication anyway. */
|
||||
|
||||
void
|
||||
ctf_add_type_mapping (ctf_file_t *src_fp, ctf_id_t src_type,
|
||||
ctf_file_t *dst_fp, ctf_id_t dst_type)
|
||||
{
|
||||
if (LCTF_TYPE_ISPARENT (src_fp, src_type) && src_fp->ctf_parent)
|
||||
src_fp = src_fp->ctf_parent;
|
||||
|
||||
src_type = LCTF_TYPE_TO_INDEX(src_fp, src_type);
|
||||
|
||||
if (LCTF_TYPE_ISPARENT (dst_fp, dst_type) && dst_fp->ctf_parent)
|
||||
dst_fp = dst_fp->ctf_parent;
|
||||
|
||||
dst_type = LCTF_TYPE_TO_INDEX(dst_fp, dst_type);
|
||||
|
||||
/* This dynhash is a bit tricky: it has a multivalued (structural) key, so we
|
||||
need to use the sized-hash machinery to generate key hashing and equality
|
||||
functions. */
|
||||
|
||||
if (dst_fp->ctf_link_type_mapping == NULL)
|
||||
{
|
||||
ctf_hash_fun f = ctf_hash_type_mapping_key;
|
||||
ctf_hash_eq_fun e = ctf_hash_eq_type_mapping_key;
|
||||
|
||||
if ((dst_fp->ctf_link_type_mapping = ctf_dynhash_create (f, e, free,
|
||||
NULL)) == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
ctf_link_type_mapping_key_t *key;
|
||||
key = calloc (1, sizeof (struct ctf_link_type_mapping_key));
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
key->cltm_fp = src_fp;
|
||||
key->cltm_idx = src_type;
|
||||
|
||||
ctf_dynhash_insert (dst_fp->ctf_link_type_mapping, key,
|
||||
(void *) (uintptr_t) dst_type);
|
||||
}
|
||||
|
||||
/* Look up a type mapping: return 0 if none. The DST_FP is modified to point to
|
||||
the parent if need be. The ID returned is from the dst_fp's perspective. */
|
||||
ctf_id_t
|
||||
ctf_type_mapping (ctf_file_t *src_fp, ctf_id_t src_type, ctf_file_t **dst_fp)
|
||||
{
|
||||
ctf_link_type_mapping_key_t key;
|
||||
ctf_file_t *target_fp = *dst_fp;
|
||||
ctf_id_t dst_type = 0;
|
||||
|
||||
if (LCTF_TYPE_ISPARENT (src_fp, src_type) && src_fp->ctf_parent)
|
||||
src_fp = src_fp->ctf_parent;
|
||||
|
||||
src_type = LCTF_TYPE_TO_INDEX(src_fp, src_type);
|
||||
key.cltm_fp = src_fp;
|
||||
key.cltm_idx = src_type;
|
||||
|
||||
if (target_fp->ctf_link_type_mapping)
|
||||
dst_type = (uintptr_t) ctf_dynhash_lookup (target_fp->ctf_link_type_mapping,
|
||||
&key);
|
||||
|
||||
if (dst_type != 0)
|
||||
{
|
||||
dst_type = LCTF_INDEX_TO_TYPE (target_fp, dst_type,
|
||||
target_fp->ctf_parent != NULL);
|
||||
*dst_fp = target_fp;
|
||||
return dst_type;
|
||||
}
|
||||
|
||||
if (target_fp->ctf_parent)
|
||||
target_fp = target_fp->ctf_parent;
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (target_fp->ctf_link_type_mapping)
|
||||
dst_type = (uintptr_t) ctf_dynhash_lookup (target_fp->ctf_link_type_mapping,
|
||||
&key);
|
||||
|
||||
if (dst_type)
|
||||
dst_type = LCTF_INDEX_TO_TYPE (target_fp, dst_type,
|
||||
target_fp->ctf_parent != NULL);
|
||||
|
||||
*dst_fp = target_fp;
|
||||
return dst_type;
|
||||
}
|
||||
|
||||
/* Linker machinery.
|
||||
|
||||
CTF linking consists of adding CTF archives full of content to be merged into
|
||||
@ -229,6 +327,17 @@ ctf_link_one_input_archive_member (ctf_file_t *in_fp, const char *name, void *ar
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Dump the unnecessary link type mapping after one input file is processed. */
|
||||
static void
|
||||
empty_link_type_mapping (void *key _libctf_unused_, void *value,
|
||||
void *arg _libctf_unused_)
|
||||
{
|
||||
ctf_file_t *fp = (ctf_file_t *) value;
|
||||
|
||||
if (fp->ctf_link_type_mapping)
|
||||
ctf_dynhash_empty (fp->ctf_link_type_mapping);
|
||||
}
|
||||
|
||||
/* Link one input file's types into the output file. */
|
||||
static void
|
||||
ctf_link_one_input_archive (void *key, void *value, void *arg_)
|
||||
@ -267,6 +376,11 @@ ctf_link_one_input_archive (void *key, void *value, void *arg_)
|
||||
ctf_set_errno (arg->out_fp, 0);
|
||||
}
|
||||
ctf_file_close (arg->main_input_fp);
|
||||
|
||||
/* Discard the now-unnecessary mapping table data. */
|
||||
if (arg->out_fp->ctf_link_type_mapping)
|
||||
ctf_dynhash_empty (arg->out_fp->ctf_link_type_mapping);
|
||||
ctf_dynhash_iter (arg->out_fp->ctf_link_outputs, empty_link_type_mapping, NULL);
|
||||
}
|
||||
|
||||
/* Merge types and variable sections in all files added to the link
|
||||
|
@ -1627,6 +1627,7 @@ ctf_file_close (ctf_file_t *fp)
|
||||
ctf_dynhash_destroy (fp->ctf_syn_ext_strtab);
|
||||
ctf_dynhash_destroy (fp->ctf_link_inputs);
|
||||
ctf_dynhash_destroy (fp->ctf_link_outputs);
|
||||
ctf_dynhash_destroy (fp->ctf_link_type_mapping);
|
||||
|
||||
ctf_free (fp->ctf_sxlate);
|
||||
ctf_free (fp->ctf_txlate);
|
||||
|
Loading…
Reference in New Issue
Block a user