diff options
author | Nick Alcock <nick.alcock@oracle.com> | 2019-07-13 21:31:26 +0100 |
---|---|---|
committer | Nick Alcock <nick.alcock@oracle.com> | 2019-10-03 17:04:55 +0100 |
commit | 886453cbbc86ba63d8ab1264e9684a7698243eeb (patch) | |
tree | 77880fc8d6e8c2342b6c45f8de49a4058433c89c /libctf/ctf-link.c | |
parent | 72c83edd92ef15a19ed0c033e25bb5006ee3bdd8 (diff) | |
download | binutils-886453cbbc86ba63d8ab1264e9684a7698243eeb.zip binutils-886453cbbc86ba63d8ab1264e9684a7698243eeb.tar.gz binutils-886453cbbc86ba63d8ab1264e9684a7698243eeb.tar.bz2 |
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.
Diffstat (limited to 'libctf/ctf-link.c')
-rw-r--r-- | libctf/ctf-link.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/libctf/ctf-link.c b/libctf/ctf-link.c index 8f18a49..e10edf2 100644 --- a/libctf/ctf-link.c +++ b/libctf/ctf-link.c @@ -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 |