ctf-create.c revision 1.1.1.4 1 1.1.1.2 christos /* CTF dict creation.
2 1.1.1.3 christos Copyright (C) 2019-2024 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This file is part of libctf.
5 1.1 christos
6 1.1 christos libctf is free software; you can redistribute it and/or modify it under
7 1.1 christos the terms of the GNU General Public License as published by the Free
8 1.1 christos Software Foundation; either version 3, or (at your option) any later
9 1.1 christos version.
10 1.1 christos
11 1.1 christos This program is distributed in the hope that it will be useful, but
12 1.1 christos WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 1.1 christos See the GNU General Public License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with this program; see the file COPYING. If not see
18 1.1 christos <http://www.gnu.org/licenses/>. */
19 1.1 christos
20 1.1 christos #include <ctf-impl.h>
21 1.1 christos #include <sys/param.h>
22 1.1 christos #include <string.h>
23 1.1 christos #include <unistd.h>
24 1.1 christos
25 1.1 christos #ifndef EOVERFLOW
26 1.1 christos #define EOVERFLOW ERANGE
27 1.1 christos #endif
28 1.1 christos
29 1.1 christos #ifndef roundup
30 1.1 christos #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
31 1.1 christos #endif
32 1.1 christos
33 1.1.1.2 christos /* The initial size of a dynamic type's vlen in members. Arbitrary: the bigger
34 1.1.1.2 christos this is, the less allocation needs to be done for small structure
35 1.1.1.2 christos initialization, and the more memory is wasted for small structures during CTF
36 1.1.1.2 christos construction. No effect on generated CTF or ctf_open()ed CTF. */
37 1.1.1.2 christos #define INITIAL_VLEN 16
38 1.1.1.2 christos
39 1.1 christos /* Make sure the ptrtab has enough space for at least one more type.
40 1.1 christos
41 1.1 christos We start with 4KiB of ptrtab, enough for a thousand types, then grow it 25%
42 1.1 christos at a time. */
43 1.1 christos
44 1.1 christos static int
45 1.1.1.2 christos ctf_grow_ptrtab (ctf_dict_t *fp)
46 1.1 christos {
47 1.1 christos size_t new_ptrtab_len = fp->ctf_ptrtab_len;
48 1.1 christos
49 1.1 christos /* We allocate one more ptrtab entry than we need, for the initial zero,
50 1.1.1.3 christos plus one because the caller will probably allocate a new type.
51 1.1 christos
52 1.1.1.3 christos Equally, if the ptrtab is small -- perhaps due to ctf_open of a small
53 1.1.1.3 christos dict -- boost it by quite a lot at first, so we don't need to keep
54 1.1.1.3 christos realloc()ing. */
55 1.1.1.3 christos
56 1.1.1.3 christos if (fp->ctf_ptrtab == NULL || fp->ctf_ptrtab_len < 1024)
57 1.1 christos new_ptrtab_len = 1024;
58 1.1 christos else if ((fp->ctf_typemax + 2) > fp->ctf_ptrtab_len)
59 1.1 christos new_ptrtab_len = fp->ctf_ptrtab_len * 1.25;
60 1.1 christos
61 1.1 christos if (new_ptrtab_len != fp->ctf_ptrtab_len)
62 1.1 christos {
63 1.1 christos uint32_t *new_ptrtab;
64 1.1 christos
65 1.1 christos if ((new_ptrtab = realloc (fp->ctf_ptrtab,
66 1.1 christos new_ptrtab_len * sizeof (uint32_t))) == NULL)
67 1.1 christos return (ctf_set_errno (fp, ENOMEM));
68 1.1 christos
69 1.1 christos fp->ctf_ptrtab = new_ptrtab;
70 1.1 christos memset (fp->ctf_ptrtab + fp->ctf_ptrtab_len, 0,
71 1.1 christos (new_ptrtab_len - fp->ctf_ptrtab_len) * sizeof (uint32_t));
72 1.1 christos fp->ctf_ptrtab_len = new_ptrtab_len;
73 1.1 christos }
74 1.1 christos return 0;
75 1.1 christos }
76 1.1 christos
77 1.1.1.2 christos /* Make sure a vlen has enough space: expand it otherwise. Unlike the ptrtab,
78 1.1.1.2 christos which grows quite slowly, the vlen grows in big jumps because it is quite
79 1.1.1.2 christos expensive to expand: the caller has to scan the old vlen for string refs
80 1.1.1.2 christos first and remove them, then re-add them afterwards. The initial size is
81 1.1.1.2 christos more or less arbitrary. */
82 1.1.1.2 christos static int
83 1.1.1.2 christos ctf_grow_vlen (ctf_dict_t *fp, ctf_dtdef_t *dtd, size_t vlen)
84 1.1.1.2 christos {
85 1.1.1.2 christos unsigned char *old = dtd->dtd_vlen;
86 1.1.1.2 christos
87 1.1.1.2 christos if (dtd->dtd_vlen_alloc > vlen)
88 1.1.1.2 christos return 0;
89 1.1.1.2 christos
90 1.1.1.2 christos if ((dtd->dtd_vlen = realloc (dtd->dtd_vlen,
91 1.1.1.2 christos dtd->dtd_vlen_alloc * 2)) == NULL)
92 1.1.1.2 christos {
93 1.1.1.2 christos dtd->dtd_vlen = old;
94 1.1.1.2 christos return (ctf_set_errno (fp, ENOMEM));
95 1.1.1.2 christos }
96 1.1.1.2 christos memset (dtd->dtd_vlen + dtd->dtd_vlen_alloc, 0, dtd->dtd_vlen_alloc);
97 1.1.1.2 christos dtd->dtd_vlen_alloc *= 2;
98 1.1.1.2 christos return 0;
99 1.1.1.2 christos }
100 1.1.1.2 christos
101 1.1.1.2 christos /* To create an empty CTF dict, we just declare a zeroed header and call
102 1.1.1.2 christos ctf_bufopen() on it. If ctf_bufopen succeeds, we mark the new dict r/w and
103 1.1.1.2 christos initialize the dynamic members. We start assigning type IDs at 1 because
104 1.1 christos type ID 0 is used as a sentinel and a not-found indicator. */
105 1.1 christos
106 1.1.1.2 christos ctf_dict_t *
107 1.1 christos ctf_create (int *errp)
108 1.1 christos {
109 1.1 christos static const ctf_header_t hdr = { .cth_preamble = { CTF_MAGIC, CTF_VERSION, 0 } };
110 1.1 christos
111 1.1 christos ctf_dynhash_t *structs = NULL, *unions = NULL, *enums = NULL, *names = NULL;
112 1.1 christos ctf_sect_t cts;
113 1.1.1.2 christos ctf_dict_t *fp;
114 1.1 christos
115 1.1 christos libctf_init_debug();
116 1.1 christos
117 1.1 christos structs = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
118 1.1 christos NULL, NULL);
119 1.1 christos unions = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
120 1.1 christos NULL, NULL);
121 1.1 christos enums = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
122 1.1 christos NULL, NULL);
123 1.1 christos names = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
124 1.1 christos NULL, NULL);
125 1.1 christos if (!structs || !unions || !enums || !names)
126 1.1 christos {
127 1.1 christos ctf_set_open_errno (errp, EAGAIN);
128 1.1.1.3 christos goto err;
129 1.1 christos }
130 1.1 christos
131 1.1 christos cts.cts_name = _CTF_SECTION;
132 1.1 christos cts.cts_data = &hdr;
133 1.1 christos cts.cts_size = sizeof (hdr);
134 1.1 christos cts.cts_entsize = 1;
135 1.1 christos
136 1.1.1.3 christos if ((fp = ctf_bufopen (&cts, NULL, NULL, errp)) == NULL)
137 1.1.1.3 christos goto err;
138 1.1 christos
139 1.1.1.3 christos /* These hashes will have been initialized with a starting size of zero,
140 1.1.1.3 christos which is surely wrong. Use ones with slightly larger sizes. */
141 1.1.1.3 christos ctf_dynhash_destroy (fp->ctf_structs);
142 1.1.1.3 christos ctf_dynhash_destroy (fp->ctf_unions);
143 1.1.1.3 christos ctf_dynhash_destroy (fp->ctf_enums);
144 1.1.1.3 christos ctf_dynhash_destroy (fp->ctf_names);
145 1.1.1.3 christos fp->ctf_structs = structs;
146 1.1.1.3 christos fp->ctf_unions = unions;
147 1.1.1.3 christos fp->ctf_enums = enums;
148 1.1.1.3 christos fp->ctf_names = names;
149 1.1 christos fp->ctf_dtoldid = 0;
150 1.1 christos fp->ctf_snapshot_lu = 0;
151 1.1.1.3 christos
152 1.1.1.3 christos /* Make sure the ptrtab starts out at a reasonable size. */
153 1.1 christos
154 1.1 christos ctf_set_ctl_hashes (fp);
155 1.1 christos if (ctf_grow_ptrtab (fp) < 0)
156 1.1 christos {
157 1.1 christos ctf_set_open_errno (errp, ctf_errno (fp));
158 1.1.1.2 christos ctf_dict_close (fp);
159 1.1 christos return NULL;
160 1.1 christos }
161 1.1 christos
162 1.1 christos return fp;
163 1.1 christos
164 1.1.1.3 christos err:
165 1.1 christos ctf_dynhash_destroy (structs);
166 1.1 christos ctf_dynhash_destroy (unions);
167 1.1 christos ctf_dynhash_destroy (enums);
168 1.1 christos ctf_dynhash_destroy (names);
169 1.1 christos return NULL;
170 1.1 christos }
171 1.1 christos
172 1.1 christos /* Compatibility: just update the threshold for ctf_discard. */
173 1.1 christos int
174 1.1.1.2 christos ctf_update (ctf_dict_t *fp)
175 1.1 christos {
176 1.1 christos fp->ctf_dtoldid = fp->ctf_typemax;
177 1.1 christos return 0;
178 1.1 christos }
179 1.1 christos
180 1.1.1.3 christos ctf_dynhash_t *
181 1.1.1.2 christos ctf_name_table (ctf_dict_t *fp, int kind)
182 1.1 christos {
183 1.1 christos switch (kind)
184 1.1 christos {
185 1.1 christos case CTF_K_STRUCT:
186 1.1.1.3 christos return fp->ctf_structs;
187 1.1 christos case CTF_K_UNION:
188 1.1.1.3 christos return fp->ctf_unions;
189 1.1 christos case CTF_K_ENUM:
190 1.1.1.3 christos return fp->ctf_enums;
191 1.1 christos default:
192 1.1.1.3 christos return fp->ctf_names;
193 1.1 christos }
194 1.1 christos }
195 1.1 christos
196 1.1 christos int
197 1.1.1.2 christos ctf_dtd_insert (ctf_dict_t *fp, ctf_dtdef_t *dtd, int flag, int kind)
198 1.1 christos {
199 1.1 christos const char *name;
200 1.1 christos if (ctf_dynhash_insert (fp->ctf_dthash, (void *) (uintptr_t) dtd->dtd_type,
201 1.1 christos dtd) < 0)
202 1.1.1.3 christos return ctf_set_errno (fp, ENOMEM);
203 1.1 christos
204 1.1 christos if (flag == CTF_ADD_ROOT && dtd->dtd_data.ctt_name
205 1.1 christos && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL)
206 1.1 christos {
207 1.1.1.3 christos if (ctf_dynhash_insert (ctf_name_table (fp, kind),
208 1.1 christos (char *) name, (void *) (uintptr_t)
209 1.1 christos dtd->dtd_type) < 0)
210 1.1 christos {
211 1.1 christos ctf_dynhash_remove (fp->ctf_dthash, (void *) (uintptr_t)
212 1.1 christos dtd->dtd_type);
213 1.1.1.3 christos return ctf_set_errno (fp, ENOMEM);
214 1.1 christos }
215 1.1 christos }
216 1.1 christos ctf_list_append (&fp->ctf_dtdefs, dtd);
217 1.1 christos return 0;
218 1.1 christos }
219 1.1 christos
220 1.1 christos void
221 1.1.1.2 christos ctf_dtd_delete (ctf_dict_t *fp, ctf_dtdef_t *dtd)
222 1.1 christos {
223 1.1 christos int kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
224 1.1.1.2 christos size_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
225 1.1 christos int name_kind = kind;
226 1.1 christos const char *name;
227 1.1 christos
228 1.1 christos ctf_dynhash_remove (fp->ctf_dthash, (void *) (uintptr_t) dtd->dtd_type);
229 1.1 christos
230 1.1 christos switch (kind)
231 1.1 christos {
232 1.1 christos case CTF_K_STRUCT:
233 1.1 christos case CTF_K_UNION:
234 1.1.1.2 christos {
235 1.1.1.2 christos ctf_lmember_t *memb = (ctf_lmember_t *) dtd->dtd_vlen;
236 1.1.1.2 christos size_t i;
237 1.1.1.2 christos
238 1.1.1.2 christos for (i = 0; i < vlen; i++)
239 1.1.1.2 christos ctf_str_remove_ref (fp, ctf_strraw (fp, memb[i].ctlm_name),
240 1.1.1.2 christos &memb[i].ctlm_name);
241 1.1.1.2 christos }
242 1.1 christos break;
243 1.1.1.2 christos case CTF_K_ENUM:
244 1.1.1.2 christos {
245 1.1.1.2 christos ctf_enum_t *en = (ctf_enum_t *) dtd->dtd_vlen;
246 1.1.1.2 christos size_t i;
247 1.1.1.2 christos
248 1.1.1.2 christos for (i = 0; i < vlen; i++)
249 1.1.1.2 christos ctf_str_remove_ref (fp, ctf_strraw (fp, en[i].cte_name),
250 1.1.1.2 christos &en[i].cte_name);
251 1.1.1.2 christos }
252 1.1 christos break;
253 1.1 christos case CTF_K_FORWARD:
254 1.1 christos name_kind = dtd->dtd_data.ctt_type;
255 1.1 christos break;
256 1.1 christos }
257 1.1.1.2 christos free (dtd->dtd_vlen);
258 1.1.1.2 christos dtd->dtd_vlen_alloc = 0;
259 1.1 christos
260 1.1 christos if (dtd->dtd_data.ctt_name
261 1.1.1.4 christos && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL)
262 1.1 christos {
263 1.1.1.4 christos if (LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info))
264 1.1.1.4 christos ctf_dynhash_remove (ctf_name_table (fp, name_kind), name);
265 1.1 christos ctf_str_remove_ref (fp, name, &dtd->dtd_data.ctt_name);
266 1.1 christos }
267 1.1 christos
268 1.1 christos ctf_list_delete (&fp->ctf_dtdefs, dtd);
269 1.1 christos free (dtd);
270 1.1 christos }
271 1.1 christos
272 1.1 christos ctf_dtdef_t *
273 1.1.1.2 christos ctf_dtd_lookup (const ctf_dict_t *fp, ctf_id_t type)
274 1.1 christos {
275 1.1.1.3 christos if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, type))
276 1.1.1.3 christos fp = fp->ctf_parent;
277 1.1.1.3 christos
278 1.1 christos return (ctf_dtdef_t *)
279 1.1 christos ctf_dynhash_lookup (fp->ctf_dthash, (void *) (uintptr_t) type);
280 1.1 christos }
281 1.1 christos
282 1.1 christos ctf_dtdef_t *
283 1.1.1.2 christos ctf_dynamic_type (const ctf_dict_t *fp, ctf_id_t id)
284 1.1 christos {
285 1.1 christos ctf_id_t idx;
286 1.1 christos
287 1.1 christos if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, id))
288 1.1 christos fp = fp->ctf_parent;
289 1.1 christos
290 1.1 christos idx = LCTF_TYPE_TO_INDEX(fp, id);
291 1.1 christos
292 1.1 christos if ((unsigned long) idx <= fp->ctf_typemax)
293 1.1 christos return ctf_dtd_lookup (fp, id);
294 1.1 christos return NULL;
295 1.1 christos }
296 1.1 christos
297 1.1.1.3 christos static int
298 1.1.1.3 christos ctf_static_type (const ctf_dict_t *fp, ctf_id_t id)
299 1.1.1.3 christos {
300 1.1.1.3 christos ctf_id_t idx;
301 1.1.1.3 christos
302 1.1.1.3 christos if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, id))
303 1.1.1.3 christos fp = fp->ctf_parent;
304 1.1.1.3 christos
305 1.1.1.3 christos idx = LCTF_TYPE_TO_INDEX(fp, id);
306 1.1.1.3 christos
307 1.1.1.3 christos return ((unsigned long) idx <= fp->ctf_stypes);
308 1.1.1.3 christos }
309 1.1.1.3 christos
310 1.1 christos int
311 1.1.1.2 christos ctf_dvd_insert (ctf_dict_t *fp, ctf_dvdef_t *dvd)
312 1.1 christos {
313 1.1 christos if (ctf_dynhash_insert (fp->ctf_dvhash, dvd->dvd_name, dvd) < 0)
314 1.1.1.3 christos return ctf_set_errno (fp, ENOMEM);
315 1.1 christos ctf_list_append (&fp->ctf_dvdefs, dvd);
316 1.1 christos return 0;
317 1.1 christos }
318 1.1 christos
319 1.1 christos void
320 1.1.1.2 christos ctf_dvd_delete (ctf_dict_t *fp, ctf_dvdef_t *dvd)
321 1.1 christos {
322 1.1 christos ctf_dynhash_remove (fp->ctf_dvhash, dvd->dvd_name);
323 1.1 christos free (dvd->dvd_name);
324 1.1 christos
325 1.1 christos ctf_list_delete (&fp->ctf_dvdefs, dvd);
326 1.1 christos free (dvd);
327 1.1 christos }
328 1.1 christos
329 1.1 christos ctf_dvdef_t *
330 1.1.1.2 christos ctf_dvd_lookup (const ctf_dict_t *fp, const char *name)
331 1.1 christos {
332 1.1 christos return (ctf_dvdef_t *) ctf_dynhash_lookup (fp->ctf_dvhash, name);
333 1.1 christos }
334 1.1 christos
335 1.1 christos /* Discard all of the dynamic type definitions and variable definitions that
336 1.1.1.2 christos have been added to the dict since the last call to ctf_update(). We locate
337 1.1.1.2 christos such types by scanning the dtd list and deleting elements that have type IDs
338 1.1.1.2 christos greater than ctf_dtoldid, which is set by ctf_update(), above, and by
339 1.1.1.2 christos scanning the variable list and deleting elements that have update IDs equal
340 1.1.1.2 christos to the current value of the last-update snapshot count (indicating that they
341 1.1.1.2 christos were added after the most recent call to ctf_update()). */
342 1.1 christos int
343 1.1.1.2 christos ctf_discard (ctf_dict_t *fp)
344 1.1 christos {
345 1.1 christos ctf_snapshot_id_t last_update =
346 1.1 christos { fp->ctf_dtoldid,
347 1.1 christos fp->ctf_snapshot_lu + 1 };
348 1.1 christos
349 1.1 christos return (ctf_rollback (fp, last_update));
350 1.1 christos }
351 1.1 christos
352 1.1 christos ctf_snapshot_id_t
353 1.1.1.2 christos ctf_snapshot (ctf_dict_t *fp)
354 1.1 christos {
355 1.1 christos ctf_snapshot_id_t snapid;
356 1.1 christos snapid.dtd_id = fp->ctf_typemax;
357 1.1 christos snapid.snapshot_id = fp->ctf_snapshots++;
358 1.1 christos return snapid;
359 1.1 christos }
360 1.1 christos
361 1.1 christos /* Like ctf_discard(), only discards everything after a particular ID. */
362 1.1 christos int
363 1.1.1.2 christos ctf_rollback (ctf_dict_t *fp, ctf_snapshot_id_t id)
364 1.1 christos {
365 1.1 christos ctf_dtdef_t *dtd, *ntd;
366 1.1 christos ctf_dvdef_t *dvd, *nvd;
367 1.1 christos
368 1.1.1.3 christos if (id.snapshot_id < fp->ctf_stypes)
369 1.1 christos return (ctf_set_errno (fp, ECTF_RDONLY));
370 1.1 christos
371 1.1 christos if (fp->ctf_snapshot_lu >= id.snapshot_id)
372 1.1 christos return (ctf_set_errno (fp, ECTF_OVERROLLBACK));
373 1.1 christos
374 1.1 christos for (dtd = ctf_list_next (&fp->ctf_dtdefs); dtd != NULL; dtd = ntd)
375 1.1 christos {
376 1.1 christos int kind;
377 1.1 christos const char *name;
378 1.1 christos
379 1.1 christos ntd = ctf_list_next (dtd);
380 1.1 christos
381 1.1 christos if (LCTF_TYPE_TO_INDEX (fp, dtd->dtd_type) <= id.dtd_id)
382 1.1 christos continue;
383 1.1 christos
384 1.1 christos kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
385 1.1 christos if (kind == CTF_K_FORWARD)
386 1.1 christos kind = dtd->dtd_data.ctt_type;
387 1.1 christos
388 1.1 christos if (dtd->dtd_data.ctt_name
389 1.1 christos && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL
390 1.1 christos && LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info))
391 1.1 christos {
392 1.1.1.3 christos ctf_dynhash_remove (ctf_name_table (fp, kind), name);
393 1.1 christos ctf_str_remove_ref (fp, name, &dtd->dtd_data.ctt_name);
394 1.1 christos }
395 1.1 christos
396 1.1 christos ctf_dynhash_remove (fp->ctf_dthash, (void *) (uintptr_t) dtd->dtd_type);
397 1.1 christos ctf_dtd_delete (fp, dtd);
398 1.1 christos }
399 1.1 christos
400 1.1 christos for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
401 1.1 christos {
402 1.1 christos nvd = ctf_list_next (dvd);
403 1.1 christos
404 1.1 christos if (dvd->dvd_snapshots <= id.snapshot_id)
405 1.1 christos continue;
406 1.1 christos
407 1.1 christos ctf_dvd_delete (fp, dvd);
408 1.1 christos }
409 1.1 christos
410 1.1 christos fp->ctf_typemax = id.dtd_id;
411 1.1 christos fp->ctf_snapshots = id.snapshot_id;
412 1.1 christos
413 1.1 christos return 0;
414 1.1 christos }
415 1.1 christos
416 1.1.1.2 christos /* Note: vlen is the amount of space *allocated* for the vlen. It may well not
417 1.1.1.2 christos be the amount of space used (yet): the space used is declared in per-kind
418 1.1.1.2 christos fashion in the dtd_data's info word. */
419 1.1 christos static ctf_id_t
420 1.1.1.2 christos ctf_add_generic (ctf_dict_t *fp, uint32_t flag, const char *name, int kind,
421 1.1.1.2 christos size_t vlen, ctf_dtdef_t **rp)
422 1.1 christos {
423 1.1 christos ctf_dtdef_t *dtd;
424 1.1 christos ctf_id_t type;
425 1.1 christos
426 1.1 christos if (flag != CTF_ADD_NONROOT && flag != CTF_ADD_ROOT)
427 1.1.1.3 christos return (ctf_set_typed_errno (fp, EINVAL));
428 1.1 christos
429 1.1 christos if (LCTF_INDEX_TO_TYPE (fp, fp->ctf_typemax, 1) >= CTF_MAX_TYPE)
430 1.1.1.3 christos return (ctf_set_typed_errno (fp, ECTF_FULL));
431 1.1 christos
432 1.1 christos if (LCTF_INDEX_TO_TYPE (fp, fp->ctf_typemax, 1) == (CTF_MAX_PTYPE - 1))
433 1.1.1.3 christos return (ctf_set_typed_errno (fp, ECTF_FULL));
434 1.1.1.3 christos
435 1.1.1.3 christos /* Prohibit addition of a root-visible type that is already present
436 1.1.1.3 christos in the non-dynamic portion. */
437 1.1.1.3 christos
438 1.1.1.3 christos if (flag == CTF_ADD_ROOT && name != NULL && name[0] != '\0')
439 1.1.1.3 christos {
440 1.1.1.3 christos ctf_id_t existing;
441 1.1.1.3 christos
442 1.1.1.3 christos if (((existing = ctf_dynhash_lookup_type (ctf_name_table (fp, kind),
443 1.1.1.3 christos name)) > 0)
444 1.1.1.3 christos && ctf_static_type (fp, existing))
445 1.1.1.3 christos return (ctf_set_typed_errno (fp, ECTF_RDONLY));
446 1.1.1.3 christos }
447 1.1 christos
448 1.1 christos /* Make sure ptrtab always grows to be big enough for all types. */
449 1.1 christos if (ctf_grow_ptrtab (fp) < 0)
450 1.1.1.2 christos return CTF_ERR; /* errno is set for us. */
451 1.1 christos
452 1.1.1.2 christos if ((dtd = calloc (1, sizeof (ctf_dtdef_t))) == NULL)
453 1.1.1.3 christos return (ctf_set_typed_errno (fp, EAGAIN));
454 1.1 christos
455 1.1.1.2 christos dtd->dtd_vlen_alloc = vlen;
456 1.1.1.2 christos if (vlen > 0)
457 1.1.1.2 christos {
458 1.1.1.2 christos if ((dtd->dtd_vlen = calloc (1, vlen)) == NULL)
459 1.1.1.2 christos goto oom;
460 1.1.1.2 christos }
461 1.1.1.2 christos else
462 1.1.1.2 christos dtd->dtd_vlen = NULL;
463 1.1.1.2 christos
464 1.1 christos type = ++fp->ctf_typemax;
465 1.1 christos type = LCTF_INDEX_TO_TYPE (fp, type, (fp->ctf_flags & LCTF_CHILD));
466 1.1 christos
467 1.1.1.3 christos dtd->dtd_data.ctt_name = ctf_str_add_ref (fp, name, &dtd->dtd_data.ctt_name);
468 1.1 christos dtd->dtd_type = type;
469 1.1 christos
470 1.1 christos if (dtd->dtd_data.ctt_name == 0 && name != NULL && name[0] != '\0')
471 1.1.1.2 christos goto oom;
472 1.1 christos
473 1.1 christos if (ctf_dtd_insert (fp, dtd, flag, kind) < 0)
474 1.1.1.2 christos goto err; /* errno is set for us. */
475 1.1.1.2 christos
476 1.1 christos *rp = dtd;
477 1.1 christos return type;
478 1.1.1.2 christos
479 1.1.1.2 christos oom:
480 1.1.1.2 christos ctf_set_errno (fp, EAGAIN);
481 1.1.1.2 christos err:
482 1.1.1.2 christos free (dtd->dtd_vlen);
483 1.1.1.2 christos free (dtd);
484 1.1.1.2 christos return CTF_ERR;
485 1.1 christos }
486 1.1 christos
487 1.1 christos /* When encoding integer sizes, we want to convert a byte count in the range
488 1.1 christos 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc). The clp2() function
489 1.1 christos is a clever implementation from "Hacker's Delight" by Henry Warren, Jr. */
490 1.1 christos static size_t
491 1.1 christos clp2 (size_t x)
492 1.1 christos {
493 1.1 christos x--;
494 1.1 christos
495 1.1 christos x |= (x >> 1);
496 1.1 christos x |= (x >> 2);
497 1.1 christos x |= (x >> 4);
498 1.1 christos x |= (x >> 8);
499 1.1 christos x |= (x >> 16);
500 1.1 christos
501 1.1 christos return (x + 1);
502 1.1 christos }
503 1.1 christos
504 1.1 christos ctf_id_t
505 1.1.1.2 christos ctf_add_encoded (ctf_dict_t *fp, uint32_t flag,
506 1.1 christos const char *name, const ctf_encoding_t *ep, uint32_t kind)
507 1.1 christos {
508 1.1 christos ctf_dtdef_t *dtd;
509 1.1 christos ctf_id_t type;
510 1.1.1.2 christos uint32_t encoding;
511 1.1 christos
512 1.1 christos if (ep == NULL)
513 1.1.1.3 christos return (ctf_set_typed_errno (fp, EINVAL));
514 1.1 christos
515 1.1.1.2 christos if (name == NULL || name[0] == '\0')
516 1.1.1.3 christos return (ctf_set_typed_errno (fp, ECTF_NONAME));
517 1.1.1.2 christos
518 1.1.1.2 christos if (!ctf_assert (fp, kind == CTF_K_INTEGER || kind == CTF_K_FLOAT))
519 1.1.1.3 christos return CTF_ERR; /* errno is set for us. */
520 1.1.1.2 christos
521 1.1.1.2 christos if ((type = ctf_add_generic (fp, flag, name, kind, sizeof (uint32_t),
522 1.1.1.2 christos &dtd)) == CTF_ERR)
523 1.1 christos return CTF_ERR; /* errno is set for us. */
524 1.1 christos
525 1.1 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, flag, 0);
526 1.1 christos dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, CHAR_BIT)
527 1.1 christos / CHAR_BIT);
528 1.1.1.2 christos switch (kind)
529 1.1.1.2 christos {
530 1.1.1.2 christos case CTF_K_INTEGER:
531 1.1.1.2 christos encoding = CTF_INT_DATA (ep->cte_format, ep->cte_offset, ep->cte_bits);
532 1.1.1.2 christos break;
533 1.1.1.2 christos case CTF_K_FLOAT:
534 1.1.1.2 christos encoding = CTF_FP_DATA (ep->cte_format, ep->cte_offset, ep->cte_bits);
535 1.1.1.2 christos break;
536 1.1.1.3 christos default:
537 1.1.1.3 christos /* ctf_assert is opaque with -fno-inline. This dead code avoids
538 1.1.1.3 christos a warning about "encoding" being used uninitialized. */
539 1.1.1.3 christos return CTF_ERR;
540 1.1.1.2 christos }
541 1.1.1.2 christos memcpy (dtd->dtd_vlen, &encoding, sizeof (encoding));
542 1.1 christos
543 1.1 christos return type;
544 1.1 christos }
545 1.1 christos
546 1.1 christos ctf_id_t
547 1.1.1.2 christos ctf_add_reftype (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref, uint32_t kind)
548 1.1 christos {
549 1.1 christos ctf_dtdef_t *dtd;
550 1.1 christos ctf_id_t type;
551 1.1.1.2 christos ctf_dict_t *tmp = fp;
552 1.1 christos int child = fp->ctf_flags & LCTF_CHILD;
553 1.1 christos
554 1.1 christos if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
555 1.1.1.3 christos return (ctf_set_typed_errno (fp, EINVAL));
556 1.1 christos
557 1.1 christos if (ref != 0 && ctf_lookup_by_id (&tmp, ref) == NULL)
558 1.1 christos return CTF_ERR; /* errno is set for us. */
559 1.1 christos
560 1.1.1.2 christos if ((type = ctf_add_generic (fp, flag, NULL, kind, 0, &dtd)) == CTF_ERR)
561 1.1 christos return CTF_ERR; /* errno is set for us. */
562 1.1 christos
563 1.1 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, flag, 0);
564 1.1 christos dtd->dtd_data.ctt_type = (uint32_t) ref;
565 1.1 christos
566 1.1 christos if (kind != CTF_K_POINTER)
567 1.1 christos return type;
568 1.1 christos
569 1.1.1.2 christos /* If we are adding a pointer, update the ptrtab, pointing at this type from
570 1.1.1.2 christos the type it points to. Note that ctf_typemax is at this point one higher
571 1.1.1.2 christos than we want to check against, because it's just been incremented for the
572 1.1.1.2 christos addition of this type. The pptrtab is lazily-updated as needed, so is not
573 1.1.1.2 christos touched here. */
574 1.1 christos
575 1.1 christos uint32_t type_idx = LCTF_TYPE_TO_INDEX (fp, type);
576 1.1 christos uint32_t ref_idx = LCTF_TYPE_TO_INDEX (fp, ref);
577 1.1 christos
578 1.1 christos if (LCTF_TYPE_ISCHILD (fp, ref) == child
579 1.1 christos && ref_idx < fp->ctf_typemax)
580 1.1.1.2 christos fp->ctf_ptrtab[ref_idx] = type_idx;
581 1.1 christos
582 1.1 christos return type;
583 1.1 christos }
584 1.1 christos
585 1.1 christos ctf_id_t
586 1.1.1.2 christos ctf_add_slice (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref,
587 1.1 christos const ctf_encoding_t *ep)
588 1.1 christos {
589 1.1 christos ctf_dtdef_t *dtd;
590 1.1.1.2 christos ctf_slice_t slice;
591 1.1 christos ctf_id_t resolved_ref = ref;
592 1.1 christos ctf_id_t type;
593 1.1 christos int kind;
594 1.1 christos const ctf_type_t *tp;
595 1.1.1.2 christos ctf_dict_t *tmp = fp;
596 1.1 christos
597 1.1 christos if (ep == NULL)
598 1.1.1.3 christos return (ctf_set_typed_errno (fp, EINVAL));
599 1.1 christos
600 1.1 christos if ((ep->cte_bits > 255) || (ep->cte_offset > 255))
601 1.1.1.3 christos return (ctf_set_typed_errno (fp, ECTF_SLICEOVERFLOW));
602 1.1 christos
603 1.1 christos if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
604 1.1.1.3 christos return (ctf_set_typed_errno (fp, EINVAL));
605 1.1 christos
606 1.1 christos if (ref != 0 && ((tp = ctf_lookup_by_id (&tmp, ref)) == NULL))
607 1.1 christos return CTF_ERR; /* errno is set for us. */
608 1.1 christos
609 1.1 christos /* Make sure we ultimately point to an integral type. We also allow slices to
610 1.1 christos point to the unimplemented type, for now, because the compiler can emit
611 1.1 christos such slices, though they're not very much use. */
612 1.1 christos
613 1.1.1.3 christos resolved_ref = ctf_type_resolve_unsliced (fp, ref);
614 1.1.1.3 christos kind = ctf_type_kind_unsliced (fp, resolved_ref);
615 1.1 christos
616 1.1 christos if ((kind != CTF_K_INTEGER) && (kind != CTF_K_FLOAT) &&
617 1.1 christos (kind != CTF_K_ENUM)
618 1.1 christos && (ref != 0))
619 1.1.1.3 christos return (ctf_set_typed_errno (fp, ECTF_NOTINTFP));
620 1.1 christos
621 1.1.1.2 christos if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_SLICE,
622 1.1.1.2 christos sizeof (ctf_slice_t), &dtd)) == CTF_ERR)
623 1.1 christos return CTF_ERR; /* errno is set for us. */
624 1.1 christos
625 1.1.1.2 christos memset (&slice, 0, sizeof (ctf_slice_t));
626 1.1.1.2 christos
627 1.1 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_SLICE, flag, 0);
628 1.1 christos dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, CHAR_BIT)
629 1.1 christos / CHAR_BIT);
630 1.1.1.2 christos slice.cts_type = (uint32_t) ref;
631 1.1.1.2 christos slice.cts_bits = ep->cte_bits;
632 1.1.1.2 christos slice.cts_offset = ep->cte_offset;
633 1.1.1.2 christos memcpy (dtd->dtd_vlen, &slice, sizeof (ctf_slice_t));
634 1.1 christos
635 1.1 christos return type;
636 1.1 christos }
637 1.1 christos
638 1.1 christos ctf_id_t
639 1.1.1.2 christos ctf_add_integer (ctf_dict_t *fp, uint32_t flag,
640 1.1 christos const char *name, const ctf_encoding_t *ep)
641 1.1 christos {
642 1.1 christos return (ctf_add_encoded (fp, flag, name, ep, CTF_K_INTEGER));
643 1.1 christos }
644 1.1 christos
645 1.1 christos ctf_id_t
646 1.1.1.2 christos ctf_add_float (ctf_dict_t *fp, uint32_t flag,
647 1.1 christos const char *name, const ctf_encoding_t *ep)
648 1.1 christos {
649 1.1 christos return (ctf_add_encoded (fp, flag, name, ep, CTF_K_FLOAT));
650 1.1 christos }
651 1.1 christos
652 1.1 christos ctf_id_t
653 1.1.1.2 christos ctf_add_pointer (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref)
654 1.1 christos {
655 1.1 christos return (ctf_add_reftype (fp, flag, ref, CTF_K_POINTER));
656 1.1 christos }
657 1.1 christos
658 1.1 christos ctf_id_t
659 1.1.1.2 christos ctf_add_array (ctf_dict_t *fp, uint32_t flag, const ctf_arinfo_t *arp)
660 1.1 christos {
661 1.1 christos ctf_dtdef_t *dtd;
662 1.1.1.2 christos ctf_array_t cta;
663 1.1 christos ctf_id_t type;
664 1.1.1.2 christos ctf_dict_t *tmp = fp;
665 1.1 christos
666 1.1 christos if (arp == NULL)
667 1.1.1.3 christos return (ctf_set_typed_errno (fp, EINVAL));
668 1.1 christos
669 1.1 christos if (arp->ctr_contents != 0
670 1.1 christos && ctf_lookup_by_id (&tmp, arp->ctr_contents) == NULL)
671 1.1 christos return CTF_ERR; /* errno is set for us. */
672 1.1 christos
673 1.1 christos tmp = fp;
674 1.1 christos if (ctf_lookup_by_id (&tmp, arp->ctr_index) == NULL)
675 1.1 christos return CTF_ERR; /* errno is set for us. */
676 1.1 christos
677 1.1.1.2 christos if (ctf_type_kind (fp, arp->ctr_index) == CTF_K_FORWARD)
678 1.1.1.2 christos {
679 1.1.1.2 christos ctf_err_warn (fp, 1, ECTF_INCOMPLETE,
680 1.1.1.2 christos _("ctf_add_array: index type %lx is incomplete"),
681 1.1.1.2 christos arp->ctr_contents);
682 1.1.1.3 christos return (ctf_set_typed_errno (fp, ECTF_INCOMPLETE));
683 1.1.1.2 christos }
684 1.1.1.2 christos
685 1.1.1.2 christos if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_ARRAY,
686 1.1.1.2 christos sizeof (ctf_array_t), &dtd)) == CTF_ERR)
687 1.1 christos return CTF_ERR; /* errno is set for us. */
688 1.1 christos
689 1.1.1.2 christos memset (&cta, 0, sizeof (ctf_array_t));
690 1.1.1.2 christos
691 1.1 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_ARRAY, flag, 0);
692 1.1 christos dtd->dtd_data.ctt_size = 0;
693 1.1.1.2 christos cta.cta_contents = (uint32_t) arp->ctr_contents;
694 1.1.1.2 christos cta.cta_index = (uint32_t) arp->ctr_index;
695 1.1.1.2 christos cta.cta_nelems = arp->ctr_nelems;
696 1.1.1.2 christos memcpy (dtd->dtd_vlen, &cta, sizeof (ctf_array_t));
697 1.1 christos
698 1.1 christos return type;
699 1.1 christos }
700 1.1 christos
701 1.1 christos int
702 1.1.1.2 christos ctf_set_array (ctf_dict_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
703 1.1 christos {
704 1.1.1.3 christos ctf_dict_t *ofp = fp;
705 1.1 christos ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, type);
706 1.1.1.2 christos ctf_array_t *vlen;
707 1.1 christos
708 1.1.1.3 christos if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, type))
709 1.1.1.3 christos fp = fp->ctf_parent;
710 1.1.1.3 christos
711 1.1.1.3 christos /* You can only call ctf_set_array on a type you have added, not a
712 1.1.1.3 christos type that was read in via ctf_open(). */
713 1.1.1.3 christos if (type < fp->ctf_stypes)
714 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_RDONLY));
715 1.1 christos
716 1.1 christos if (dtd == NULL
717 1.1 christos || LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
718 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_BADID));
719 1.1 christos
720 1.1.1.2 christos vlen = (ctf_array_t *) dtd->dtd_vlen;
721 1.1.1.2 christos vlen->cta_contents = (uint32_t) arp->ctr_contents;
722 1.1.1.2 christos vlen->cta_index = (uint32_t) arp->ctr_index;
723 1.1.1.2 christos vlen->cta_nelems = arp->ctr_nelems;
724 1.1 christos
725 1.1 christos return 0;
726 1.1 christos }
727 1.1 christos
728 1.1 christos ctf_id_t
729 1.1.1.2 christos ctf_add_function (ctf_dict_t *fp, uint32_t flag,
730 1.1 christos const ctf_funcinfo_t *ctc, const ctf_id_t *argv)
731 1.1 christos {
732 1.1 christos ctf_dtdef_t *dtd;
733 1.1 christos ctf_id_t type;
734 1.1 christos uint32_t vlen;
735 1.1.1.2 christos uint32_t *vdat;
736 1.1.1.2 christos ctf_dict_t *tmp = fp;
737 1.1.1.2 christos size_t initial_vlen;
738 1.1 christos size_t i;
739 1.1 christos
740 1.1 christos if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0
741 1.1 christos || (ctc->ctc_argc != 0 && argv == NULL))
742 1.1.1.3 christos return (ctf_set_typed_errno (fp, EINVAL));
743 1.1 christos
744 1.1 christos vlen = ctc->ctc_argc;
745 1.1 christos if (ctc->ctc_flags & CTF_FUNC_VARARG)
746 1.1 christos vlen++; /* Add trailing zero to indicate varargs (see below). */
747 1.1 christos
748 1.1 christos if (ctc->ctc_return != 0
749 1.1 christos && ctf_lookup_by_id (&tmp, ctc->ctc_return) == NULL)
750 1.1.1.2 christos return CTF_ERR; /* errno is set for us. */
751 1.1 christos
752 1.1 christos if (vlen > CTF_MAX_VLEN)
753 1.1.1.3 christos return (ctf_set_typed_errno (fp, EOVERFLOW));
754 1.1 christos
755 1.1.1.2 christos /* One word extra allocated for padding for 4-byte alignment if need be.
756 1.1.1.2 christos Not reflected in vlen: we don't want to copy anything into it, and
757 1.1.1.2 christos it's in addition to (e.g.) the trailing 0 indicating varargs. */
758 1.1.1.2 christos
759 1.1.1.2 christos initial_vlen = (sizeof (uint32_t) * (vlen + (vlen & 1)));
760 1.1.1.2 christos if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_FUNCTION,
761 1.1.1.2 christos initial_vlen, &dtd)) == CTF_ERR)
762 1.1.1.2 christos return CTF_ERR; /* errno is set for us. */
763 1.1.1.2 christos
764 1.1.1.2 christos vdat = (uint32_t *) dtd->dtd_vlen;
765 1.1 christos
766 1.1 christos for (i = 0; i < ctc->ctc_argc; i++)
767 1.1 christos {
768 1.1 christos tmp = fp;
769 1.1 christos if (argv[i] != 0 && ctf_lookup_by_id (&tmp, argv[i]) == NULL)
770 1.1.1.2 christos return CTF_ERR; /* errno is set for us. */
771 1.1 christos vdat[i] = (uint32_t) argv[i];
772 1.1 christos }
773 1.1 christos
774 1.1 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_FUNCTION, flag, vlen);
775 1.1 christos dtd->dtd_data.ctt_type = (uint32_t) ctc->ctc_return;
776 1.1 christos
777 1.1 christos if (ctc->ctc_flags & CTF_FUNC_VARARG)
778 1.1 christos vdat[vlen - 1] = 0; /* Add trailing zero to indicate varargs. */
779 1.1 christos
780 1.1 christos return type;
781 1.1 christos }
782 1.1 christos
783 1.1 christos ctf_id_t
784 1.1.1.2 christos ctf_add_struct_sized (ctf_dict_t *fp, uint32_t flag, const char *name,
785 1.1 christos size_t size)
786 1.1 christos {
787 1.1 christos ctf_dtdef_t *dtd;
788 1.1 christos ctf_id_t type = 0;
789 1.1.1.2 christos size_t initial_vlen = sizeof (ctf_lmember_t) * INITIAL_VLEN;
790 1.1 christos
791 1.1 christos /* Promote root-visible forwards to structs. */
792 1.1 christos if (name != NULL)
793 1.1 christos type = ctf_lookup_by_rawname (fp, CTF_K_STRUCT, name);
794 1.1 christos
795 1.1.1.3 christos /* Prohibit promotion if this type was ctf_open()ed. */
796 1.1.1.3 christos if (type > 0 && type < fp->ctf_stypes)
797 1.1.1.3 christos return (ctf_set_errno (fp, ECTF_RDONLY));
798 1.1.1.3 christos
799 1.1 christos if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
800 1.1 christos dtd = ctf_dtd_lookup (fp, type);
801 1.1 christos else if ((type = ctf_add_generic (fp, flag, name, CTF_K_STRUCT,
802 1.1.1.2 christos initial_vlen, &dtd)) == CTF_ERR)
803 1.1 christos return CTF_ERR; /* errno is set for us. */
804 1.1 christos
805 1.1.1.2 christos /* Forwards won't have any vlen yet. */
806 1.1.1.2 christos if (dtd->dtd_vlen_alloc == 0)
807 1.1 christos {
808 1.1.1.2 christos if ((dtd->dtd_vlen = calloc (1, initial_vlen)) == NULL)
809 1.1.1.3 christos return (ctf_set_typed_errno (fp, ENOMEM));
810 1.1.1.2 christos dtd->dtd_vlen_alloc = initial_vlen;
811 1.1 christos }
812 1.1.1.2 christos
813 1.1.1.2 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_STRUCT, flag, 0);
814 1.1.1.2 christos dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
815 1.1.1.2 christos dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
816 1.1.1.2 christos dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
817 1.1 christos
818 1.1 christos return type;
819 1.1 christos }
820 1.1 christos
821 1.1 christos ctf_id_t
822 1.1.1.2 christos ctf_add_struct (ctf_dict_t *fp, uint32_t flag, const char *name)
823 1.1 christos {
824 1.1 christos return (ctf_add_struct_sized (fp, flag, name, 0));
825 1.1 christos }
826 1.1 christos
827 1.1 christos ctf_id_t
828 1.1.1.2 christos ctf_add_union_sized (ctf_dict_t *fp, uint32_t flag, const char *name,
829 1.1 christos size_t size)
830 1.1 christos {
831 1.1 christos ctf_dtdef_t *dtd;
832 1.1 christos ctf_id_t type = 0;
833 1.1.1.2 christos size_t initial_vlen = sizeof (ctf_lmember_t) * INITIAL_VLEN;
834 1.1 christos
835 1.1 christos /* Promote root-visible forwards to unions. */
836 1.1 christos if (name != NULL)
837 1.1 christos type = ctf_lookup_by_rawname (fp, CTF_K_UNION, name);
838 1.1 christos
839 1.1.1.3 christos /* Prohibit promotion if this type was ctf_open()ed. */
840 1.1.1.3 christos if (type > 0 && type < fp->ctf_stypes)
841 1.1.1.3 christos return (ctf_set_errno (fp, ECTF_RDONLY));
842 1.1.1.3 christos
843 1.1 christos if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
844 1.1 christos dtd = ctf_dtd_lookup (fp, type);
845 1.1 christos else if ((type = ctf_add_generic (fp, flag, name, CTF_K_UNION,
846 1.1.1.2 christos initial_vlen, &dtd)) == CTF_ERR)
847 1.1.1.3 christos return CTF_ERR; /* errno is set for us. */
848 1.1 christos
849 1.1.1.2 christos /* Forwards won't have any vlen yet. */
850 1.1.1.2 christos if (dtd->dtd_vlen_alloc == 0)
851 1.1 christos {
852 1.1.1.2 christos if ((dtd->dtd_vlen = calloc (1, initial_vlen)) == NULL)
853 1.1.1.3 christos return (ctf_set_typed_errno (fp, ENOMEM));
854 1.1.1.2 christos dtd->dtd_vlen_alloc = initial_vlen;
855 1.1 christos }
856 1.1.1.2 christos
857 1.1.1.2 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_UNION, flag, 0);
858 1.1.1.2 christos dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
859 1.1.1.2 christos dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
860 1.1.1.2 christos dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
861 1.1 christos
862 1.1 christos return type;
863 1.1 christos }
864 1.1 christos
865 1.1 christos ctf_id_t
866 1.1.1.2 christos ctf_add_union (ctf_dict_t *fp, uint32_t flag, const char *name)
867 1.1 christos {
868 1.1 christos return (ctf_add_union_sized (fp, flag, name, 0));
869 1.1 christos }
870 1.1 christos
871 1.1 christos ctf_id_t
872 1.1.1.2 christos ctf_add_enum (ctf_dict_t *fp, uint32_t flag, const char *name)
873 1.1 christos {
874 1.1 christos ctf_dtdef_t *dtd;
875 1.1 christos ctf_id_t type = 0;
876 1.1.1.2 christos size_t initial_vlen = sizeof (ctf_enum_t) * INITIAL_VLEN;
877 1.1 christos
878 1.1 christos /* Promote root-visible forwards to enums. */
879 1.1 christos if (name != NULL)
880 1.1 christos type = ctf_lookup_by_rawname (fp, CTF_K_ENUM, name);
881 1.1 christos
882 1.1.1.3 christos /* Prohibit promotion if this type was ctf_open()ed. */
883 1.1.1.3 christos if (type > 0 && type < fp->ctf_stypes)
884 1.1.1.3 christos return (ctf_set_errno (fp, ECTF_RDONLY));
885 1.1.1.3 christos
886 1.1 christos if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
887 1.1 christos dtd = ctf_dtd_lookup (fp, type);
888 1.1 christos else if ((type = ctf_add_generic (fp, flag, name, CTF_K_ENUM,
889 1.1.1.2 christos initial_vlen, &dtd)) == CTF_ERR)
890 1.1 christos return CTF_ERR; /* errno is set for us. */
891 1.1 christos
892 1.1.1.2 christos /* Forwards won't have any vlen yet. */
893 1.1.1.2 christos if (dtd->dtd_vlen_alloc == 0)
894 1.1.1.2 christos {
895 1.1.1.2 christos if ((dtd->dtd_vlen = calloc (1, initial_vlen)) == NULL)
896 1.1.1.3 christos return (ctf_set_typed_errno (fp, ENOMEM));
897 1.1.1.2 christos dtd->dtd_vlen_alloc = initial_vlen;
898 1.1.1.2 christos }
899 1.1.1.2 christos
900 1.1 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_ENUM, flag, 0);
901 1.1 christos dtd->dtd_data.ctt_size = fp->ctf_dmodel->ctd_int;
902 1.1 christos
903 1.1 christos return type;
904 1.1 christos }
905 1.1 christos
906 1.1 christos ctf_id_t
907 1.1.1.2 christos ctf_add_enum_encoded (ctf_dict_t *fp, uint32_t flag, const char *name,
908 1.1 christos const ctf_encoding_t *ep)
909 1.1 christos {
910 1.1 christos ctf_id_t type = 0;
911 1.1 christos
912 1.1 christos /* First, create the enum if need be, using most of the same machinery as
913 1.1 christos ctf_add_enum(), to ensure that we do not allow things past that are not
914 1.1 christos enums or forwards to them. (This includes other slices: you cannot slice a
915 1.1 christos slice, which would be a useless thing to do anyway.) */
916 1.1 christos
917 1.1 christos if (name != NULL)
918 1.1 christos type = ctf_lookup_by_rawname (fp, CTF_K_ENUM, name);
919 1.1 christos
920 1.1 christos if (type != 0)
921 1.1 christos {
922 1.1 christos if ((ctf_type_kind (fp, type) != CTF_K_FORWARD) &&
923 1.1 christos (ctf_type_kind_unsliced (fp, type) != CTF_K_ENUM))
924 1.1.1.3 christos return (ctf_set_typed_errno (fp, ECTF_NOTINTFP));
925 1.1 christos }
926 1.1 christos else if ((type = ctf_add_enum (fp, flag, name)) == CTF_ERR)
927 1.1 christos return CTF_ERR; /* errno is set for us. */
928 1.1 christos
929 1.1 christos /* Now attach a suitable slice to it. */
930 1.1 christos
931 1.1 christos return ctf_add_slice (fp, flag, type, ep);
932 1.1 christos }
933 1.1 christos
934 1.1 christos ctf_id_t
935 1.1.1.2 christos ctf_add_forward (ctf_dict_t *fp, uint32_t flag, const char *name,
936 1.1 christos uint32_t kind)
937 1.1 christos {
938 1.1 christos ctf_dtdef_t *dtd;
939 1.1 christos ctf_id_t type = 0;
940 1.1 christos
941 1.1 christos if (!ctf_forwardable_kind (kind))
942 1.1.1.3 christos return (ctf_set_typed_errno (fp, ECTF_NOTSUE));
943 1.1 christos
944 1.1.1.2 christos if (name == NULL || name[0] == '\0')
945 1.1.1.3 christos return (ctf_set_typed_errno (fp, ECTF_NONAME));
946 1.1.1.2 christos
947 1.1.1.3 christos /* If the type is already defined or exists as a forward tag, just return
948 1.1.1.3 christos the ctf_id_t of the existing definition. Since this changes nothing,
949 1.1.1.3 christos it's safe to do even on the read-only portion of the dict. */
950 1.1 christos
951 1.1.1.2 christos type = ctf_lookup_by_rawname (fp, kind, name);
952 1.1 christos
953 1.1 christos if (type)
954 1.1 christos return type;
955 1.1 christos
956 1.1.1.2 christos if ((type = ctf_add_generic (fp, flag, name, kind, 0, &dtd)) == CTF_ERR)
957 1.1 christos return CTF_ERR; /* errno is set for us. */
958 1.1 christos
959 1.1 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_FORWARD, flag, 0);
960 1.1 christos dtd->dtd_data.ctt_type = kind;
961 1.1 christos
962 1.1 christos return type;
963 1.1 christos }
964 1.1 christos
965 1.1 christos ctf_id_t
966 1.1.1.2 christos ctf_add_unknown (ctf_dict_t *fp, uint32_t flag, const char *name)
967 1.1.1.2 christos {
968 1.1.1.2 christos ctf_dtdef_t *dtd;
969 1.1.1.2 christos ctf_id_t type = 0;
970 1.1.1.2 christos
971 1.1.1.2 christos /* If a type is already defined with this name, error (if not CTF_K_UNKNOWN)
972 1.1.1.2 christos or just return it. */
973 1.1.1.2 christos
974 1.1.1.2 christos if (name != NULL && name[0] != '\0' && flag == CTF_ADD_ROOT
975 1.1.1.2 christos && (type = ctf_lookup_by_rawname (fp, CTF_K_UNKNOWN, name)))
976 1.1.1.2 christos {
977 1.1.1.2 christos if (ctf_type_kind (fp, type) == CTF_K_UNKNOWN)
978 1.1.1.2 christos return type;
979 1.1.1.2 christos else
980 1.1.1.2 christos {
981 1.1.1.2 christos ctf_err_warn (fp, 1, ECTF_CONFLICT,
982 1.1.1.2 christos _("ctf_add_unknown: cannot add unknown type "
983 1.1.1.2 christos "named %s: type of this name already defined"),
984 1.1.1.2 christos name ? name : _("(unnamed type)"));
985 1.1.1.3 christos return (ctf_set_typed_errno (fp, ECTF_CONFLICT));
986 1.1.1.2 christos }
987 1.1.1.2 christos }
988 1.1.1.2 christos
989 1.1.1.2 christos if ((type = ctf_add_generic (fp, flag, name, CTF_K_UNKNOWN, 0, &dtd)) == CTF_ERR)
990 1.1.1.2 christos return CTF_ERR; /* errno is set for us. */
991 1.1.1.2 christos
992 1.1.1.2 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_UNKNOWN, flag, 0);
993 1.1.1.2 christos dtd->dtd_data.ctt_type = 0;
994 1.1.1.2 christos
995 1.1.1.2 christos return type;
996 1.1.1.2 christos }
997 1.1.1.2 christos
998 1.1.1.2 christos ctf_id_t
999 1.1.1.2 christos ctf_add_typedef (ctf_dict_t *fp, uint32_t flag, const char *name,
1000 1.1 christos ctf_id_t ref)
1001 1.1 christos {
1002 1.1 christos ctf_dtdef_t *dtd;
1003 1.1 christos ctf_id_t type;
1004 1.1.1.2 christos ctf_dict_t *tmp = fp;
1005 1.1 christos
1006 1.1 christos if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
1007 1.1.1.3 christos return (ctf_set_typed_errno (fp, EINVAL));
1008 1.1 christos
1009 1.1.1.2 christos if (name == NULL || name[0] == '\0')
1010 1.1.1.3 christos return (ctf_set_typed_errno (fp, ECTF_NONAME));
1011 1.1.1.2 christos
1012 1.1 christos if (ref != 0 && ctf_lookup_by_id (&tmp, ref) == NULL)
1013 1.1 christos return CTF_ERR; /* errno is set for us. */
1014 1.1 christos
1015 1.1.1.2 christos if ((type = ctf_add_generic (fp, flag, name, CTF_K_TYPEDEF, 0,
1016 1.1 christos &dtd)) == CTF_ERR)
1017 1.1 christos return CTF_ERR; /* errno is set for us. */
1018 1.1 christos
1019 1.1 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_TYPEDEF, flag, 0);
1020 1.1 christos dtd->dtd_data.ctt_type = (uint32_t) ref;
1021 1.1 christos
1022 1.1 christos return type;
1023 1.1 christos }
1024 1.1 christos
1025 1.1 christos ctf_id_t
1026 1.1.1.2 christos ctf_add_volatile (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref)
1027 1.1 christos {
1028 1.1 christos return (ctf_add_reftype (fp, flag, ref, CTF_K_VOLATILE));
1029 1.1 christos }
1030 1.1 christos
1031 1.1 christos ctf_id_t
1032 1.1.1.2 christos ctf_add_const (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref)
1033 1.1 christos {
1034 1.1 christos return (ctf_add_reftype (fp, flag, ref, CTF_K_CONST));
1035 1.1 christos }
1036 1.1 christos
1037 1.1 christos ctf_id_t
1038 1.1.1.2 christos ctf_add_restrict (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref)
1039 1.1 christos {
1040 1.1 christos return (ctf_add_reftype (fp, flag, ref, CTF_K_RESTRICT));
1041 1.1 christos }
1042 1.1 christos
1043 1.1 christos int
1044 1.1.1.2 christos ctf_add_enumerator (ctf_dict_t *fp, ctf_id_t enid, const char *name,
1045 1.1 christos int value)
1046 1.1 christos {
1047 1.1.1.3 christos ctf_dict_t *ofp = fp;
1048 1.1 christos ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, enid);
1049 1.1.1.2 christos unsigned char *old_vlen;
1050 1.1.1.2 christos ctf_enum_t *en;
1051 1.1 christos
1052 1.1 christos uint32_t kind, vlen, root;
1053 1.1 christos
1054 1.1 christos if (name == NULL)
1055 1.1 christos return (ctf_set_errno (fp, EINVAL));
1056 1.1 christos
1057 1.1.1.3 christos if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, enid))
1058 1.1.1.3 christos fp = fp->ctf_parent;
1059 1.1.1.3 christos
1060 1.1.1.3 christos if (enid < fp->ctf_stypes)
1061 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_RDONLY));
1062 1.1 christos
1063 1.1 christos if (dtd == NULL)
1064 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_BADID));
1065 1.1 christos
1066 1.1 christos kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
1067 1.1 christos root = LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info);
1068 1.1 christos vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
1069 1.1 christos
1070 1.1.1.4 christos /* Enumeration constant names are only added, and only checked for duplicates,
1071 1.1.1.4 christos if the enum they are part of is a root-visible type. */
1072 1.1.1.4 christos
1073 1.1.1.4 christos if (root == CTF_ADD_ROOT && ctf_dynhash_lookup (fp->ctf_names, name))
1074 1.1.1.4 christos {
1075 1.1.1.4 christos if (fp->ctf_flags & LCTF_STRICT_NO_DUP_ENUMERATORS)
1076 1.1.1.4 christos return (ctf_set_errno (ofp, ECTF_DUPLICATE));
1077 1.1.1.4 christos
1078 1.1.1.4 christos if (ctf_track_enumerator (fp, enid, name) < 0)
1079 1.1.1.4 christos return (ctf_set_errno (ofp, ctf_errno (fp)));
1080 1.1.1.4 christos }
1081 1.1.1.4 christos
1082 1.1 christos if (kind != CTF_K_ENUM)
1083 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_NOTENUM));
1084 1.1 christos
1085 1.1 christos if (vlen == CTF_MAX_VLEN)
1086 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_DTFULL));
1087 1.1 christos
1088 1.1.1.2 christos old_vlen = dtd->dtd_vlen;
1089 1.1.1.4 christos
1090 1.1.1.2 christos if (ctf_grow_vlen (fp, dtd, sizeof (ctf_enum_t) * (vlen + 1)) < 0)
1091 1.1.1.2 christos return -1; /* errno is set for us. */
1092 1.1.1.4 christos
1093 1.1.1.2 christos en = (ctf_enum_t *) dtd->dtd_vlen;
1094 1.1.1.2 christos
1095 1.1.1.3 christos /* Remove refs in the old vlen region and reapply them. */
1096 1.1 christos
1097 1.1.1.3 christos ctf_str_move_refs (fp, old_vlen, sizeof (ctf_enum_t) * vlen, dtd->dtd_vlen);
1098 1.1 christos
1099 1.1.1.4 christos /* Check for constant duplication within any given enum: only needed for
1100 1.1.1.4 christos non-root-visible types, since the duplicate detection above does the job
1101 1.1.1.4 christos for root-visible types just fine. */
1102 1.1.1.2 christos
1103 1.1.1.4 christos if (root == CTF_ADD_NONROOT && (fp->ctf_flags & LCTF_STRICT_NO_DUP_ENUMERATORS))
1104 1.1.1.4 christos {
1105 1.1.1.4 christos size_t i;
1106 1.1.1.2 christos
1107 1.1.1.4 christos for (i = 0; i < vlen; i++)
1108 1.1.1.4 christos if (strcmp (ctf_strptr (fp, en[i].cte_name), name) == 0)
1109 1.1.1.4 christos return (ctf_set_errno (ofp, ECTF_DUPLICATE));
1110 1.1.1.4 christos }
1111 1.1.1.4 christos
1112 1.1.1.4 christos en[vlen].cte_name = ctf_str_add_movable_ref (fp, name, &en[vlen].cte_name);
1113 1.1.1.4 christos en[vlen].cte_value = value;
1114 1.1.1.4 christos
1115 1.1.1.4 christos if (en[vlen].cte_name == 0 && name != NULL && name[0] != '\0')
1116 1.1.1.3 christos return (ctf_set_errno (ofp, ctf_errno (fp)));
1117 1.1 christos
1118 1.1.1.4 christos /* Put the newly-added enumerator name into the name table if this type is
1119 1.1.1.4 christos root-visible. */
1120 1.1.1.4 christos
1121 1.1.1.4 christos if (root == CTF_ADD_ROOT)
1122 1.1.1.4 christos {
1123 1.1.1.4 christos if (ctf_dynhash_insert (fp->ctf_names,
1124 1.1.1.4 christos (char *) ctf_strptr (fp, en[vlen].cte_name),
1125 1.1.1.4 christos (void *) (uintptr_t) enid) < 0)
1126 1.1.1.4 christos return ctf_set_errno (fp, ENOMEM);
1127 1.1.1.4 christos }
1128 1.1.1.4 christos
1129 1.1 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
1130 1.1 christos
1131 1.1 christos return 0;
1132 1.1 christos }
1133 1.1 christos
1134 1.1 christos int
1135 1.1.1.2 christos ctf_add_member_offset (ctf_dict_t *fp, ctf_id_t souid, const char *name,
1136 1.1 christos ctf_id_t type, unsigned long bit_offset)
1137 1.1 christos {
1138 1.1.1.3 christos ctf_dict_t *ofp = fp;
1139 1.1 christos ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, souid);
1140 1.1 christos
1141 1.1 christos ssize_t msize, malign, ssize;
1142 1.1 christos uint32_t kind, vlen, root;
1143 1.1.1.2 christos size_t i;
1144 1.1.1.2 christos int is_incomplete = 0;
1145 1.1.1.2 christos unsigned char *old_vlen;
1146 1.1.1.2 christos ctf_lmember_t *memb;
1147 1.1 christos
1148 1.1.1.3 christos if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, souid))
1149 1.1.1.3 christos {
1150 1.1.1.3 christos /* Adding a child type to a parent, even via the child, is prohibited.
1151 1.1.1.3 christos Otherwise, climb to the parent and do all work there. */
1152 1.1.1.3 christos
1153 1.1.1.3 christos if (LCTF_TYPE_ISCHILD (fp, type))
1154 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_BADID));
1155 1.1.1.3 christos
1156 1.1.1.3 christos fp = fp->ctf_parent;
1157 1.1.1.3 christos }
1158 1.1.1.3 christos
1159 1.1.1.3 christos if (souid < fp->ctf_stypes)
1160 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_RDONLY));
1161 1.1 christos
1162 1.1 christos if (dtd == NULL)
1163 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_BADID));
1164 1.1 christos
1165 1.1 christos if (name != NULL && name[0] == '\0')
1166 1.1 christos name = NULL;
1167 1.1 christos
1168 1.1 christos kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
1169 1.1 christos root = LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info);
1170 1.1 christos vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
1171 1.1 christos
1172 1.1 christos if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
1173 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_NOTSOU));
1174 1.1 christos
1175 1.1 christos if (vlen == CTF_MAX_VLEN)
1176 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_DTFULL));
1177 1.1 christos
1178 1.1.1.2 christos old_vlen = dtd->dtd_vlen;
1179 1.1.1.2 christos if (ctf_grow_vlen (fp, dtd, sizeof (ctf_lmember_t) * (vlen + 1)) < 0)
1180 1.1.1.3 christos return (ctf_set_errno (ofp, ctf_errno (fp)));
1181 1.1.1.2 christos memb = (ctf_lmember_t *) dtd->dtd_vlen;
1182 1.1.1.2 christos
1183 1.1.1.3 christos /* Remove pending refs in the old vlen region and reapply them. */
1184 1.1.1.2 christos
1185 1.1.1.3 christos ctf_str_move_refs (fp, old_vlen, sizeof (ctf_lmember_t) * vlen, dtd->dtd_vlen);
1186 1.1.1.2 christos
1187 1.1 christos if (name != NULL)
1188 1.1 christos {
1189 1.1.1.2 christos for (i = 0; i < vlen; i++)
1190 1.1.1.2 christos if (strcmp (ctf_strptr (fp, memb[i].ctlm_name), name) == 0)
1191 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_DUPLICATE));
1192 1.1 christos }
1193 1.1 christos
1194 1.1 christos if ((msize = ctf_type_size (fp, type)) < 0 ||
1195 1.1 christos (malign = ctf_type_align (fp, type)) < 0)
1196 1.1 christos {
1197 1.1 christos /* The unimplemented type, and any type that resolves to it, has no size
1198 1.1 christos and no alignment: it can correspond to any number of compiler-inserted
1199 1.1.1.2 christos types. We allow incomplete types through since they are routinely
1200 1.1.1.2 christos added to the ends of structures, and can even be added elsewhere in
1201 1.1.1.2 christos structures by the deduplicator. They are assumed to be zero-size with
1202 1.1.1.2 christos no alignment: this is often wrong, but problems can be avoided in this
1203 1.1.1.2 christos case by explicitly specifying the size of the structure via the _sized
1204 1.1.1.2 christos functions. The deduplicator always does this. */
1205 1.1 christos
1206 1.1.1.2 christos msize = 0;
1207 1.1.1.2 christos malign = 0;
1208 1.1 christos if (ctf_errno (fp) == ECTF_NONREPRESENTABLE)
1209 1.1.1.2 christos ctf_set_errno (fp, 0);
1210 1.1.1.2 christos else if (ctf_errno (fp) == ECTF_INCOMPLETE)
1211 1.1.1.2 christos is_incomplete = 1;
1212 1.1 christos else
1213 1.1 christos return -1; /* errno is set for us. */
1214 1.1 christos }
1215 1.1 christos
1216 1.1.1.3 christos memb[vlen].ctlm_name = ctf_str_add_movable_ref (fp, name, &memb[vlen].ctlm_name);
1217 1.1.1.2 christos memb[vlen].ctlm_type = type;
1218 1.1.1.2 christos if (memb[vlen].ctlm_name == 0 && name != NULL && name[0] != '\0')
1219 1.1.1.2 christos return -1; /* errno is set for us. */
1220 1.1 christos
1221 1.1 christos if (kind == CTF_K_STRUCT && vlen != 0)
1222 1.1 christos {
1223 1.1 christos if (bit_offset == (unsigned long) - 1)
1224 1.1 christos {
1225 1.1 christos /* Natural alignment. */
1226 1.1 christos
1227 1.1.1.2 christos ctf_id_t ltype = ctf_type_resolve (fp, memb[vlen - 1].ctlm_type);
1228 1.1.1.2 christos size_t off = CTF_LMEM_OFFSET(&memb[vlen - 1]);
1229 1.1 christos
1230 1.1 christos ctf_encoding_t linfo;
1231 1.1 christos ssize_t lsize;
1232 1.1 christos
1233 1.1 christos /* Propagate any error from ctf_type_resolve. If the last member was
1234 1.1 christos of unimplemented type, this may be -ECTF_NONREPRESENTABLE: we
1235 1.1 christos cannot insert right after such a member without explicit offset
1236 1.1 christos specification, because its alignment and size is not known. */
1237 1.1 christos if (ltype == CTF_ERR)
1238 1.1.1.2 christos return -1; /* errno is set for us. */
1239 1.1.1.2 christos
1240 1.1.1.2 christos if (is_incomplete)
1241 1.1 christos {
1242 1.1.1.3 christos ctf_err_warn (ofp, 1, ECTF_INCOMPLETE,
1243 1.1.1.2 christos _("ctf_add_member_offset: cannot add member %s of "
1244 1.1.1.2 christos "incomplete type %lx to struct %lx without "
1245 1.1.1.2 christos "specifying explicit offset\n"),
1246 1.1.1.2 christos name ? name : _("(unnamed member)"), type, souid);
1247 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_INCOMPLETE));
1248 1.1 christos }
1249 1.1 christos
1250 1.1 christos if (ctf_type_encoding (fp, ltype, &linfo) == 0)
1251 1.1 christos off += linfo.cte_bits;
1252 1.1 christos else if ((lsize = ctf_type_size (fp, ltype)) > 0)
1253 1.1 christos off += lsize * CHAR_BIT;
1254 1.1.1.2 christos else if (lsize == -1 && ctf_errno (fp) == ECTF_INCOMPLETE)
1255 1.1.1.2 christos {
1256 1.1.1.2 christos const char *lname = ctf_strraw (fp, memb[vlen - 1].ctlm_name);
1257 1.1.1.2 christos
1258 1.1.1.3 christos ctf_err_warn (ofp, 1, ECTF_INCOMPLETE,
1259 1.1.1.2 christos _("ctf_add_member_offset: cannot add member %s of "
1260 1.1.1.2 christos "type %lx to struct %lx without specifying "
1261 1.1.1.2 christos "explicit offset after member %s of type %lx, "
1262 1.1.1.2 christos "which is an incomplete type\n"),
1263 1.1.1.2 christos name ? name : _("(unnamed member)"), type, souid,
1264 1.1.1.2 christos lname ? lname : _("(unnamed member)"), ltype);
1265 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_INCOMPLETE));
1266 1.1.1.2 christos }
1267 1.1 christos
1268 1.1 christos /* Round up the offset of the end of the last member to
1269 1.1 christos the next byte boundary, convert 'off' to bytes, and
1270 1.1 christos then round it up again to the next multiple of the
1271 1.1 christos alignment required by the new member. Finally,
1272 1.1 christos convert back to bits and store the result in
1273 1.1 christos dmd_offset. Technically we could do more efficient
1274 1.1 christos packing if the new member is a bit-field, but we're
1275 1.1 christos the "compiler" and ANSI says we can do as we choose. */
1276 1.1 christos
1277 1.1 christos off = roundup (off, CHAR_BIT) / CHAR_BIT;
1278 1.1 christos off = roundup (off, MAX (malign, 1));
1279 1.1.1.2 christos memb[vlen].ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (off * CHAR_BIT);
1280 1.1.1.2 christos memb[vlen].ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (off * CHAR_BIT);
1281 1.1 christos ssize = off + msize;
1282 1.1 christos }
1283 1.1 christos else
1284 1.1 christos {
1285 1.1 christos /* Specified offset in bits. */
1286 1.1 christos
1287 1.1.1.2 christos memb[vlen].ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (bit_offset);
1288 1.1.1.2 christos memb[vlen].ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (bit_offset);
1289 1.1 christos ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
1290 1.1 christos ssize = MAX (ssize, ((signed) bit_offset / CHAR_BIT) + msize);
1291 1.1 christos }
1292 1.1 christos }
1293 1.1 christos else
1294 1.1 christos {
1295 1.1.1.2 christos memb[vlen].ctlm_offsethi = 0;
1296 1.1.1.2 christos memb[vlen].ctlm_offsetlo = 0;
1297 1.1 christos ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
1298 1.1 christos ssize = MAX (ssize, msize);
1299 1.1 christos }
1300 1.1 christos
1301 1.1.1.2 christos dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
1302 1.1.1.2 christos dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (ssize);
1303 1.1.1.2 christos dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (ssize);
1304 1.1 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
1305 1.1 christos
1306 1.1 christos return 0;
1307 1.1 christos }
1308 1.1 christos
1309 1.1 christos int
1310 1.1.1.2 christos ctf_add_member_encoded (ctf_dict_t *fp, ctf_id_t souid, const char *name,
1311 1.1 christos ctf_id_t type, unsigned long bit_offset,
1312 1.1 christos const ctf_encoding_t encoding)
1313 1.1 christos {
1314 1.1 christos ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, type);
1315 1.1.1.3 christos int kind;
1316 1.1 christos int otype = type;
1317 1.1 christos
1318 1.1.1.3 christos if (dtd == NULL)
1319 1.1.1.3 christos return (ctf_set_errno (fp, ECTF_BADID));
1320 1.1.1.3 christos
1321 1.1.1.3 christos kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
1322 1.1.1.3 christos
1323 1.1 christos if ((kind != CTF_K_INTEGER) && (kind != CTF_K_FLOAT) && (kind != CTF_K_ENUM))
1324 1.1 christos return (ctf_set_errno (fp, ECTF_NOTINTFP));
1325 1.1 christos
1326 1.1 christos if ((type = ctf_add_slice (fp, CTF_ADD_NONROOT, otype, &encoding)) == CTF_ERR)
1327 1.1 christos return -1; /* errno is set for us. */
1328 1.1 christos
1329 1.1 christos return ctf_add_member_offset (fp, souid, name, type, bit_offset);
1330 1.1 christos }
1331 1.1 christos
1332 1.1 christos int
1333 1.1.1.2 christos ctf_add_member (ctf_dict_t *fp, ctf_id_t souid, const char *name,
1334 1.1 christos ctf_id_t type)
1335 1.1 christos {
1336 1.1 christos return ctf_add_member_offset (fp, souid, name, type, (unsigned long) - 1);
1337 1.1 christos }
1338 1.1 christos
1339 1.1.1.3 christos /* Add a variable regardless of whether or not it is already present.
1340 1.1.1.3 christos
1341 1.1.1.3 christos Internal use only. */
1342 1.1 christos int
1343 1.1.1.3 christos ctf_add_variable_forced (ctf_dict_t *fp, const char *name, ctf_id_t ref)
1344 1.1 christos {
1345 1.1 christos ctf_dvdef_t *dvd;
1346 1.1.1.2 christos ctf_dict_t *tmp = fp;
1347 1.1 christos
1348 1.1 christos if (ctf_lookup_by_id (&tmp, ref) == NULL)
1349 1.1 christos return -1; /* errno is set for us. */
1350 1.1 christos
1351 1.1 christos /* Make sure this type is representable. */
1352 1.1 christos if ((ctf_type_resolve (fp, ref) == CTF_ERR)
1353 1.1 christos && (ctf_errno (fp) == ECTF_NONREPRESENTABLE))
1354 1.1 christos return -1;
1355 1.1 christos
1356 1.1 christos if ((dvd = malloc (sizeof (ctf_dvdef_t))) == NULL)
1357 1.1 christos return (ctf_set_errno (fp, EAGAIN));
1358 1.1 christos
1359 1.1 christos if (name != NULL && (dvd->dvd_name = strdup (name)) == NULL)
1360 1.1 christos {
1361 1.1 christos free (dvd);
1362 1.1 christos return (ctf_set_errno (fp, EAGAIN));
1363 1.1 christos }
1364 1.1 christos dvd->dvd_type = ref;
1365 1.1 christos dvd->dvd_snapshots = fp->ctf_snapshots;
1366 1.1 christos
1367 1.1 christos if (ctf_dvd_insert (fp, dvd) < 0)
1368 1.1 christos {
1369 1.1 christos free (dvd->dvd_name);
1370 1.1 christos free (dvd);
1371 1.1 christos return -1; /* errno is set for us. */
1372 1.1 christos }
1373 1.1 christos
1374 1.1 christos return 0;
1375 1.1 christos }
1376 1.1 christos
1377 1.1.1.2 christos int
1378 1.1.1.3 christos ctf_add_variable (ctf_dict_t *fp, const char *name, ctf_id_t ref)
1379 1.1.1.3 christos {
1380 1.1.1.3 christos if (ctf_lookup_variable_here (fp, name) != CTF_ERR)
1381 1.1.1.3 christos return (ctf_set_errno (fp, ECTF_DUPLICATE));
1382 1.1.1.3 christos
1383 1.1.1.3 christos if (ctf_errno (fp) != ECTF_NOTYPEDAT)
1384 1.1.1.3 christos return -1; /* errno is set for us. */
1385 1.1.1.3 christos
1386 1.1.1.3 christos return ctf_add_variable_forced (fp, name, ref);
1387 1.1.1.3 christos }
1388 1.1.1.3 christos
1389 1.1.1.3 christos /* Add a function or object symbol regardless of whether or not it is already
1390 1.1.1.3 christos present (already existing symbols are silently overwritten).
1391 1.1.1.3 christos
1392 1.1.1.3 christos Internal use only. */
1393 1.1.1.3 christos int
1394 1.1.1.3 christos ctf_add_funcobjt_sym_forced (ctf_dict_t *fp, int is_function, const char *name, ctf_id_t id)
1395 1.1.1.2 christos {
1396 1.1.1.2 christos ctf_dict_t *tmp = fp;
1397 1.1.1.2 christos char *dupname;
1398 1.1.1.2 christos ctf_dynhash_t *h = is_function ? fp->ctf_funchash : fp->ctf_objthash;
1399 1.1.1.2 christos
1400 1.1.1.2 christos if (ctf_lookup_by_id (&tmp, id) == NULL)
1401 1.1.1.3 christos return -1; /* errno is set for us. */
1402 1.1.1.2 christos
1403 1.1.1.2 christos if (is_function && ctf_type_kind (fp, id) != CTF_K_FUNCTION)
1404 1.1.1.2 christos return (ctf_set_errno (fp, ECTF_NOTFUNC));
1405 1.1.1.2 christos
1406 1.1.1.2 christos if ((dupname = strdup (name)) == NULL)
1407 1.1.1.2 christos return (ctf_set_errno (fp, ENOMEM));
1408 1.1.1.2 christos
1409 1.1.1.2 christos if (ctf_dynhash_insert (h, dupname, (void *) (uintptr_t) id) < 0)
1410 1.1.1.2 christos {
1411 1.1.1.2 christos free (dupname);
1412 1.1.1.2 christos return (ctf_set_errno (fp, ENOMEM));
1413 1.1.1.2 christos }
1414 1.1.1.2 christos return 0;
1415 1.1.1.2 christos }
1416 1.1.1.2 christos
1417 1.1.1.2 christos int
1418 1.1.1.3 christos ctf_add_funcobjt_sym (ctf_dict_t *fp, int is_function, const char *name, ctf_id_t id)
1419 1.1.1.3 christos {
1420 1.1.1.3 christos if (ctf_lookup_by_sym_or_name (fp, 0, name, 0, is_function) != CTF_ERR)
1421 1.1.1.3 christos return (ctf_set_errno (fp, ECTF_DUPLICATE));
1422 1.1.1.3 christos
1423 1.1.1.3 christos return ctf_add_funcobjt_sym_forced (fp, is_function, name, id);
1424 1.1.1.3 christos }
1425 1.1.1.3 christos
1426 1.1.1.3 christos int
1427 1.1.1.2 christos ctf_add_objt_sym (ctf_dict_t *fp, const char *name, ctf_id_t id)
1428 1.1.1.2 christos {
1429 1.1.1.2 christos return (ctf_add_funcobjt_sym (fp, 0, name, id));
1430 1.1.1.2 christos }
1431 1.1.1.2 christos
1432 1.1.1.2 christos int
1433 1.1.1.2 christos ctf_add_func_sym (ctf_dict_t *fp, const char *name, ctf_id_t id)
1434 1.1.1.2 christos {
1435 1.1.1.2 christos return (ctf_add_funcobjt_sym (fp, 1, name, id));
1436 1.1.1.2 christos }
1437 1.1.1.2 christos
1438 1.1.1.4 christos /* Add an enumeration constant observed in a given enum type as an identifier.
1439 1.1.1.4 christos They appear as names that cite the enum type.
1440 1.1.1.4 christos
1441 1.1.1.4 christos Constants that appear in more than one enum, or which are already the names
1442 1.1.1.4 christos of types, appear in ctf_conflicting_enums as well.
1443 1.1.1.4 christos
1444 1.1.1.4 christos This is done for all enumeration types at open time, and for newly-added ones
1445 1.1.1.4 christos as well: if the strict-enum flag is turned on, this table must be kept up to
1446 1.1.1.4 christos date with enums added in the interim. */
1447 1.1.1.4 christos
1448 1.1.1.4 christos int
1449 1.1.1.4 christos ctf_track_enumerator (ctf_dict_t *fp, ctf_id_t type, const char *cte_name)
1450 1.1.1.4 christos {
1451 1.1.1.4 christos int err;
1452 1.1.1.4 christos
1453 1.1.1.4 christos if (ctf_dynhash_lookup_type (fp->ctf_names, cte_name) == 0)
1454 1.1.1.4 christos {
1455 1.1.1.4 christos uint32_t name = ctf_str_add (fp, cte_name);
1456 1.1.1.4 christos
1457 1.1.1.4 christos if (name == 0)
1458 1.1.1.4 christos return -1; /* errno is set for us. */
1459 1.1.1.4 christos
1460 1.1.1.4 christos err = ctf_dynhash_insert_type (fp, fp->ctf_names, type, name);
1461 1.1.1.4 christos }
1462 1.1.1.4 christos else
1463 1.1.1.4 christos {
1464 1.1.1.4 christos err = ctf_dynset_insert (fp->ctf_conflicting_enums, (void *)
1465 1.1.1.4 christos cte_name);
1466 1.1.1.4 christos if (err != 0)
1467 1.1.1.4 christos ctf_set_errno (fp, err * -1);
1468 1.1.1.4 christos }
1469 1.1.1.4 christos if (err != 0)
1470 1.1.1.4 christos return -1; /* errno is set for us. */
1471 1.1.1.4 christos return 0;
1472 1.1.1.4 christos }
1473 1.1.1.4 christos
1474 1.1 christos typedef struct ctf_bundle
1475 1.1 christos {
1476 1.1.1.2 christos ctf_dict_t *ctb_dict; /* CTF dict handle. */
1477 1.1 christos ctf_id_t ctb_type; /* CTF type identifier. */
1478 1.1 christos ctf_dtdef_t *ctb_dtd; /* CTF dynamic type definition (if any). */
1479 1.1 christos } ctf_bundle_t;
1480 1.1 christos
1481 1.1 christos static int
1482 1.1 christos enumcmp (const char *name, int value, void *arg)
1483 1.1 christos {
1484 1.1 christos ctf_bundle_t *ctb = arg;
1485 1.1 christos int bvalue;
1486 1.1 christos
1487 1.1.1.2 christos if (ctf_enum_value (ctb->ctb_dict, ctb->ctb_type, name, &bvalue) < 0)
1488 1.1 christos {
1489 1.1.1.2 christos ctf_err_warn (ctb->ctb_dict, 0, 0,
1490 1.1 christos _("conflict due to enum %s iteration error"), name);
1491 1.1 christos return 1;
1492 1.1 christos }
1493 1.1 christos if (value != bvalue)
1494 1.1 christos {
1495 1.1.1.2 christos ctf_err_warn (ctb->ctb_dict, 1, ECTF_CONFLICT,
1496 1.1 christos _("conflict due to enum value change: %i versus %i"),
1497 1.1 christos value, bvalue);
1498 1.1 christos return 1;
1499 1.1 christos }
1500 1.1 christos return 0;
1501 1.1 christos }
1502 1.1 christos
1503 1.1 christos static int
1504 1.1 christos enumadd (const char *name, int value, void *arg)
1505 1.1 christos {
1506 1.1 christos ctf_bundle_t *ctb = arg;
1507 1.1 christos
1508 1.1.1.2 christos return (ctf_add_enumerator (ctb->ctb_dict, ctb->ctb_type,
1509 1.1 christos name, value) < 0);
1510 1.1 christos }
1511 1.1 christos
1512 1.1 christos static int
1513 1.1 christos membcmp (const char *name, ctf_id_t type _libctf_unused_, unsigned long offset,
1514 1.1 christos void *arg)
1515 1.1 christos {
1516 1.1 christos ctf_bundle_t *ctb = arg;
1517 1.1 christos ctf_membinfo_t ctm;
1518 1.1 christos
1519 1.1 christos /* Don't check nameless members (e.g. anonymous structs/unions) against each
1520 1.1 christos other. */
1521 1.1 christos if (name[0] == 0)
1522 1.1 christos return 0;
1523 1.1 christos
1524 1.1.1.2 christos if (ctf_member_info (ctb->ctb_dict, ctb->ctb_type, name, &ctm) < 0)
1525 1.1 christos {
1526 1.1.1.2 christos ctf_err_warn (ctb->ctb_dict, 0, 0,
1527 1.1 christos _("conflict due to struct member %s iteration error"),
1528 1.1 christos name);
1529 1.1 christos return 1;
1530 1.1 christos }
1531 1.1 christos if (ctm.ctm_offset != offset)
1532 1.1 christos {
1533 1.1.1.2 christos ctf_err_warn (ctb->ctb_dict, 1, ECTF_CONFLICT,
1534 1.1 christos _("conflict due to struct member %s offset change: "
1535 1.1 christos "%lx versus %lx"),
1536 1.1 christos name, ctm.ctm_offset, offset);
1537 1.1 christos return 1;
1538 1.1 christos }
1539 1.1 christos return 0;
1540 1.1 christos }
1541 1.1 christos
1542 1.1.1.2 christos /* Record the correspondence between a source and ctf_add_type()-added
1543 1.1.1.2 christos destination type: both types are translated into parent type IDs if need be,
1544 1.1.1.2 christos so they relate to the actual dictionary they are in. Outside controlled
1545 1.1.1.2 christos circumstances (like linking) it is probably not useful to do more than
1546 1.1.1.2 christos compare these pointers, since there is nothing stopping the user closing the
1547 1.1.1.2 christos source dict whenever they want to.
1548 1.1.1.2 christos
1549 1.1.1.2 christos Our OOM handling here is just to not do anything, because this is called deep
1550 1.1.1.2 christos enough in the call stack that doing anything useful is painfully difficult:
1551 1.1.1.2 christos the worst consequence if we do OOM is a bit of type duplication anyway. */
1552 1.1.1.2 christos
1553 1.1.1.2 christos static void
1554 1.1.1.2 christos ctf_add_type_mapping (ctf_dict_t *src_fp, ctf_id_t src_type,
1555 1.1.1.2 christos ctf_dict_t *dst_fp, ctf_id_t dst_type)
1556 1.1 christos {
1557 1.1.1.2 christos if (LCTF_TYPE_ISPARENT (src_fp, src_type) && src_fp->ctf_parent)
1558 1.1.1.2 christos src_fp = src_fp->ctf_parent;
1559 1.1 christos
1560 1.1.1.2 christos src_type = LCTF_TYPE_TO_INDEX(src_fp, src_type);
1561 1.1 christos
1562 1.1.1.2 christos if (LCTF_TYPE_ISPARENT (dst_fp, dst_type) && dst_fp->ctf_parent)
1563 1.1.1.2 christos dst_fp = dst_fp->ctf_parent;
1564 1.1.1.2 christos
1565 1.1.1.2 christos dst_type = LCTF_TYPE_TO_INDEX(dst_fp, dst_type);
1566 1.1.1.2 christos
1567 1.1.1.2 christos if (dst_fp->ctf_link_type_mapping == NULL)
1568 1.1 christos {
1569 1.1.1.2 christos ctf_hash_fun f = ctf_hash_type_key;
1570 1.1.1.2 christos ctf_hash_eq_fun e = ctf_hash_eq_type_key;
1571 1.1.1.2 christos
1572 1.1.1.2 christos if ((dst_fp->ctf_link_type_mapping = ctf_dynhash_create (f, e, free,
1573 1.1.1.2 christos NULL)) == NULL)
1574 1.1.1.2 christos return;
1575 1.1 christos }
1576 1.1 christos
1577 1.1.1.2 christos ctf_link_type_key_t *key;
1578 1.1.1.2 christos key = calloc (1, sizeof (struct ctf_link_type_key));
1579 1.1.1.2 christos if (!key)
1580 1.1.1.2 christos return;
1581 1.1 christos
1582 1.1.1.2 christos key->cltk_fp = src_fp;
1583 1.1.1.2 christos key->cltk_idx = src_type;
1584 1.1 christos
1585 1.1.1.2 christos /* No OOM checking needed, because if this doesn't work the worst we'll do is
1586 1.1.1.2 christos add a few more duplicate types (which will probably run out of memory
1587 1.1.1.2 christos anyway). */
1588 1.1.1.2 christos ctf_dynhash_insert (dst_fp->ctf_link_type_mapping, key,
1589 1.1.1.2 christos (void *) (uintptr_t) dst_type);
1590 1.1 christos }
1591 1.1 christos
1592 1.1.1.2 christos /* Look up a type mapping: return 0 if none. The DST_FP is modified to point to
1593 1.1.1.2 christos the parent if need be. The ID returned is from the dst_fp's perspective. */
1594 1.1.1.2 christos static ctf_id_t
1595 1.1.1.2 christos ctf_type_mapping (ctf_dict_t *src_fp, ctf_id_t src_type, ctf_dict_t **dst_fp)
1596 1.1.1.2 christos {
1597 1.1.1.2 christos ctf_link_type_key_t key;
1598 1.1.1.2 christos ctf_dict_t *target_fp = *dst_fp;
1599 1.1.1.2 christos ctf_id_t dst_type = 0;
1600 1.1.1.2 christos
1601 1.1.1.2 christos if (LCTF_TYPE_ISPARENT (src_fp, src_type) && src_fp->ctf_parent)
1602 1.1.1.2 christos src_fp = src_fp->ctf_parent;
1603 1.1.1.2 christos
1604 1.1.1.2 christos src_type = LCTF_TYPE_TO_INDEX(src_fp, src_type);
1605 1.1.1.2 christos key.cltk_fp = src_fp;
1606 1.1.1.2 christos key.cltk_idx = src_type;
1607 1.1.1.2 christos
1608 1.1.1.2 christos if (target_fp->ctf_link_type_mapping)
1609 1.1.1.2 christos dst_type = (uintptr_t) ctf_dynhash_lookup (target_fp->ctf_link_type_mapping,
1610 1.1.1.2 christos &key);
1611 1.1.1.2 christos
1612 1.1.1.2 christos if (dst_type != 0)
1613 1.1.1.2 christos {
1614 1.1.1.2 christos dst_type = LCTF_INDEX_TO_TYPE (target_fp, dst_type,
1615 1.1.1.2 christos target_fp->ctf_parent != NULL);
1616 1.1.1.2 christos *dst_fp = target_fp;
1617 1.1.1.2 christos return dst_type;
1618 1.1.1.2 christos }
1619 1.1.1.2 christos
1620 1.1.1.2 christos if (target_fp->ctf_parent)
1621 1.1.1.2 christos target_fp = target_fp->ctf_parent;
1622 1.1.1.2 christos else
1623 1.1.1.2 christos return 0;
1624 1.1.1.2 christos
1625 1.1.1.2 christos if (target_fp->ctf_link_type_mapping)
1626 1.1.1.2 christos dst_type = (uintptr_t) ctf_dynhash_lookup (target_fp->ctf_link_type_mapping,
1627 1.1.1.2 christos &key);
1628 1.1.1.2 christos
1629 1.1.1.2 christos if (dst_type)
1630 1.1.1.2 christos dst_type = LCTF_INDEX_TO_TYPE (target_fp, dst_type,
1631 1.1.1.2 christos target_fp->ctf_parent != NULL);
1632 1.1.1.2 christos
1633 1.1.1.2 christos *dst_fp = target_fp;
1634 1.1.1.2 christos return dst_type;
1635 1.1.1.2 christos }
1636 1.1.1.2 christos
1637 1.1.1.2 christos /* The ctf_add_type routine is used to copy a type from a source CTF dictionary
1638 1.1.1.2 christos to a dynamic destination dictionary. This routine operates recursively by
1639 1.1 christos following the source type's links and embedded member types. If the
1640 1.1.1.2 christos destination dict already contains a named type which has the same attributes,
1641 1.1.1.2 christos then we succeed and return this type but no changes occur. */
1642 1.1 christos static ctf_id_t
1643 1.1.1.2 christos ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type,
1644 1.1.1.2 christos ctf_dict_t *proc_tracking_fp)
1645 1.1 christos {
1646 1.1 christos ctf_id_t dst_type = CTF_ERR;
1647 1.1 christos uint32_t dst_kind = CTF_K_UNKNOWN;
1648 1.1.1.2 christos ctf_dict_t *tmp_fp = dst_fp;
1649 1.1 christos ctf_id_t tmp;
1650 1.1 christos
1651 1.1 christos const char *name;
1652 1.1 christos uint32_t kind, forward_kind, flag, vlen;
1653 1.1 christos
1654 1.1 christos const ctf_type_t *src_tp, *dst_tp;
1655 1.1 christos ctf_bundle_t src, dst;
1656 1.1 christos ctf_encoding_t src_en, dst_en;
1657 1.1 christos ctf_arinfo_t src_ar, dst_ar;
1658 1.1 christos
1659 1.1 christos ctf_funcinfo_t ctc;
1660 1.1 christos
1661 1.1 christos ctf_id_t orig_src_type = src_type;
1662 1.1 christos
1663 1.1 christos if ((src_tp = ctf_lookup_by_id (&src_fp, src_type)) == NULL)
1664 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ctf_errno (src_fp)));
1665 1.1 christos
1666 1.1 christos if ((ctf_type_resolve (src_fp, src_type) == CTF_ERR)
1667 1.1 christos && (ctf_errno (src_fp) == ECTF_NONREPRESENTABLE))
1668 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_NONREPRESENTABLE));
1669 1.1 christos
1670 1.1 christos name = ctf_strptr (src_fp, src_tp->ctt_name);
1671 1.1 christos kind = LCTF_INFO_KIND (src_fp, src_tp->ctt_info);
1672 1.1 christos flag = LCTF_INFO_ISROOT (src_fp, src_tp->ctt_info);
1673 1.1 christos vlen = LCTF_INFO_VLEN (src_fp, src_tp->ctt_info);
1674 1.1 christos
1675 1.1 christos /* If this is a type we are currently in the middle of adding, hand it
1676 1.1 christos straight back. (This lets us handle self-referential structures without
1677 1.1 christos considering forwards and empty structures the same as their completed
1678 1.1 christos forms.) */
1679 1.1 christos
1680 1.1 christos tmp = ctf_type_mapping (src_fp, src_type, &tmp_fp);
1681 1.1 christos
1682 1.1 christos if (tmp != 0)
1683 1.1 christos {
1684 1.1 christos if (ctf_dynhash_lookup (proc_tracking_fp->ctf_add_processing,
1685 1.1 christos (void *) (uintptr_t) src_type))
1686 1.1 christos return tmp;
1687 1.1 christos
1688 1.1.1.2 christos /* If this type has already been added from this dictionary, and is the
1689 1.1.1.2 christos same kind and (if a struct or union) has the same number of members,
1690 1.1.1.2 christos hand it straight back. */
1691 1.1 christos
1692 1.1 christos if (ctf_type_kind_unsliced (tmp_fp, tmp) == (int) kind)
1693 1.1 christos {
1694 1.1 christos if (kind == CTF_K_STRUCT || kind == CTF_K_UNION
1695 1.1 christos || kind == CTF_K_ENUM)
1696 1.1 christos {
1697 1.1 christos if ((dst_tp = ctf_lookup_by_id (&tmp_fp, dst_type)) != NULL)
1698 1.1 christos if (vlen == LCTF_INFO_VLEN (tmp_fp, dst_tp->ctt_info))
1699 1.1 christos return tmp;
1700 1.1 christos }
1701 1.1 christos else
1702 1.1 christos return tmp;
1703 1.1 christos }
1704 1.1 christos }
1705 1.1 christos
1706 1.1 christos forward_kind = kind;
1707 1.1 christos if (kind == CTF_K_FORWARD)
1708 1.1 christos forward_kind = src_tp->ctt_type;
1709 1.1 christos
1710 1.1.1.2 christos /* If the source type has a name and is a root type (visible at the top-level
1711 1.1.1.2 christos scope), lookup the name in the destination dictionary and verify that it is
1712 1.1.1.2 christos of the same kind before we do anything else. */
1713 1.1 christos
1714 1.1 christos if ((flag & CTF_ADD_ROOT) && name[0] != '\0'
1715 1.1 christos && (tmp = ctf_lookup_by_rawname (dst_fp, forward_kind, name)) != 0)
1716 1.1 christos {
1717 1.1 christos dst_type = tmp;
1718 1.1 christos dst_kind = ctf_type_kind_unsliced (dst_fp, dst_type);
1719 1.1 christos }
1720 1.1 christos
1721 1.1 christos /* If an identically named dst_type exists, fail with ECTF_CONFLICT
1722 1.1 christos unless dst_type is a forward declaration and src_type is a struct,
1723 1.1 christos union, or enum (i.e. the definition of the previous forward decl).
1724 1.1 christos
1725 1.1 christos We also allow addition in the opposite order (addition of a forward when a
1726 1.1 christos struct, union, or enum already exists), which is a NOP and returns the
1727 1.1 christos already-present struct, union, or enum. */
1728 1.1 christos
1729 1.1 christos if (dst_type != CTF_ERR && dst_kind != kind)
1730 1.1 christos {
1731 1.1 christos if (kind == CTF_K_FORWARD
1732 1.1 christos && (dst_kind == CTF_K_ENUM || dst_kind == CTF_K_STRUCT
1733 1.1 christos || dst_kind == CTF_K_UNION))
1734 1.1 christos {
1735 1.1 christos ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
1736 1.1 christos return dst_type;
1737 1.1 christos }
1738 1.1 christos
1739 1.1 christos if (dst_kind != CTF_K_FORWARD
1740 1.1 christos || (kind != CTF_K_ENUM && kind != CTF_K_STRUCT
1741 1.1 christos && kind != CTF_K_UNION))
1742 1.1 christos {
1743 1.1 christos ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
1744 1.1.1.2 christos _("ctf_add_type: conflict for type %s: "
1745 1.1 christos "kinds differ, new: %i; old (ID %lx): %i"),
1746 1.1 christos name, kind, dst_type, dst_kind);
1747 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
1748 1.1 christos }
1749 1.1 christos }
1750 1.1 christos
1751 1.1 christos /* We take special action for an integer, float, or slice since it is
1752 1.1 christos described not only by its name but also its encoding. For integers,
1753 1.1 christos bit-fields exploit this degeneracy. */
1754 1.1 christos
1755 1.1 christos if (kind == CTF_K_INTEGER || kind == CTF_K_FLOAT || kind == CTF_K_SLICE)
1756 1.1 christos {
1757 1.1 christos if (ctf_type_encoding (src_fp, src_type, &src_en) != 0)
1758 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ctf_errno (src_fp)));
1759 1.1 christos
1760 1.1 christos if (dst_type != CTF_ERR)
1761 1.1 christos {
1762 1.1.1.2 christos ctf_dict_t *fp = dst_fp;
1763 1.1 christos
1764 1.1 christos if ((dst_tp = ctf_lookup_by_id (&fp, dst_type)) == NULL)
1765 1.1 christos return CTF_ERR;
1766 1.1 christos
1767 1.1 christos if (ctf_type_encoding (dst_fp, dst_type, &dst_en) != 0)
1768 1.1 christos return CTF_ERR; /* errno set for us. */
1769 1.1 christos
1770 1.1 christos if (LCTF_INFO_ISROOT (fp, dst_tp->ctt_info) & CTF_ADD_ROOT)
1771 1.1 christos {
1772 1.1 christos /* The type that we found in the hash is also root-visible. If
1773 1.1 christos the two types match then use the existing one; otherwise,
1774 1.1 christos declare a conflict. Note: slices are not certain to match
1775 1.1 christos even if there is no conflict: we must check the contained type
1776 1.1 christos too. */
1777 1.1 christos
1778 1.1 christos if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0)
1779 1.1 christos {
1780 1.1 christos if (kind != CTF_K_SLICE)
1781 1.1 christos {
1782 1.1 christos ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
1783 1.1 christos return dst_type;
1784 1.1 christos }
1785 1.1 christos }
1786 1.1 christos else
1787 1.1 christos {
1788 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
1789 1.1 christos }
1790 1.1 christos }
1791 1.1 christos else
1792 1.1 christos {
1793 1.1 christos /* We found a non-root-visible type in the hash. If its encoding
1794 1.1 christos is the same, we can reuse it, unless it is a slice. */
1795 1.1 christos
1796 1.1 christos if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0)
1797 1.1 christos {
1798 1.1 christos if (kind != CTF_K_SLICE)
1799 1.1 christos {
1800 1.1 christos ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
1801 1.1 christos return dst_type;
1802 1.1 christos }
1803 1.1 christos }
1804 1.1 christos }
1805 1.1 christos }
1806 1.1 christos }
1807 1.1 christos
1808 1.1.1.2 christos src.ctb_dict = src_fp;
1809 1.1 christos src.ctb_type = src_type;
1810 1.1 christos src.ctb_dtd = NULL;
1811 1.1 christos
1812 1.1.1.2 christos dst.ctb_dict = dst_fp;
1813 1.1 christos dst.ctb_type = dst_type;
1814 1.1 christos dst.ctb_dtd = NULL;
1815 1.1 christos
1816 1.1 christos /* Now perform kind-specific processing. If dst_type is CTF_ERR, then we add
1817 1.1 christos a new type with the same properties as src_type to dst_fp. If dst_type is
1818 1.1 christos not CTF_ERR, then we verify that dst_type has the same attributes as
1819 1.1 christos src_type. We recurse for embedded references. Before we start, we note
1820 1.1 christos that we are processing this type, to prevent infinite recursion: we do not
1821 1.1 christos re-process any type that appears in this list. The list is emptied
1822 1.1 christos wholesale at the end of processing everything in this recursive stack. */
1823 1.1 christos
1824 1.1 christos if (ctf_dynhash_insert (proc_tracking_fp->ctf_add_processing,
1825 1.1 christos (void *) (uintptr_t) src_type, (void *) 1) < 0)
1826 1.1.1.3 christos return ctf_set_typed_errno (dst_fp, ENOMEM);
1827 1.1 christos
1828 1.1 christos switch (kind)
1829 1.1 christos {
1830 1.1 christos case CTF_K_INTEGER:
1831 1.1 christos /* If we found a match we will have either returned it or declared a
1832 1.1 christos conflict. */
1833 1.1 christos dst_type = ctf_add_integer (dst_fp, flag, name, &src_en);
1834 1.1 christos break;
1835 1.1 christos
1836 1.1 christos case CTF_K_FLOAT:
1837 1.1 christos /* If we found a match we will have either returned it or declared a
1838 1.1 christos conflict. */
1839 1.1 christos dst_type = ctf_add_float (dst_fp, flag, name, &src_en);
1840 1.1 christos break;
1841 1.1 christos
1842 1.1 christos case CTF_K_SLICE:
1843 1.1 christos /* We have checked for conflicting encodings: now try to add the
1844 1.1 christos contained type. */
1845 1.1 christos src_type = ctf_type_reference (src_fp, src_type);
1846 1.1 christos src_type = ctf_add_type_internal (dst_fp, src_fp, src_type,
1847 1.1 christos proc_tracking_fp);
1848 1.1 christos
1849 1.1 christos if (src_type == CTF_ERR)
1850 1.1 christos return CTF_ERR; /* errno is set for us. */
1851 1.1 christos
1852 1.1 christos dst_type = ctf_add_slice (dst_fp, flag, src_type, &src_en);
1853 1.1 christos break;
1854 1.1 christos
1855 1.1 christos case CTF_K_POINTER:
1856 1.1 christos case CTF_K_VOLATILE:
1857 1.1 christos case CTF_K_CONST:
1858 1.1 christos case CTF_K_RESTRICT:
1859 1.1 christos src_type = ctf_type_reference (src_fp, src_type);
1860 1.1 christos src_type = ctf_add_type_internal (dst_fp, src_fp, src_type,
1861 1.1 christos proc_tracking_fp);
1862 1.1 christos
1863 1.1 christos if (src_type == CTF_ERR)
1864 1.1 christos return CTF_ERR; /* errno is set for us. */
1865 1.1 christos
1866 1.1 christos dst_type = ctf_add_reftype (dst_fp, flag, src_type, kind);
1867 1.1 christos break;
1868 1.1 christos
1869 1.1 christos case CTF_K_ARRAY:
1870 1.1 christos if (ctf_array_info (src_fp, src_type, &src_ar) != 0)
1871 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ctf_errno (src_fp)));
1872 1.1 christos
1873 1.1 christos src_ar.ctr_contents =
1874 1.1 christos ctf_add_type_internal (dst_fp, src_fp, src_ar.ctr_contents,
1875 1.1 christos proc_tracking_fp);
1876 1.1 christos src_ar.ctr_index = ctf_add_type_internal (dst_fp, src_fp,
1877 1.1 christos src_ar.ctr_index,
1878 1.1 christos proc_tracking_fp);
1879 1.1 christos src_ar.ctr_nelems = src_ar.ctr_nelems;
1880 1.1 christos
1881 1.1 christos if (src_ar.ctr_contents == CTF_ERR || src_ar.ctr_index == CTF_ERR)
1882 1.1 christos return CTF_ERR; /* errno is set for us. */
1883 1.1 christos
1884 1.1 christos if (dst_type != CTF_ERR)
1885 1.1 christos {
1886 1.1 christos if (ctf_array_info (dst_fp, dst_type, &dst_ar) != 0)
1887 1.1 christos return CTF_ERR; /* errno is set for us. */
1888 1.1 christos
1889 1.1 christos if (memcmp (&src_ar, &dst_ar, sizeof (ctf_arinfo_t)))
1890 1.1 christos {
1891 1.1 christos ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
1892 1.1 christos _("conflict for type %s against ID %lx: array info "
1893 1.1 christos "differs, old %lx/%lx/%x; new: %lx/%lx/%x"),
1894 1.1 christos name, dst_type, src_ar.ctr_contents,
1895 1.1 christos src_ar.ctr_index, src_ar.ctr_nelems,
1896 1.1 christos dst_ar.ctr_contents, dst_ar.ctr_index,
1897 1.1 christos dst_ar.ctr_nelems);
1898 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
1899 1.1 christos }
1900 1.1 christos }
1901 1.1 christos else
1902 1.1 christos dst_type = ctf_add_array (dst_fp, flag, &src_ar);
1903 1.1 christos break;
1904 1.1 christos
1905 1.1 christos case CTF_K_FUNCTION:
1906 1.1 christos ctc.ctc_return = ctf_add_type_internal (dst_fp, src_fp,
1907 1.1 christos src_tp->ctt_type,
1908 1.1 christos proc_tracking_fp);
1909 1.1 christos ctc.ctc_argc = 0;
1910 1.1 christos ctc.ctc_flags = 0;
1911 1.1 christos
1912 1.1 christos if (ctc.ctc_return == CTF_ERR)
1913 1.1 christos return CTF_ERR; /* errno is set for us. */
1914 1.1 christos
1915 1.1 christos dst_type = ctf_add_function (dst_fp, flag, &ctc, NULL);
1916 1.1 christos break;
1917 1.1 christos
1918 1.1 christos case CTF_K_STRUCT:
1919 1.1 christos case CTF_K_UNION:
1920 1.1 christos {
1921 1.1.1.2 christos ctf_next_t *i = NULL;
1922 1.1.1.2 christos ssize_t offset;
1923 1.1.1.2 christos const char *membname;
1924 1.1.1.2 christos ctf_id_t src_membtype;
1925 1.1 christos
1926 1.1 christos /* Technically to match a struct or union we need to check both
1927 1.1 christos ways (src members vs. dst, dst members vs. src) but we make
1928 1.1 christos this more optimal by only checking src vs. dst and comparing
1929 1.1 christos the total size of the structure (which we must do anyway)
1930 1.1 christos which covers the possibility of dst members not in src.
1931 1.1 christos This optimization can be defeated for unions, but is so
1932 1.1 christos pathological as to render it irrelevant for our purposes. */
1933 1.1 christos
1934 1.1 christos if (dst_type != CTF_ERR && kind != CTF_K_FORWARD
1935 1.1 christos && dst_kind != CTF_K_FORWARD)
1936 1.1 christos {
1937 1.1 christos if (ctf_type_size (src_fp, src_type) !=
1938 1.1 christos ctf_type_size (dst_fp, dst_type))
1939 1.1 christos {
1940 1.1 christos ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
1941 1.1 christos _("conflict for type %s against ID %lx: union "
1942 1.1 christos "size differs, old %li, new %li"), name,
1943 1.1 christos dst_type, (long) ctf_type_size (src_fp, src_type),
1944 1.1 christos (long) ctf_type_size (dst_fp, dst_type));
1945 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
1946 1.1 christos }
1947 1.1 christos
1948 1.1 christos if (ctf_member_iter (src_fp, src_type, membcmp, &dst))
1949 1.1 christos {
1950 1.1 christos ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
1951 1.1 christos _("conflict for type %s against ID %lx: members "
1952 1.1 christos "differ, see above"), name, dst_type);
1953 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
1954 1.1 christos }
1955 1.1 christos
1956 1.1 christos break;
1957 1.1 christos }
1958 1.1 christos
1959 1.1.1.2 christos dst_type = ctf_add_struct_sized (dst_fp, flag, name,
1960 1.1.1.2 christos ctf_type_size (src_fp, src_type));
1961 1.1 christos if (dst_type == CTF_ERR)
1962 1.1 christos return CTF_ERR; /* errno is set for us. */
1963 1.1 christos
1964 1.1 christos /* Pre-emptively add this struct to the type mapping so that
1965 1.1 christos structures that refer to themselves work. */
1966 1.1 christos ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
1967 1.1 christos
1968 1.1.1.2 christos while ((offset = ctf_member_next (src_fp, src_type, &i, &membname,
1969 1.1.1.2 christos &src_membtype, 0)) >= 0)
1970 1.1 christos {
1971 1.1.1.2 christos ctf_dict_t *dst = dst_fp;
1972 1.1.1.2 christos ctf_id_t dst_membtype = ctf_type_mapping (src_fp, src_membtype, &dst);
1973 1.1 christos
1974 1.1.1.2 christos if (dst_membtype == 0)
1975 1.1 christos {
1976 1.1.1.2 christos dst_membtype = ctf_add_type_internal (dst_fp, src_fp,
1977 1.1.1.2 christos src_membtype,
1978 1.1.1.2 christos proc_tracking_fp);
1979 1.1.1.2 christos if (dst_membtype == CTF_ERR)
1980 1.1 christos {
1981 1.1 christos if (ctf_errno (dst_fp) != ECTF_NONREPRESENTABLE)
1982 1.1.1.2 christos {
1983 1.1.1.2 christos ctf_next_destroy (i);
1984 1.1.1.2 christos break;
1985 1.1.1.2 christos }
1986 1.1 christos }
1987 1.1 christos }
1988 1.1 christos
1989 1.1.1.2 christos if (ctf_add_member_offset (dst_fp, dst_type, membname,
1990 1.1.1.2 christos dst_membtype, offset) < 0)
1991 1.1.1.2 christos {
1992 1.1.1.2 christos ctf_next_destroy (i);
1993 1.1.1.2 christos break;
1994 1.1.1.2 christos }
1995 1.1.1.2 christos }
1996 1.1.1.2 christos if (ctf_errno (src_fp) != ECTF_NEXT_END)
1997 1.1 christos return CTF_ERR; /* errno is set for us. */
1998 1.1 christos break;
1999 1.1 christos }
2000 1.1 christos
2001 1.1 christos case CTF_K_ENUM:
2002 1.1 christos if (dst_type != CTF_ERR && kind != CTF_K_FORWARD
2003 1.1 christos && dst_kind != CTF_K_FORWARD)
2004 1.1 christos {
2005 1.1 christos if (ctf_enum_iter (src_fp, src_type, enumcmp, &dst)
2006 1.1 christos || ctf_enum_iter (dst_fp, dst_type, enumcmp, &src))
2007 1.1 christos {
2008 1.1 christos ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
2009 1.1 christos _("conflict for enum %s against ID %lx: members "
2010 1.1 christos "differ, see above"), name, dst_type);
2011 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
2012 1.1 christos }
2013 1.1 christos }
2014 1.1 christos else
2015 1.1 christos {
2016 1.1.1.4 christos ctf_snapshot_id_t snap = ctf_snapshot (dst_fp);
2017 1.1.1.4 christos
2018 1.1 christos dst_type = ctf_add_enum (dst_fp, flag, name);
2019 1.1 christos if ((dst.ctb_type = dst_type) == CTF_ERR
2020 1.1 christos || ctf_enum_iter (src_fp, src_type, enumadd, &dst))
2021 1.1.1.4 christos {
2022 1.1.1.4 christos ctf_rollback (dst_fp, snap);
2023 1.1.1.4 christos return CTF_ERR; /* errno is set for us */
2024 1.1.1.4 christos }
2025 1.1 christos }
2026 1.1 christos break;
2027 1.1 christos
2028 1.1 christos case CTF_K_FORWARD:
2029 1.1 christos if (dst_type == CTF_ERR)
2030 1.1 christos dst_type = ctf_add_forward (dst_fp, flag, name, forward_kind);
2031 1.1 christos break;
2032 1.1 christos
2033 1.1 christos case CTF_K_TYPEDEF:
2034 1.1 christos src_type = ctf_type_reference (src_fp, src_type);
2035 1.1 christos src_type = ctf_add_type_internal (dst_fp, src_fp, src_type,
2036 1.1 christos proc_tracking_fp);
2037 1.1 christos
2038 1.1 christos if (src_type == CTF_ERR)
2039 1.1 christos return CTF_ERR; /* errno is set for us. */
2040 1.1 christos
2041 1.1 christos /* If dst_type is not CTF_ERR at this point, we should check if
2042 1.1 christos ctf_type_reference(dst_fp, dst_type) != src_type and if so fail with
2043 1.1 christos ECTF_CONFLICT. However, this causes problems with bitness typedefs
2044 1.1 christos that vary based on things like if 32-bit then pid_t is int otherwise
2045 1.1 christos long. We therefore omit this check and assume that if the identically
2046 1.1 christos named typedef already exists in dst_fp, it is correct or
2047 1.1 christos equivalent. */
2048 1.1 christos
2049 1.1 christos if (dst_type == CTF_ERR)
2050 1.1 christos dst_type = ctf_add_typedef (dst_fp, flag, name, src_type);
2051 1.1 christos
2052 1.1 christos break;
2053 1.1 christos
2054 1.1 christos default:
2055 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CORRUPT));
2056 1.1 christos }
2057 1.1 christos
2058 1.1 christos if (dst_type != CTF_ERR)
2059 1.1 christos ctf_add_type_mapping (src_fp, orig_src_type, dst_fp, dst_type);
2060 1.1 christos return dst_type;
2061 1.1 christos }
2062 1.1 christos
2063 1.1 christos ctf_id_t
2064 1.1.1.2 christos ctf_add_type (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type)
2065 1.1 christos {
2066 1.1 christos ctf_id_t id;
2067 1.1 christos
2068 1.1 christos if (!src_fp->ctf_add_processing)
2069 1.1 christos src_fp->ctf_add_processing = ctf_dynhash_create (ctf_hash_integer,
2070 1.1 christos ctf_hash_eq_integer,
2071 1.1 christos NULL, NULL);
2072 1.1 christos
2073 1.1 christos /* We store the hash on the source, because it contains only source type IDs:
2074 1.1 christos but callers will invariably expect errors to appear on the dest. */
2075 1.1 christos if (!src_fp->ctf_add_processing)
2076 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ENOMEM));
2077 1.1 christos
2078 1.1 christos id = ctf_add_type_internal (dst_fp, src_fp, src_type, src_fp);
2079 1.1 christos ctf_dynhash_empty (src_fp->ctf_add_processing);
2080 1.1 christos
2081 1.1 christos return id;
2082 1.1 christos }
2083