GNU Binutils with patches for OS216
修訂 | c150ea49ac8ea95059e5ae1c516b0cef39472366 (tree) |
---|---|
時間 | 2019-09-23 22:12:54 |
作者 | Nick Alcock <nick.alcock@orac...> |
Commiter | Nick Alcock |
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
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.
@@ -1,5 +1,26 @@ | ||
1 | 1 | 2019-07-13 Nick Alcock <nick.alcock@oracle.com> |
2 | 2 | |
3 | + * ctf-impl.h (ctf_file_t): New field ctf_link_type_mapping. | |
4 | + (struct ctf_link_type_mapping_key): New. | |
5 | + (ctf_hash_type_mapping_key): Likewise. | |
6 | + (ctf_hash_eq_type_mapping_key): Likewise. | |
7 | + (ctf_add_type_mapping): Likewise. | |
8 | + (ctf_type_mapping): Likewise. | |
9 | + (ctf_dynhash_empty): Likewise. | |
10 | + * ctf-open.c (ctf_file_close): Update accordingly. | |
11 | + * ctf-create.c (ctf_update): Likewise. | |
12 | + (ctf_add_type): Populate the mapping. | |
13 | + * ctf-hash.c (ctf_hash_type_mapping_key): Hash a type mapping key. | |
14 | + (ctf_hash_eq_type_mapping_key): Check the key for equality. | |
15 | + (ctf_dynhash_insert): Fix comment typo. | |
16 | + (ctf_dynhash_empty): New. | |
17 | + * ctf-link.c (ctf_add_type_mapping): New. | |
18 | + (ctf_type_mapping): Likewise. | |
19 | + (empty_link_type_mapping): New. | |
20 | + (ctf_link_one_input_archive): Call it. | |
21 | + | |
22 | +2019-07-13 Nick Alcock <nick.alcock@oracle.com> | |
23 | + | |
3 | 24 | * ctf-link.c: New file, linking of the string and type sections. |
4 | 25 | * Makefile.am (libctf_a_SOURCES): Add it. |
5 | 26 | * Makefile.in: Regenerate. |
@@ -473,6 +473,7 @@ ctf_update (ctf_file_t *fp) | ||
473 | 473 | nfp->ctf_link_inputs = fp->ctf_link_inputs; |
474 | 474 | nfp->ctf_link_outputs = fp->ctf_link_outputs; |
475 | 475 | nfp->ctf_syn_ext_strtab = fp->ctf_syn_ext_strtab; |
476 | + nfp->ctf_link_type_mapping = fp->ctf_link_type_mapping; | |
476 | 477 | |
477 | 478 | nfp->ctf_snapshot_lu = fp->ctf_snapshots; |
478 | 479 |
@@ -485,6 +486,7 @@ ctf_update (ctf_file_t *fp) | ||
485 | 486 | fp->ctf_link_inputs = NULL; |
486 | 487 | fp->ctf_link_outputs = NULL; |
487 | 488 | fp->ctf_syn_ext_strtab = NULL; |
489 | + fp->ctf_link_type_mapping = NULL; | |
488 | 490 | |
489 | 491 | fp->ctf_dvhash = NULL; |
490 | 492 | 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) | ||
1557 | 1559 | ctf_funcinfo_t ctc; |
1558 | 1560 | |
1559 | 1561 | ctf_hash_t *hp; |
1562 | + ctf_id_t orig_src_type = src_type; | |
1560 | 1563 | |
1561 | 1564 | if (!(dst_fp->ctf_flags & LCTF_RDWR)) |
1562 | 1565 | 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) | ||
1640 | 1643 | if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0) |
1641 | 1644 | { |
1642 | 1645 | if (kind != CTF_K_SLICE) |
1643 | - return dst_type; | |
1646 | + { | |
1647 | + ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type); | |
1648 | + return dst_type; | |
1649 | + } | |
1644 | 1650 | } |
1645 | 1651 | else |
1646 | 1652 | { |
@@ -1679,7 +1685,10 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1679 | 1685 | int match; /* Do the encodings match? */ |
1680 | 1686 | |
1681 | 1687 | if (kind != CTF_K_INTEGER && kind != CTF_K_FLOAT && kind != CTF_K_SLICE) |
1682 | - return dtd->dtd_type; | |
1688 | + { | |
1689 | + ctf_add_type_mapping (src_fp, src_type, dst_fp, dtd->dtd_type); | |
1690 | + return dtd->dtd_type; | |
1691 | + } | |
1683 | 1692 | |
1684 | 1693 | sroot = (flag & CTF_ADD_ROOT); |
1685 | 1694 | 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) | ||
1698 | 1707 | if (match && sroot == droot) |
1699 | 1708 | { |
1700 | 1709 | if (kind != CTF_K_SLICE) |
1701 | - return dtd->dtd_type; | |
1710 | + { | |
1711 | + ctf_add_type_mapping (src_fp, src_type, dst_fp, dtd->dtd_type); | |
1712 | + return dtd->dtd_type; | |
1713 | + } | |
1702 | 1714 | } |
1703 | 1715 | else if (!match && sroot && droot) |
1704 | 1716 | { |
@@ -1939,6 +1951,8 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1939 | 1951 | return (ctf_set_errno (dst_fp, ECTF_CORRUPT)); |
1940 | 1952 | } |
1941 | 1953 | |
1954 | + if (dst_type != CTF_ERR) | |
1955 | + ctf_add_type_mapping (src_fp, orig_src_type, dst_fp, dst_type); | |
1942 | 1956 | return dst_type; |
1943 | 1957 | } |
1944 | 1958 |
@@ -82,6 +82,28 @@ ctf_hash_eq_string (const void *a, const void *b) | ||
82 | 82 | return !strcmp((const char *) hep_a->key, (const char *) hep_b->key); |
83 | 83 | } |
84 | 84 | |
85 | +/* Hash a type_mapping_key. */ | |
86 | +unsigned int | |
87 | +ctf_hash_type_mapping_key (const void *ptr) | |
88 | +{ | |
89 | + ctf_helem_t *hep = (ctf_helem_t *) ptr; | |
90 | + ctf_link_type_mapping_key_t *k = (ctf_link_type_mapping_key_t *) hep->key; | |
91 | + | |
92 | + return htab_hash_pointer (k->cltm_fp) + 59 * htab_hash_pointer ((void *) k->cltm_idx); | |
93 | +} | |
94 | + | |
95 | +int | |
96 | +ctf_hash_eq_type_mapping_key (const void *a, const void *b) | |
97 | +{ | |
98 | + ctf_helem_t *hep_a = (ctf_helem_t *) a; | |
99 | + ctf_helem_t *hep_b = (ctf_helem_t *) b; | |
100 | + ctf_link_type_mapping_key_t *key_a = (ctf_link_type_mapping_key_t *) hep_a->key; | |
101 | + ctf_link_type_mapping_key_t *key_b = (ctf_link_type_mapping_key_t *) hep_b->key; | |
102 | + | |
103 | + return (key_a->cltm_fp == key_b->cltm_fp) | |
104 | + && (key_a->cltm_idx == key_b->cltm_idx); | |
105 | +} | |
106 | + | |
85 | 107 | /* The dynhash, used for hashes whose size is not known at creation time. */ |
86 | 108 | |
87 | 109 | /* Free a single ctf_helem. */ |
@@ -164,7 +186,7 @@ ctf_dynhash_insert (ctf_dynhash_t *hp, void *key, void *value) | ||
164 | 186 | return errno; |
165 | 187 | |
166 | 188 | /* We need to keep the key_free and value_free around in each item because the |
167 | - del function has no visiblity into the hash as a whole, only into the | |
189 | + del function has no visibility into the hash as a whole, only into the | |
168 | 190 | individual items. */ |
169 | 191 | |
170 | 192 | slot->key_free = hp->key_free; |
@@ -180,6 +202,12 @@ ctf_dynhash_remove (ctf_dynhash_t *hp, const void *key) | ||
180 | 202 | htab_remove_elt (hp->htab, &hep); |
181 | 203 | } |
182 | 204 | |
205 | +void | |
206 | +ctf_dynhash_empty (ctf_dynhash_t *hp) | |
207 | +{ | |
208 | + htab_empty (hp->htab); | |
209 | +} | |
210 | + | |
183 | 211 | void * |
184 | 212 | ctf_dynhash_lookup (ctf_dynhash_t *hp, const void *key) |
185 | 213 | { |
@@ -204,6 +204,17 @@ typedef struct ctf_str_atom_ref | ||
204 | 204 | uint32_t *caf_ref; /* A single ref to this string. */ |
205 | 205 | } ctf_str_atom_ref_t; |
206 | 206 | |
207 | +/* The structure used as the key in a ctf_link_type_mapping, which lets the | |
208 | + linker machinery determine which type IDs on the input side of a link map to | |
209 | + which types on the output side. (The value is a ctf_id_t: another | |
210 | + index, not a type.) */ | |
211 | + | |
212 | +typedef struct ctf_link_type_mapping_key | |
213 | +{ | |
214 | + ctf_file_t *cltm_fp; | |
215 | + ctf_id_t cltm_idx; | |
216 | +} ctf_link_type_mapping_key_t; | |
217 | + | |
207 | 218 | /* The ctf_file is the structure used to represent a CTF container to library |
208 | 219 | clients, who see it only as an opaque pointer. Modifications can therefore |
209 | 220 | be made freely to this structure without regard to client versioning. The |
@@ -269,6 +280,7 @@ struct ctf_file | ||
269 | 280 | ctf_archive_t *ctf_archive; /* Archive this ctf_file_t came from. */ |
270 | 281 | ctf_dynhash_t *ctf_link_inputs; /* Inputs to this link. */ |
271 | 282 | ctf_dynhash_t *ctf_link_outputs; /* Additional outputs from this link. */ |
283 | + ctf_dynhash_t *ctf_link_type_mapping; /* Map input types to output types. */ | |
272 | 284 | char *ctf_tmp_typeslice; /* Storage for slicing up type names. */ |
273 | 285 | size_t ctf_tmp_typeslicelen; /* Size of the typeslice. */ |
274 | 286 | 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); | ||
328 | 340 | typedef unsigned int (*ctf_hash_fun) (const void *ptr); |
329 | 341 | extern unsigned int ctf_hash_integer (const void *ptr); |
330 | 342 | extern unsigned int ctf_hash_string (const void *ptr); |
343 | +extern unsigned int ctf_hash_type_mapping_key (const void *ptr); | |
331 | 344 | |
332 | 345 | typedef int (*ctf_hash_eq_fun) (const void *, const void *); |
333 | 346 | extern int ctf_hash_eq_integer (const void *, const void *); |
334 | 347 | extern int ctf_hash_eq_string (const void *, const void *); |
348 | +extern int ctf_hash_eq_type_mapping_key (const void *, const void *); | |
335 | 349 | |
336 | 350 | typedef void (*ctf_hash_free_fun) (void *); |
337 | 351 |
@@ -349,6 +363,7 @@ extern ctf_dynhash_t *ctf_dynhash_create (ctf_hash_fun, ctf_hash_eq_fun, | ||
349 | 363 | ctf_hash_free_fun, ctf_hash_free_fun); |
350 | 364 | extern int ctf_dynhash_insert (ctf_dynhash_t *, void *, void *); |
351 | 365 | extern void ctf_dynhash_remove (ctf_dynhash_t *, const void *); |
366 | +extern void ctf_dynhash_empty (ctf_dynhash_t *); | |
352 | 367 | extern void *ctf_dynhash_lookup (ctf_dynhash_t *, const void *); |
353 | 368 | extern void ctf_dynhash_destroy (ctf_dynhash_t *); |
354 | 369 | 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 *); | ||
371 | 386 | extern void ctf_dvd_delete (ctf_file_t *, ctf_dvdef_t *); |
372 | 387 | extern ctf_dvdef_t *ctf_dvd_lookup (const ctf_file_t *, const char *); |
373 | 388 | |
389 | +extern void ctf_add_type_mapping (ctf_file_t *src_fp, ctf_id_t src_type, | |
390 | + ctf_file_t *dst_fp, ctf_id_t dst_type); | |
391 | +extern ctf_id_t ctf_type_mapping (ctf_file_t *src_fp, ctf_id_t src_type, | |
392 | + ctf_file_t **dst_fp); | |
393 | + | |
374 | 394 | extern void ctf_decl_init (ctf_decl_t *); |
375 | 395 | extern void ctf_decl_fini (ctf_decl_t *); |
376 | 396 | extern void ctf_decl_push (ctf_decl_t *, ctf_file_t *, ctf_id_t); |
@@ -21,6 +21,103 @@ | ||
21 | 21 | #include <string.h> |
22 | 22 | |
23 | 23 | /* Type tracking machinery. */ |
24 | + | |
25 | +/* Record the correspondence between a source and ctf_add_type()-added | |
26 | + destination type: both types are translated into parent type IDs if need be, | |
27 | + so they relate to the actual container they are in. Outside controlled | |
28 | + circumstances (like linking) it is probably not useful to do more than | |
29 | + compare these pointers, since there is nothing stopping the user closing the | |
30 | + source container whenever they want to. | |
31 | + | |
32 | + Our OOM handling here is just to not do anything, because this is called deep | |
33 | + enough in the call stack that doing anything useful is painfully difficult: | |
34 | + the worst consequence if we do OOM is a bit of type duplication anyway. */ | |
35 | + | |
36 | +void | |
37 | +ctf_add_type_mapping (ctf_file_t *src_fp, ctf_id_t src_type, | |
38 | + ctf_file_t *dst_fp, ctf_id_t dst_type) | |
39 | +{ | |
40 | + if (LCTF_TYPE_ISPARENT (src_fp, src_type) && src_fp->ctf_parent) | |
41 | + src_fp = src_fp->ctf_parent; | |
42 | + | |
43 | + src_type = LCTF_TYPE_TO_INDEX(src_fp, src_type); | |
44 | + | |
45 | + if (LCTF_TYPE_ISPARENT (dst_fp, dst_type) && dst_fp->ctf_parent) | |
46 | + dst_fp = dst_fp->ctf_parent; | |
47 | + | |
48 | + dst_type = LCTF_TYPE_TO_INDEX(dst_fp, dst_type); | |
49 | + | |
50 | + /* This dynhash is a bit tricky: it has a multivalued (structural) key, so we | |
51 | + need to use the sized-hash machinery to generate key hashing and equality | |
52 | + functions. */ | |
53 | + | |
54 | + if (dst_fp->ctf_link_type_mapping == NULL) | |
55 | + { | |
56 | + ctf_hash_fun f = ctf_hash_type_mapping_key; | |
57 | + ctf_hash_eq_fun e = ctf_hash_eq_type_mapping_key; | |
58 | + | |
59 | + if ((dst_fp->ctf_link_type_mapping = ctf_dynhash_create (f, e, free, | |
60 | + NULL)) == NULL) | |
61 | + return; | |
62 | + } | |
63 | + | |
64 | + ctf_link_type_mapping_key_t *key; | |
65 | + key = calloc (1, sizeof (struct ctf_link_type_mapping_key)); | |
66 | + if (!key) | |
67 | + return; | |
68 | + | |
69 | + key->cltm_fp = src_fp; | |
70 | + key->cltm_idx = src_type; | |
71 | + | |
72 | + ctf_dynhash_insert (dst_fp->ctf_link_type_mapping, key, | |
73 | + (void *) (uintptr_t) dst_type); | |
74 | +} | |
75 | + | |
76 | +/* Look up a type mapping: return 0 if none. The DST_FP is modified to point to | |
77 | + the parent if need be. The ID returned is from the dst_fp's perspective. */ | |
78 | +ctf_id_t | |
79 | +ctf_type_mapping (ctf_file_t *src_fp, ctf_id_t src_type, ctf_file_t **dst_fp) | |
80 | +{ | |
81 | + ctf_link_type_mapping_key_t key; | |
82 | + ctf_file_t *target_fp = *dst_fp; | |
83 | + ctf_id_t dst_type = 0; | |
84 | + | |
85 | + if (LCTF_TYPE_ISPARENT (src_fp, src_type) && src_fp->ctf_parent) | |
86 | + src_fp = src_fp->ctf_parent; | |
87 | + | |
88 | + src_type = LCTF_TYPE_TO_INDEX(src_fp, src_type); | |
89 | + key.cltm_fp = src_fp; | |
90 | + key.cltm_idx = src_type; | |
91 | + | |
92 | + if (target_fp->ctf_link_type_mapping) | |
93 | + dst_type = (uintptr_t) ctf_dynhash_lookup (target_fp->ctf_link_type_mapping, | |
94 | + &key); | |
95 | + | |
96 | + if (dst_type != 0) | |
97 | + { | |
98 | + dst_type = LCTF_INDEX_TO_TYPE (target_fp, dst_type, | |
99 | + target_fp->ctf_parent != NULL); | |
100 | + *dst_fp = target_fp; | |
101 | + return dst_type; | |
102 | + } | |
103 | + | |
104 | + if (target_fp->ctf_parent) | |
105 | + target_fp = target_fp->ctf_parent; | |
106 | + else | |
107 | + return 0; | |
108 | + | |
109 | + if (target_fp->ctf_link_type_mapping) | |
110 | + dst_type = (uintptr_t) ctf_dynhash_lookup (target_fp->ctf_link_type_mapping, | |
111 | + &key); | |
112 | + | |
113 | + if (dst_type) | |
114 | + dst_type = LCTF_INDEX_TO_TYPE (target_fp, dst_type, | |
115 | + target_fp->ctf_parent != NULL); | |
116 | + | |
117 | + *dst_fp = target_fp; | |
118 | + return dst_type; | |
119 | +} | |
120 | + | |
24 | 121 | /* Linker machinery. |
25 | 122 | |
26 | 123 | CTF linking consists of adding CTF archives full of content to be merged into |
@@ -231,6 +328,17 @@ ctf_link_one_input_archive_member (ctf_file_t *in_fp, const char *name, void *ar | ||
231 | 328 | return 0; |
232 | 329 | } |
233 | 330 | |
331 | +/* Dump the unnecessary link type mapping after one input file is processed. */ | |
332 | +static void | |
333 | +empty_link_type_mapping (void *key _libctf_unused_, void *value, | |
334 | + void *arg _libctf_unused_) | |
335 | +{ | |
336 | + ctf_file_t *fp = (ctf_file_t *) value; | |
337 | + | |
338 | + if (fp->ctf_link_type_mapping) | |
339 | + ctf_dynhash_empty (fp->ctf_link_type_mapping); | |
340 | +} | |
341 | + | |
234 | 342 | /* Link one input file's types into the output file. */ |
235 | 343 | static void |
236 | 344 | ctf_link_one_input_archive (void *key, void *value, void *arg_) |
@@ -269,6 +377,11 @@ ctf_link_one_input_archive (void *key, void *value, void *arg_) | ||
269 | 377 | ctf_set_errno (arg->out_fp, 0); |
270 | 378 | } |
271 | 379 | ctf_file_close (arg->main_input_fp); |
380 | + | |
381 | + /* Discard the now-unnecessary mapping table data. */ | |
382 | + if (arg->out_fp->ctf_link_type_mapping) | |
383 | + ctf_dynhash_empty (arg->out_fp->ctf_link_type_mapping); | |
384 | + ctf_dynhash_iter (arg->out_fp->ctf_link_outputs, empty_link_type_mapping, NULL); | |
272 | 385 | } |
273 | 386 | |
274 | 387 | /* Merge types and variable sections in all files added to the link |
@@ -1628,6 +1628,7 @@ ctf_file_close (ctf_file_t *fp) | ||
1628 | 1628 | ctf_dynhash_destroy (fp->ctf_syn_ext_strtab); |
1629 | 1629 | ctf_dynhash_destroy (fp->ctf_link_inputs); |
1630 | 1630 | ctf_dynhash_destroy (fp->ctf_link_outputs); |
1631 | + ctf_dynhash_destroy (fp->ctf_link_type_mapping); | |
1631 | 1632 | |
1632 | 1633 | ctf_free (fp->ctf_sxlate); |
1633 | 1634 | ctf_free (fp->ctf_txlate); |