ctf-create.c revision 1.1.1.3 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 christos && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL
262 1.1 christos && LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info))
263 1.1 christos {
264 1.1.1.3 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.1.2 christos size_t i;
1052 1.1 christos
1053 1.1 christos uint32_t kind, vlen, root;
1054 1.1 christos
1055 1.1 christos if (name == NULL)
1056 1.1 christos return (ctf_set_errno (fp, EINVAL));
1057 1.1 christos
1058 1.1.1.3 christos if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, enid))
1059 1.1.1.3 christos fp = fp->ctf_parent;
1060 1.1.1.3 christos
1061 1.1.1.3 christos if (enid < fp->ctf_stypes)
1062 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_RDONLY));
1063 1.1 christos
1064 1.1 christos if (dtd == NULL)
1065 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_BADID));
1066 1.1 christos
1067 1.1 christos kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
1068 1.1 christos root = LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info);
1069 1.1 christos vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
1070 1.1 christos
1071 1.1 christos if (kind != CTF_K_ENUM)
1072 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_NOTENUM));
1073 1.1 christos
1074 1.1 christos if (vlen == CTF_MAX_VLEN)
1075 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_DTFULL));
1076 1.1 christos
1077 1.1.1.2 christos old_vlen = dtd->dtd_vlen;
1078 1.1.1.2 christos if (ctf_grow_vlen (fp, dtd, sizeof (ctf_enum_t) * (vlen + 1)) < 0)
1079 1.1.1.2 christos return -1; /* errno is set for us. */
1080 1.1.1.2 christos en = (ctf_enum_t *) dtd->dtd_vlen;
1081 1.1.1.2 christos
1082 1.1.1.3 christos /* Remove refs in the old vlen region and reapply them. */
1083 1.1 christos
1084 1.1.1.3 christos ctf_str_move_refs (fp, old_vlen, sizeof (ctf_enum_t) * vlen, dtd->dtd_vlen);
1085 1.1 christos
1086 1.1.1.2 christos for (i = 0; i < vlen; i++)
1087 1.1.1.2 christos if (strcmp (ctf_strptr (fp, en[i].cte_name), name) == 0)
1088 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_DUPLICATE));
1089 1.1.1.2 christos
1090 1.1.1.3 christos en[i].cte_name = ctf_str_add_movable_ref (fp, name, &en[i].cte_name);
1091 1.1.1.2 christos en[i].cte_value = value;
1092 1.1.1.2 christos
1093 1.1.1.2 christos if (en[i].cte_name == 0 && name != NULL && name[0] != '\0')
1094 1.1.1.3 christos return (ctf_set_errno (ofp, ctf_errno (fp)));
1095 1.1 christos
1096 1.1 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
1097 1.1 christos
1098 1.1 christos return 0;
1099 1.1 christos }
1100 1.1 christos
1101 1.1 christos int
1102 1.1.1.2 christos ctf_add_member_offset (ctf_dict_t *fp, ctf_id_t souid, const char *name,
1103 1.1 christos ctf_id_t type, unsigned long bit_offset)
1104 1.1 christos {
1105 1.1.1.3 christos ctf_dict_t *ofp = fp;
1106 1.1 christos ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, souid);
1107 1.1 christos
1108 1.1 christos ssize_t msize, malign, ssize;
1109 1.1 christos uint32_t kind, vlen, root;
1110 1.1.1.2 christos size_t i;
1111 1.1.1.2 christos int is_incomplete = 0;
1112 1.1.1.2 christos unsigned char *old_vlen;
1113 1.1.1.2 christos ctf_lmember_t *memb;
1114 1.1 christos
1115 1.1.1.3 christos if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, souid))
1116 1.1.1.3 christos {
1117 1.1.1.3 christos /* Adding a child type to a parent, even via the child, is prohibited.
1118 1.1.1.3 christos Otherwise, climb to the parent and do all work there. */
1119 1.1.1.3 christos
1120 1.1.1.3 christos if (LCTF_TYPE_ISCHILD (fp, type))
1121 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_BADID));
1122 1.1.1.3 christos
1123 1.1.1.3 christos fp = fp->ctf_parent;
1124 1.1.1.3 christos }
1125 1.1.1.3 christos
1126 1.1.1.3 christos if (souid < fp->ctf_stypes)
1127 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_RDONLY));
1128 1.1 christos
1129 1.1 christos if (dtd == NULL)
1130 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_BADID));
1131 1.1 christos
1132 1.1 christos if (name != NULL && name[0] == '\0')
1133 1.1 christos name = NULL;
1134 1.1 christos
1135 1.1 christos kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
1136 1.1 christos root = LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info);
1137 1.1 christos vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
1138 1.1 christos
1139 1.1 christos if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
1140 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_NOTSOU));
1141 1.1 christos
1142 1.1 christos if (vlen == CTF_MAX_VLEN)
1143 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_DTFULL));
1144 1.1 christos
1145 1.1.1.2 christos old_vlen = dtd->dtd_vlen;
1146 1.1.1.2 christos if (ctf_grow_vlen (fp, dtd, sizeof (ctf_lmember_t) * (vlen + 1)) < 0)
1147 1.1.1.3 christos return (ctf_set_errno (ofp, ctf_errno (fp)));
1148 1.1.1.2 christos memb = (ctf_lmember_t *) dtd->dtd_vlen;
1149 1.1.1.2 christos
1150 1.1.1.3 christos /* Remove pending refs in the old vlen region and reapply them. */
1151 1.1.1.2 christos
1152 1.1.1.3 christos ctf_str_move_refs (fp, old_vlen, sizeof (ctf_lmember_t) * vlen, dtd->dtd_vlen);
1153 1.1.1.2 christos
1154 1.1 christos if (name != NULL)
1155 1.1 christos {
1156 1.1.1.2 christos for (i = 0; i < vlen; i++)
1157 1.1.1.2 christos if (strcmp (ctf_strptr (fp, memb[i].ctlm_name), name) == 0)
1158 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_DUPLICATE));
1159 1.1 christos }
1160 1.1 christos
1161 1.1 christos if ((msize = ctf_type_size (fp, type)) < 0 ||
1162 1.1 christos (malign = ctf_type_align (fp, type)) < 0)
1163 1.1 christos {
1164 1.1 christos /* The unimplemented type, and any type that resolves to it, has no size
1165 1.1 christos and no alignment: it can correspond to any number of compiler-inserted
1166 1.1.1.2 christos types. We allow incomplete types through since they are routinely
1167 1.1.1.2 christos added to the ends of structures, and can even be added elsewhere in
1168 1.1.1.2 christos structures by the deduplicator. They are assumed to be zero-size with
1169 1.1.1.2 christos no alignment: this is often wrong, but problems can be avoided in this
1170 1.1.1.2 christos case by explicitly specifying the size of the structure via the _sized
1171 1.1.1.2 christos functions. The deduplicator always does this. */
1172 1.1 christos
1173 1.1.1.2 christos msize = 0;
1174 1.1.1.2 christos malign = 0;
1175 1.1 christos if (ctf_errno (fp) == ECTF_NONREPRESENTABLE)
1176 1.1.1.2 christos ctf_set_errno (fp, 0);
1177 1.1.1.2 christos else if (ctf_errno (fp) == ECTF_INCOMPLETE)
1178 1.1.1.2 christos is_incomplete = 1;
1179 1.1 christos else
1180 1.1 christos return -1; /* errno is set for us. */
1181 1.1 christos }
1182 1.1 christos
1183 1.1.1.3 christos memb[vlen].ctlm_name = ctf_str_add_movable_ref (fp, name, &memb[vlen].ctlm_name);
1184 1.1.1.2 christos memb[vlen].ctlm_type = type;
1185 1.1.1.2 christos if (memb[vlen].ctlm_name == 0 && name != NULL && name[0] != '\0')
1186 1.1.1.2 christos return -1; /* errno is set for us. */
1187 1.1 christos
1188 1.1 christos if (kind == CTF_K_STRUCT && vlen != 0)
1189 1.1 christos {
1190 1.1 christos if (bit_offset == (unsigned long) - 1)
1191 1.1 christos {
1192 1.1 christos /* Natural alignment. */
1193 1.1 christos
1194 1.1.1.2 christos ctf_id_t ltype = ctf_type_resolve (fp, memb[vlen - 1].ctlm_type);
1195 1.1.1.2 christos size_t off = CTF_LMEM_OFFSET(&memb[vlen - 1]);
1196 1.1 christos
1197 1.1 christos ctf_encoding_t linfo;
1198 1.1 christos ssize_t lsize;
1199 1.1 christos
1200 1.1 christos /* Propagate any error from ctf_type_resolve. If the last member was
1201 1.1 christos of unimplemented type, this may be -ECTF_NONREPRESENTABLE: we
1202 1.1 christos cannot insert right after such a member without explicit offset
1203 1.1 christos specification, because its alignment and size is not known. */
1204 1.1 christos if (ltype == CTF_ERR)
1205 1.1.1.2 christos return -1; /* errno is set for us. */
1206 1.1.1.2 christos
1207 1.1.1.2 christos if (is_incomplete)
1208 1.1 christos {
1209 1.1.1.3 christos ctf_err_warn (ofp, 1, ECTF_INCOMPLETE,
1210 1.1.1.2 christos _("ctf_add_member_offset: cannot add member %s of "
1211 1.1.1.2 christos "incomplete type %lx to struct %lx without "
1212 1.1.1.2 christos "specifying explicit offset\n"),
1213 1.1.1.2 christos name ? name : _("(unnamed member)"), type, souid);
1214 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_INCOMPLETE));
1215 1.1 christos }
1216 1.1 christos
1217 1.1 christos if (ctf_type_encoding (fp, ltype, &linfo) == 0)
1218 1.1 christos off += linfo.cte_bits;
1219 1.1 christos else if ((lsize = ctf_type_size (fp, ltype)) > 0)
1220 1.1 christos off += lsize * CHAR_BIT;
1221 1.1.1.2 christos else if (lsize == -1 && ctf_errno (fp) == ECTF_INCOMPLETE)
1222 1.1.1.2 christos {
1223 1.1.1.2 christos const char *lname = ctf_strraw (fp, memb[vlen - 1].ctlm_name);
1224 1.1.1.2 christos
1225 1.1.1.3 christos ctf_err_warn (ofp, 1, ECTF_INCOMPLETE,
1226 1.1.1.2 christos _("ctf_add_member_offset: cannot add member %s of "
1227 1.1.1.2 christos "type %lx to struct %lx without specifying "
1228 1.1.1.2 christos "explicit offset after member %s of type %lx, "
1229 1.1.1.2 christos "which is an incomplete type\n"),
1230 1.1.1.2 christos name ? name : _("(unnamed member)"), type, souid,
1231 1.1.1.2 christos lname ? lname : _("(unnamed member)"), ltype);
1232 1.1.1.3 christos return (ctf_set_errno (ofp, ECTF_INCOMPLETE));
1233 1.1.1.2 christos }
1234 1.1 christos
1235 1.1 christos /* Round up the offset of the end of the last member to
1236 1.1 christos the next byte boundary, convert 'off' to bytes, and
1237 1.1 christos then round it up again to the next multiple of the
1238 1.1 christos alignment required by the new member. Finally,
1239 1.1 christos convert back to bits and store the result in
1240 1.1 christos dmd_offset. Technically we could do more efficient
1241 1.1 christos packing if the new member is a bit-field, but we're
1242 1.1 christos the "compiler" and ANSI says we can do as we choose. */
1243 1.1 christos
1244 1.1 christos off = roundup (off, CHAR_BIT) / CHAR_BIT;
1245 1.1 christos off = roundup (off, MAX (malign, 1));
1246 1.1.1.2 christos memb[vlen].ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (off * CHAR_BIT);
1247 1.1.1.2 christos memb[vlen].ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (off * CHAR_BIT);
1248 1.1 christos ssize = off + msize;
1249 1.1 christos }
1250 1.1 christos else
1251 1.1 christos {
1252 1.1 christos /* Specified offset in bits. */
1253 1.1 christos
1254 1.1.1.2 christos memb[vlen].ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (bit_offset);
1255 1.1.1.2 christos memb[vlen].ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (bit_offset);
1256 1.1 christos ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
1257 1.1 christos ssize = MAX (ssize, ((signed) bit_offset / CHAR_BIT) + msize);
1258 1.1 christos }
1259 1.1 christos }
1260 1.1 christos else
1261 1.1 christos {
1262 1.1.1.2 christos memb[vlen].ctlm_offsethi = 0;
1263 1.1.1.2 christos memb[vlen].ctlm_offsetlo = 0;
1264 1.1 christos ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
1265 1.1 christos ssize = MAX (ssize, msize);
1266 1.1 christos }
1267 1.1 christos
1268 1.1.1.2 christos dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
1269 1.1.1.2 christos dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (ssize);
1270 1.1.1.2 christos dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (ssize);
1271 1.1 christos dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
1272 1.1 christos
1273 1.1 christos return 0;
1274 1.1 christos }
1275 1.1 christos
1276 1.1 christos int
1277 1.1.1.2 christos ctf_add_member_encoded (ctf_dict_t *fp, ctf_id_t souid, const char *name,
1278 1.1 christos ctf_id_t type, unsigned long bit_offset,
1279 1.1 christos const ctf_encoding_t encoding)
1280 1.1 christos {
1281 1.1 christos ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, type);
1282 1.1.1.3 christos int kind;
1283 1.1 christos int otype = type;
1284 1.1 christos
1285 1.1.1.3 christos if (dtd == NULL)
1286 1.1.1.3 christos return (ctf_set_errno (fp, ECTF_BADID));
1287 1.1.1.3 christos
1288 1.1.1.3 christos kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
1289 1.1.1.3 christos
1290 1.1 christos if ((kind != CTF_K_INTEGER) && (kind != CTF_K_FLOAT) && (kind != CTF_K_ENUM))
1291 1.1 christos return (ctf_set_errno (fp, ECTF_NOTINTFP));
1292 1.1 christos
1293 1.1 christos if ((type = ctf_add_slice (fp, CTF_ADD_NONROOT, otype, &encoding)) == CTF_ERR)
1294 1.1 christos return -1; /* errno is set for us. */
1295 1.1 christos
1296 1.1 christos return ctf_add_member_offset (fp, souid, name, type, bit_offset);
1297 1.1 christos }
1298 1.1 christos
1299 1.1 christos int
1300 1.1.1.2 christos ctf_add_member (ctf_dict_t *fp, ctf_id_t souid, const char *name,
1301 1.1 christos ctf_id_t type)
1302 1.1 christos {
1303 1.1 christos return ctf_add_member_offset (fp, souid, name, type, (unsigned long) - 1);
1304 1.1 christos }
1305 1.1 christos
1306 1.1.1.3 christos /* Add a variable regardless of whether or not it is already present.
1307 1.1.1.3 christos
1308 1.1.1.3 christos Internal use only. */
1309 1.1 christos int
1310 1.1.1.3 christos ctf_add_variable_forced (ctf_dict_t *fp, const char *name, ctf_id_t ref)
1311 1.1 christos {
1312 1.1 christos ctf_dvdef_t *dvd;
1313 1.1.1.2 christos ctf_dict_t *tmp = fp;
1314 1.1 christos
1315 1.1 christos if (ctf_lookup_by_id (&tmp, ref) == NULL)
1316 1.1 christos return -1; /* errno is set for us. */
1317 1.1 christos
1318 1.1 christos /* Make sure this type is representable. */
1319 1.1 christos if ((ctf_type_resolve (fp, ref) == CTF_ERR)
1320 1.1 christos && (ctf_errno (fp) == ECTF_NONREPRESENTABLE))
1321 1.1 christos return -1;
1322 1.1 christos
1323 1.1 christos if ((dvd = malloc (sizeof (ctf_dvdef_t))) == NULL)
1324 1.1 christos return (ctf_set_errno (fp, EAGAIN));
1325 1.1 christos
1326 1.1 christos if (name != NULL && (dvd->dvd_name = strdup (name)) == NULL)
1327 1.1 christos {
1328 1.1 christos free (dvd);
1329 1.1 christos return (ctf_set_errno (fp, EAGAIN));
1330 1.1 christos }
1331 1.1 christos dvd->dvd_type = ref;
1332 1.1 christos dvd->dvd_snapshots = fp->ctf_snapshots;
1333 1.1 christos
1334 1.1 christos if (ctf_dvd_insert (fp, dvd) < 0)
1335 1.1 christos {
1336 1.1 christos free (dvd->dvd_name);
1337 1.1 christos free (dvd);
1338 1.1 christos return -1; /* errno is set for us. */
1339 1.1 christos }
1340 1.1 christos
1341 1.1 christos return 0;
1342 1.1 christos }
1343 1.1 christos
1344 1.1.1.2 christos int
1345 1.1.1.3 christos ctf_add_variable (ctf_dict_t *fp, const char *name, ctf_id_t ref)
1346 1.1.1.3 christos {
1347 1.1.1.3 christos if (ctf_lookup_variable_here (fp, name) != CTF_ERR)
1348 1.1.1.3 christos return (ctf_set_errno (fp, ECTF_DUPLICATE));
1349 1.1.1.3 christos
1350 1.1.1.3 christos if (ctf_errno (fp) != ECTF_NOTYPEDAT)
1351 1.1.1.3 christos return -1; /* errno is set for us. */
1352 1.1.1.3 christos
1353 1.1.1.3 christos return ctf_add_variable_forced (fp, name, ref);
1354 1.1.1.3 christos }
1355 1.1.1.3 christos
1356 1.1.1.3 christos /* Add a function or object symbol regardless of whether or not it is already
1357 1.1.1.3 christos present (already existing symbols are silently overwritten).
1358 1.1.1.3 christos
1359 1.1.1.3 christos Internal use only. */
1360 1.1.1.3 christos int
1361 1.1.1.3 christos ctf_add_funcobjt_sym_forced (ctf_dict_t *fp, int is_function, const char *name, ctf_id_t id)
1362 1.1.1.2 christos {
1363 1.1.1.2 christos ctf_dict_t *tmp = fp;
1364 1.1.1.2 christos char *dupname;
1365 1.1.1.2 christos ctf_dynhash_t *h = is_function ? fp->ctf_funchash : fp->ctf_objthash;
1366 1.1.1.2 christos
1367 1.1.1.2 christos if (ctf_lookup_by_id (&tmp, id) == NULL)
1368 1.1.1.3 christos return -1; /* errno is set for us. */
1369 1.1.1.2 christos
1370 1.1.1.2 christos if (is_function && ctf_type_kind (fp, id) != CTF_K_FUNCTION)
1371 1.1.1.2 christos return (ctf_set_errno (fp, ECTF_NOTFUNC));
1372 1.1.1.2 christos
1373 1.1.1.2 christos if ((dupname = strdup (name)) == NULL)
1374 1.1.1.2 christos return (ctf_set_errno (fp, ENOMEM));
1375 1.1.1.2 christos
1376 1.1.1.2 christos if (ctf_dynhash_insert (h, dupname, (void *) (uintptr_t) id) < 0)
1377 1.1.1.2 christos {
1378 1.1.1.2 christos free (dupname);
1379 1.1.1.2 christos return (ctf_set_errno (fp, ENOMEM));
1380 1.1.1.2 christos }
1381 1.1.1.2 christos return 0;
1382 1.1.1.2 christos }
1383 1.1.1.2 christos
1384 1.1.1.2 christos int
1385 1.1.1.3 christos ctf_add_funcobjt_sym (ctf_dict_t *fp, int is_function, const char *name, ctf_id_t id)
1386 1.1.1.3 christos {
1387 1.1.1.3 christos if (ctf_lookup_by_sym_or_name (fp, 0, name, 0, is_function) != CTF_ERR)
1388 1.1.1.3 christos return (ctf_set_errno (fp, ECTF_DUPLICATE));
1389 1.1.1.3 christos
1390 1.1.1.3 christos return ctf_add_funcobjt_sym_forced (fp, is_function, name, id);
1391 1.1.1.3 christos }
1392 1.1.1.3 christos
1393 1.1.1.3 christos int
1394 1.1.1.2 christos ctf_add_objt_sym (ctf_dict_t *fp, const char *name, ctf_id_t id)
1395 1.1.1.2 christos {
1396 1.1.1.2 christos return (ctf_add_funcobjt_sym (fp, 0, name, id));
1397 1.1.1.2 christos }
1398 1.1.1.2 christos
1399 1.1.1.2 christos int
1400 1.1.1.2 christos ctf_add_func_sym (ctf_dict_t *fp, const char *name, ctf_id_t id)
1401 1.1.1.2 christos {
1402 1.1.1.2 christos return (ctf_add_funcobjt_sym (fp, 1, name, id));
1403 1.1.1.2 christos }
1404 1.1.1.2 christos
1405 1.1 christos typedef struct ctf_bundle
1406 1.1 christos {
1407 1.1.1.2 christos ctf_dict_t *ctb_dict; /* CTF dict handle. */
1408 1.1 christos ctf_id_t ctb_type; /* CTF type identifier. */
1409 1.1 christos ctf_dtdef_t *ctb_dtd; /* CTF dynamic type definition (if any). */
1410 1.1 christos } ctf_bundle_t;
1411 1.1 christos
1412 1.1 christos static int
1413 1.1 christos enumcmp (const char *name, int value, void *arg)
1414 1.1 christos {
1415 1.1 christos ctf_bundle_t *ctb = arg;
1416 1.1 christos int bvalue;
1417 1.1 christos
1418 1.1.1.2 christos if (ctf_enum_value (ctb->ctb_dict, ctb->ctb_type, name, &bvalue) < 0)
1419 1.1 christos {
1420 1.1.1.2 christos ctf_err_warn (ctb->ctb_dict, 0, 0,
1421 1.1 christos _("conflict due to enum %s iteration error"), name);
1422 1.1 christos return 1;
1423 1.1 christos }
1424 1.1 christos if (value != bvalue)
1425 1.1 christos {
1426 1.1.1.2 christos ctf_err_warn (ctb->ctb_dict, 1, ECTF_CONFLICT,
1427 1.1 christos _("conflict due to enum value change: %i versus %i"),
1428 1.1 christos value, bvalue);
1429 1.1 christos return 1;
1430 1.1 christos }
1431 1.1 christos return 0;
1432 1.1 christos }
1433 1.1 christos
1434 1.1 christos static int
1435 1.1 christos enumadd (const char *name, int value, void *arg)
1436 1.1 christos {
1437 1.1 christos ctf_bundle_t *ctb = arg;
1438 1.1 christos
1439 1.1.1.2 christos return (ctf_add_enumerator (ctb->ctb_dict, ctb->ctb_type,
1440 1.1 christos name, value) < 0);
1441 1.1 christos }
1442 1.1 christos
1443 1.1 christos static int
1444 1.1 christos membcmp (const char *name, ctf_id_t type _libctf_unused_, unsigned long offset,
1445 1.1 christos void *arg)
1446 1.1 christos {
1447 1.1 christos ctf_bundle_t *ctb = arg;
1448 1.1 christos ctf_membinfo_t ctm;
1449 1.1 christos
1450 1.1 christos /* Don't check nameless members (e.g. anonymous structs/unions) against each
1451 1.1 christos other. */
1452 1.1 christos if (name[0] == 0)
1453 1.1 christos return 0;
1454 1.1 christos
1455 1.1.1.2 christos if (ctf_member_info (ctb->ctb_dict, ctb->ctb_type, name, &ctm) < 0)
1456 1.1 christos {
1457 1.1.1.2 christos ctf_err_warn (ctb->ctb_dict, 0, 0,
1458 1.1 christos _("conflict due to struct member %s iteration error"),
1459 1.1 christos name);
1460 1.1 christos return 1;
1461 1.1 christos }
1462 1.1 christos if (ctm.ctm_offset != offset)
1463 1.1 christos {
1464 1.1.1.2 christos ctf_err_warn (ctb->ctb_dict, 1, ECTF_CONFLICT,
1465 1.1 christos _("conflict due to struct member %s offset change: "
1466 1.1 christos "%lx versus %lx"),
1467 1.1 christos name, ctm.ctm_offset, offset);
1468 1.1 christos return 1;
1469 1.1 christos }
1470 1.1 christos return 0;
1471 1.1 christos }
1472 1.1 christos
1473 1.1.1.2 christos /* Record the correspondence between a source and ctf_add_type()-added
1474 1.1.1.2 christos destination type: both types are translated into parent type IDs if need be,
1475 1.1.1.2 christos so they relate to the actual dictionary they are in. Outside controlled
1476 1.1.1.2 christos circumstances (like linking) it is probably not useful to do more than
1477 1.1.1.2 christos compare these pointers, since there is nothing stopping the user closing the
1478 1.1.1.2 christos source dict whenever they want to.
1479 1.1.1.2 christos
1480 1.1.1.2 christos Our OOM handling here is just to not do anything, because this is called deep
1481 1.1.1.2 christos enough in the call stack that doing anything useful is painfully difficult:
1482 1.1.1.2 christos the worst consequence if we do OOM is a bit of type duplication anyway. */
1483 1.1.1.2 christos
1484 1.1.1.2 christos static void
1485 1.1.1.2 christos ctf_add_type_mapping (ctf_dict_t *src_fp, ctf_id_t src_type,
1486 1.1.1.2 christos ctf_dict_t *dst_fp, ctf_id_t dst_type)
1487 1.1 christos {
1488 1.1.1.2 christos if (LCTF_TYPE_ISPARENT (src_fp, src_type) && src_fp->ctf_parent)
1489 1.1.1.2 christos src_fp = src_fp->ctf_parent;
1490 1.1 christos
1491 1.1.1.2 christos src_type = LCTF_TYPE_TO_INDEX(src_fp, src_type);
1492 1.1 christos
1493 1.1.1.2 christos if (LCTF_TYPE_ISPARENT (dst_fp, dst_type) && dst_fp->ctf_parent)
1494 1.1.1.2 christos dst_fp = dst_fp->ctf_parent;
1495 1.1.1.2 christos
1496 1.1.1.2 christos dst_type = LCTF_TYPE_TO_INDEX(dst_fp, dst_type);
1497 1.1.1.2 christos
1498 1.1.1.2 christos if (dst_fp->ctf_link_type_mapping == NULL)
1499 1.1 christos {
1500 1.1.1.2 christos ctf_hash_fun f = ctf_hash_type_key;
1501 1.1.1.2 christos ctf_hash_eq_fun e = ctf_hash_eq_type_key;
1502 1.1.1.2 christos
1503 1.1.1.2 christos if ((dst_fp->ctf_link_type_mapping = ctf_dynhash_create (f, e, free,
1504 1.1.1.2 christos NULL)) == NULL)
1505 1.1.1.2 christos return;
1506 1.1 christos }
1507 1.1 christos
1508 1.1.1.2 christos ctf_link_type_key_t *key;
1509 1.1.1.2 christos key = calloc (1, sizeof (struct ctf_link_type_key));
1510 1.1.1.2 christos if (!key)
1511 1.1.1.2 christos return;
1512 1.1 christos
1513 1.1.1.2 christos key->cltk_fp = src_fp;
1514 1.1.1.2 christos key->cltk_idx = src_type;
1515 1.1 christos
1516 1.1.1.2 christos /* No OOM checking needed, because if this doesn't work the worst we'll do is
1517 1.1.1.2 christos add a few more duplicate types (which will probably run out of memory
1518 1.1.1.2 christos anyway). */
1519 1.1.1.2 christos ctf_dynhash_insert (dst_fp->ctf_link_type_mapping, key,
1520 1.1.1.2 christos (void *) (uintptr_t) dst_type);
1521 1.1 christos }
1522 1.1 christos
1523 1.1.1.2 christos /* Look up a type mapping: return 0 if none. The DST_FP is modified to point to
1524 1.1.1.2 christos the parent if need be. The ID returned is from the dst_fp's perspective. */
1525 1.1.1.2 christos static ctf_id_t
1526 1.1.1.2 christos ctf_type_mapping (ctf_dict_t *src_fp, ctf_id_t src_type, ctf_dict_t **dst_fp)
1527 1.1.1.2 christos {
1528 1.1.1.2 christos ctf_link_type_key_t key;
1529 1.1.1.2 christos ctf_dict_t *target_fp = *dst_fp;
1530 1.1.1.2 christos ctf_id_t dst_type = 0;
1531 1.1.1.2 christos
1532 1.1.1.2 christos if (LCTF_TYPE_ISPARENT (src_fp, src_type) && src_fp->ctf_parent)
1533 1.1.1.2 christos src_fp = src_fp->ctf_parent;
1534 1.1.1.2 christos
1535 1.1.1.2 christos src_type = LCTF_TYPE_TO_INDEX(src_fp, src_type);
1536 1.1.1.2 christos key.cltk_fp = src_fp;
1537 1.1.1.2 christos key.cltk_idx = src_type;
1538 1.1.1.2 christos
1539 1.1.1.2 christos if (target_fp->ctf_link_type_mapping)
1540 1.1.1.2 christos dst_type = (uintptr_t) ctf_dynhash_lookup (target_fp->ctf_link_type_mapping,
1541 1.1.1.2 christos &key);
1542 1.1.1.2 christos
1543 1.1.1.2 christos if (dst_type != 0)
1544 1.1.1.2 christos {
1545 1.1.1.2 christos dst_type = LCTF_INDEX_TO_TYPE (target_fp, dst_type,
1546 1.1.1.2 christos target_fp->ctf_parent != NULL);
1547 1.1.1.2 christos *dst_fp = target_fp;
1548 1.1.1.2 christos return dst_type;
1549 1.1.1.2 christos }
1550 1.1.1.2 christos
1551 1.1.1.2 christos if (target_fp->ctf_parent)
1552 1.1.1.2 christos target_fp = target_fp->ctf_parent;
1553 1.1.1.2 christos else
1554 1.1.1.2 christos return 0;
1555 1.1.1.2 christos
1556 1.1.1.2 christos if (target_fp->ctf_link_type_mapping)
1557 1.1.1.2 christos dst_type = (uintptr_t) ctf_dynhash_lookup (target_fp->ctf_link_type_mapping,
1558 1.1.1.2 christos &key);
1559 1.1.1.2 christos
1560 1.1.1.2 christos if (dst_type)
1561 1.1.1.2 christos dst_type = LCTF_INDEX_TO_TYPE (target_fp, dst_type,
1562 1.1.1.2 christos target_fp->ctf_parent != NULL);
1563 1.1.1.2 christos
1564 1.1.1.2 christos *dst_fp = target_fp;
1565 1.1.1.2 christos return dst_type;
1566 1.1.1.2 christos }
1567 1.1.1.2 christos
1568 1.1.1.2 christos /* The ctf_add_type routine is used to copy a type from a source CTF dictionary
1569 1.1.1.2 christos to a dynamic destination dictionary. This routine operates recursively by
1570 1.1 christos following the source type's links and embedded member types. If the
1571 1.1.1.2 christos destination dict already contains a named type which has the same attributes,
1572 1.1.1.2 christos then we succeed and return this type but no changes occur. */
1573 1.1 christos static ctf_id_t
1574 1.1.1.2 christos ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type,
1575 1.1.1.2 christos ctf_dict_t *proc_tracking_fp)
1576 1.1 christos {
1577 1.1 christos ctf_id_t dst_type = CTF_ERR;
1578 1.1 christos uint32_t dst_kind = CTF_K_UNKNOWN;
1579 1.1.1.2 christos ctf_dict_t *tmp_fp = dst_fp;
1580 1.1 christos ctf_id_t tmp;
1581 1.1 christos
1582 1.1 christos const char *name;
1583 1.1 christos uint32_t kind, forward_kind, flag, vlen;
1584 1.1 christos
1585 1.1 christos const ctf_type_t *src_tp, *dst_tp;
1586 1.1 christos ctf_bundle_t src, dst;
1587 1.1 christos ctf_encoding_t src_en, dst_en;
1588 1.1 christos ctf_arinfo_t src_ar, dst_ar;
1589 1.1 christos
1590 1.1 christos ctf_funcinfo_t ctc;
1591 1.1 christos
1592 1.1 christos ctf_id_t orig_src_type = src_type;
1593 1.1 christos
1594 1.1 christos if ((src_tp = ctf_lookup_by_id (&src_fp, src_type)) == NULL)
1595 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ctf_errno (src_fp)));
1596 1.1 christos
1597 1.1 christos if ((ctf_type_resolve (src_fp, src_type) == CTF_ERR)
1598 1.1 christos && (ctf_errno (src_fp) == ECTF_NONREPRESENTABLE))
1599 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_NONREPRESENTABLE));
1600 1.1 christos
1601 1.1 christos name = ctf_strptr (src_fp, src_tp->ctt_name);
1602 1.1 christos kind = LCTF_INFO_KIND (src_fp, src_tp->ctt_info);
1603 1.1 christos flag = LCTF_INFO_ISROOT (src_fp, src_tp->ctt_info);
1604 1.1 christos vlen = LCTF_INFO_VLEN (src_fp, src_tp->ctt_info);
1605 1.1 christos
1606 1.1 christos /* If this is a type we are currently in the middle of adding, hand it
1607 1.1 christos straight back. (This lets us handle self-referential structures without
1608 1.1 christos considering forwards and empty structures the same as their completed
1609 1.1 christos forms.) */
1610 1.1 christos
1611 1.1 christos tmp = ctf_type_mapping (src_fp, src_type, &tmp_fp);
1612 1.1 christos
1613 1.1 christos if (tmp != 0)
1614 1.1 christos {
1615 1.1 christos if (ctf_dynhash_lookup (proc_tracking_fp->ctf_add_processing,
1616 1.1 christos (void *) (uintptr_t) src_type))
1617 1.1 christos return tmp;
1618 1.1 christos
1619 1.1.1.2 christos /* If this type has already been added from this dictionary, and is the
1620 1.1.1.2 christos same kind and (if a struct or union) has the same number of members,
1621 1.1.1.2 christos hand it straight back. */
1622 1.1 christos
1623 1.1 christos if (ctf_type_kind_unsliced (tmp_fp, tmp) == (int) kind)
1624 1.1 christos {
1625 1.1 christos if (kind == CTF_K_STRUCT || kind == CTF_K_UNION
1626 1.1 christos || kind == CTF_K_ENUM)
1627 1.1 christos {
1628 1.1 christos if ((dst_tp = ctf_lookup_by_id (&tmp_fp, dst_type)) != NULL)
1629 1.1 christos if (vlen == LCTF_INFO_VLEN (tmp_fp, dst_tp->ctt_info))
1630 1.1 christos return tmp;
1631 1.1 christos }
1632 1.1 christos else
1633 1.1 christos return tmp;
1634 1.1 christos }
1635 1.1 christos }
1636 1.1 christos
1637 1.1 christos forward_kind = kind;
1638 1.1 christos if (kind == CTF_K_FORWARD)
1639 1.1 christos forward_kind = src_tp->ctt_type;
1640 1.1 christos
1641 1.1.1.2 christos /* If the source type has a name and is a root type (visible at the top-level
1642 1.1.1.2 christos scope), lookup the name in the destination dictionary and verify that it is
1643 1.1.1.2 christos of the same kind before we do anything else. */
1644 1.1 christos
1645 1.1 christos if ((flag & CTF_ADD_ROOT) && name[0] != '\0'
1646 1.1 christos && (tmp = ctf_lookup_by_rawname (dst_fp, forward_kind, name)) != 0)
1647 1.1 christos {
1648 1.1 christos dst_type = tmp;
1649 1.1 christos dst_kind = ctf_type_kind_unsliced (dst_fp, dst_type);
1650 1.1 christos }
1651 1.1 christos
1652 1.1 christos /* If an identically named dst_type exists, fail with ECTF_CONFLICT
1653 1.1 christos unless dst_type is a forward declaration and src_type is a struct,
1654 1.1 christos union, or enum (i.e. the definition of the previous forward decl).
1655 1.1 christos
1656 1.1 christos We also allow addition in the opposite order (addition of a forward when a
1657 1.1 christos struct, union, or enum already exists), which is a NOP and returns the
1658 1.1 christos already-present struct, union, or enum. */
1659 1.1 christos
1660 1.1 christos if (dst_type != CTF_ERR && dst_kind != kind)
1661 1.1 christos {
1662 1.1 christos if (kind == CTF_K_FORWARD
1663 1.1 christos && (dst_kind == CTF_K_ENUM || dst_kind == CTF_K_STRUCT
1664 1.1 christos || dst_kind == CTF_K_UNION))
1665 1.1 christos {
1666 1.1 christos ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
1667 1.1 christos return dst_type;
1668 1.1 christos }
1669 1.1 christos
1670 1.1 christos if (dst_kind != CTF_K_FORWARD
1671 1.1 christos || (kind != CTF_K_ENUM && kind != CTF_K_STRUCT
1672 1.1 christos && kind != CTF_K_UNION))
1673 1.1 christos {
1674 1.1 christos ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
1675 1.1.1.2 christos _("ctf_add_type: conflict for type %s: "
1676 1.1 christos "kinds differ, new: %i; old (ID %lx): %i"),
1677 1.1 christos name, kind, dst_type, dst_kind);
1678 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
1679 1.1 christos }
1680 1.1 christos }
1681 1.1 christos
1682 1.1 christos /* We take special action for an integer, float, or slice since it is
1683 1.1 christos described not only by its name but also its encoding. For integers,
1684 1.1 christos bit-fields exploit this degeneracy. */
1685 1.1 christos
1686 1.1 christos if (kind == CTF_K_INTEGER || kind == CTF_K_FLOAT || kind == CTF_K_SLICE)
1687 1.1 christos {
1688 1.1 christos if (ctf_type_encoding (src_fp, src_type, &src_en) != 0)
1689 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ctf_errno (src_fp)));
1690 1.1 christos
1691 1.1 christos if (dst_type != CTF_ERR)
1692 1.1 christos {
1693 1.1.1.2 christos ctf_dict_t *fp = dst_fp;
1694 1.1 christos
1695 1.1 christos if ((dst_tp = ctf_lookup_by_id (&fp, dst_type)) == NULL)
1696 1.1 christos return CTF_ERR;
1697 1.1 christos
1698 1.1 christos if (ctf_type_encoding (dst_fp, dst_type, &dst_en) != 0)
1699 1.1 christos return CTF_ERR; /* errno set for us. */
1700 1.1 christos
1701 1.1 christos if (LCTF_INFO_ISROOT (fp, dst_tp->ctt_info) & CTF_ADD_ROOT)
1702 1.1 christos {
1703 1.1 christos /* The type that we found in the hash is also root-visible. If
1704 1.1 christos the two types match then use the existing one; otherwise,
1705 1.1 christos declare a conflict. Note: slices are not certain to match
1706 1.1 christos even if there is no conflict: we must check the contained type
1707 1.1 christos too. */
1708 1.1 christos
1709 1.1 christos if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0)
1710 1.1 christos {
1711 1.1 christos if (kind != CTF_K_SLICE)
1712 1.1 christos {
1713 1.1 christos ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
1714 1.1 christos return dst_type;
1715 1.1 christos }
1716 1.1 christos }
1717 1.1 christos else
1718 1.1 christos {
1719 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
1720 1.1 christos }
1721 1.1 christos }
1722 1.1 christos else
1723 1.1 christos {
1724 1.1 christos /* We found a non-root-visible type in the hash. If its encoding
1725 1.1 christos is the same, we can reuse it, unless it is a slice. */
1726 1.1 christos
1727 1.1 christos if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0)
1728 1.1 christos {
1729 1.1 christos if (kind != CTF_K_SLICE)
1730 1.1 christos {
1731 1.1 christos ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
1732 1.1 christos return dst_type;
1733 1.1 christos }
1734 1.1 christos }
1735 1.1 christos }
1736 1.1 christos }
1737 1.1 christos }
1738 1.1 christos
1739 1.1.1.2 christos src.ctb_dict = src_fp;
1740 1.1 christos src.ctb_type = src_type;
1741 1.1 christos src.ctb_dtd = NULL;
1742 1.1 christos
1743 1.1.1.2 christos dst.ctb_dict = dst_fp;
1744 1.1 christos dst.ctb_type = dst_type;
1745 1.1 christos dst.ctb_dtd = NULL;
1746 1.1 christos
1747 1.1 christos /* Now perform kind-specific processing. If dst_type is CTF_ERR, then we add
1748 1.1 christos a new type with the same properties as src_type to dst_fp. If dst_type is
1749 1.1 christos not CTF_ERR, then we verify that dst_type has the same attributes as
1750 1.1 christos src_type. We recurse for embedded references. Before we start, we note
1751 1.1 christos that we are processing this type, to prevent infinite recursion: we do not
1752 1.1 christos re-process any type that appears in this list. The list is emptied
1753 1.1 christos wholesale at the end of processing everything in this recursive stack. */
1754 1.1 christos
1755 1.1 christos if (ctf_dynhash_insert (proc_tracking_fp->ctf_add_processing,
1756 1.1 christos (void *) (uintptr_t) src_type, (void *) 1) < 0)
1757 1.1.1.3 christos return ctf_set_typed_errno (dst_fp, ENOMEM);
1758 1.1 christos
1759 1.1 christos switch (kind)
1760 1.1 christos {
1761 1.1 christos case CTF_K_INTEGER:
1762 1.1 christos /* If we found a match we will have either returned it or declared a
1763 1.1 christos conflict. */
1764 1.1 christos dst_type = ctf_add_integer (dst_fp, flag, name, &src_en);
1765 1.1 christos break;
1766 1.1 christos
1767 1.1 christos case CTF_K_FLOAT:
1768 1.1 christos /* If we found a match we will have either returned it or declared a
1769 1.1 christos conflict. */
1770 1.1 christos dst_type = ctf_add_float (dst_fp, flag, name, &src_en);
1771 1.1 christos break;
1772 1.1 christos
1773 1.1 christos case CTF_K_SLICE:
1774 1.1 christos /* We have checked for conflicting encodings: now try to add the
1775 1.1 christos contained type. */
1776 1.1 christos src_type = ctf_type_reference (src_fp, src_type);
1777 1.1 christos src_type = ctf_add_type_internal (dst_fp, src_fp, src_type,
1778 1.1 christos proc_tracking_fp);
1779 1.1 christos
1780 1.1 christos if (src_type == CTF_ERR)
1781 1.1 christos return CTF_ERR; /* errno is set for us. */
1782 1.1 christos
1783 1.1 christos dst_type = ctf_add_slice (dst_fp, flag, src_type, &src_en);
1784 1.1 christos break;
1785 1.1 christos
1786 1.1 christos case CTF_K_POINTER:
1787 1.1 christos case CTF_K_VOLATILE:
1788 1.1 christos case CTF_K_CONST:
1789 1.1 christos case CTF_K_RESTRICT:
1790 1.1 christos src_type = ctf_type_reference (src_fp, src_type);
1791 1.1 christos src_type = ctf_add_type_internal (dst_fp, src_fp, src_type,
1792 1.1 christos proc_tracking_fp);
1793 1.1 christos
1794 1.1 christos if (src_type == CTF_ERR)
1795 1.1 christos return CTF_ERR; /* errno is set for us. */
1796 1.1 christos
1797 1.1 christos dst_type = ctf_add_reftype (dst_fp, flag, src_type, kind);
1798 1.1 christos break;
1799 1.1 christos
1800 1.1 christos case CTF_K_ARRAY:
1801 1.1 christos if (ctf_array_info (src_fp, src_type, &src_ar) != 0)
1802 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ctf_errno (src_fp)));
1803 1.1 christos
1804 1.1 christos src_ar.ctr_contents =
1805 1.1 christos ctf_add_type_internal (dst_fp, src_fp, src_ar.ctr_contents,
1806 1.1 christos proc_tracking_fp);
1807 1.1 christos src_ar.ctr_index = ctf_add_type_internal (dst_fp, src_fp,
1808 1.1 christos src_ar.ctr_index,
1809 1.1 christos proc_tracking_fp);
1810 1.1 christos src_ar.ctr_nelems = src_ar.ctr_nelems;
1811 1.1 christos
1812 1.1 christos if (src_ar.ctr_contents == CTF_ERR || src_ar.ctr_index == CTF_ERR)
1813 1.1 christos return CTF_ERR; /* errno is set for us. */
1814 1.1 christos
1815 1.1 christos if (dst_type != CTF_ERR)
1816 1.1 christos {
1817 1.1 christos if (ctf_array_info (dst_fp, dst_type, &dst_ar) != 0)
1818 1.1 christos return CTF_ERR; /* errno is set for us. */
1819 1.1 christos
1820 1.1 christos if (memcmp (&src_ar, &dst_ar, sizeof (ctf_arinfo_t)))
1821 1.1 christos {
1822 1.1 christos ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
1823 1.1 christos _("conflict for type %s against ID %lx: array info "
1824 1.1 christos "differs, old %lx/%lx/%x; new: %lx/%lx/%x"),
1825 1.1 christos name, dst_type, src_ar.ctr_contents,
1826 1.1 christos src_ar.ctr_index, src_ar.ctr_nelems,
1827 1.1 christos dst_ar.ctr_contents, dst_ar.ctr_index,
1828 1.1 christos dst_ar.ctr_nelems);
1829 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
1830 1.1 christos }
1831 1.1 christos }
1832 1.1 christos else
1833 1.1 christos dst_type = ctf_add_array (dst_fp, flag, &src_ar);
1834 1.1 christos break;
1835 1.1 christos
1836 1.1 christos case CTF_K_FUNCTION:
1837 1.1 christos ctc.ctc_return = ctf_add_type_internal (dst_fp, src_fp,
1838 1.1 christos src_tp->ctt_type,
1839 1.1 christos proc_tracking_fp);
1840 1.1 christos ctc.ctc_argc = 0;
1841 1.1 christos ctc.ctc_flags = 0;
1842 1.1 christos
1843 1.1 christos if (ctc.ctc_return == CTF_ERR)
1844 1.1 christos return CTF_ERR; /* errno is set for us. */
1845 1.1 christos
1846 1.1 christos dst_type = ctf_add_function (dst_fp, flag, &ctc, NULL);
1847 1.1 christos break;
1848 1.1 christos
1849 1.1 christos case CTF_K_STRUCT:
1850 1.1 christos case CTF_K_UNION:
1851 1.1 christos {
1852 1.1.1.2 christos ctf_next_t *i = NULL;
1853 1.1.1.2 christos ssize_t offset;
1854 1.1.1.2 christos const char *membname;
1855 1.1.1.2 christos ctf_id_t src_membtype;
1856 1.1 christos
1857 1.1 christos /* Technically to match a struct or union we need to check both
1858 1.1 christos ways (src members vs. dst, dst members vs. src) but we make
1859 1.1 christos this more optimal by only checking src vs. dst and comparing
1860 1.1 christos the total size of the structure (which we must do anyway)
1861 1.1 christos which covers the possibility of dst members not in src.
1862 1.1 christos This optimization can be defeated for unions, but is so
1863 1.1 christos pathological as to render it irrelevant for our purposes. */
1864 1.1 christos
1865 1.1 christos if (dst_type != CTF_ERR && kind != CTF_K_FORWARD
1866 1.1 christos && dst_kind != CTF_K_FORWARD)
1867 1.1 christos {
1868 1.1 christos if (ctf_type_size (src_fp, src_type) !=
1869 1.1 christos ctf_type_size (dst_fp, dst_type))
1870 1.1 christos {
1871 1.1 christos ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
1872 1.1 christos _("conflict for type %s against ID %lx: union "
1873 1.1 christos "size differs, old %li, new %li"), name,
1874 1.1 christos dst_type, (long) ctf_type_size (src_fp, src_type),
1875 1.1 christos (long) ctf_type_size (dst_fp, dst_type));
1876 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
1877 1.1 christos }
1878 1.1 christos
1879 1.1 christos if (ctf_member_iter (src_fp, src_type, membcmp, &dst))
1880 1.1 christos {
1881 1.1 christos ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
1882 1.1 christos _("conflict for type %s against ID %lx: members "
1883 1.1 christos "differ, see above"), name, dst_type);
1884 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
1885 1.1 christos }
1886 1.1 christos
1887 1.1 christos break;
1888 1.1 christos }
1889 1.1 christos
1890 1.1.1.2 christos dst_type = ctf_add_struct_sized (dst_fp, flag, name,
1891 1.1.1.2 christos ctf_type_size (src_fp, src_type));
1892 1.1 christos if (dst_type == CTF_ERR)
1893 1.1 christos return CTF_ERR; /* errno is set for us. */
1894 1.1 christos
1895 1.1 christos /* Pre-emptively add this struct to the type mapping so that
1896 1.1 christos structures that refer to themselves work. */
1897 1.1 christos ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
1898 1.1 christos
1899 1.1.1.2 christos while ((offset = ctf_member_next (src_fp, src_type, &i, &membname,
1900 1.1.1.2 christos &src_membtype, 0)) >= 0)
1901 1.1 christos {
1902 1.1.1.2 christos ctf_dict_t *dst = dst_fp;
1903 1.1.1.2 christos ctf_id_t dst_membtype = ctf_type_mapping (src_fp, src_membtype, &dst);
1904 1.1 christos
1905 1.1.1.2 christos if (dst_membtype == 0)
1906 1.1 christos {
1907 1.1.1.2 christos dst_membtype = ctf_add_type_internal (dst_fp, src_fp,
1908 1.1.1.2 christos src_membtype,
1909 1.1.1.2 christos proc_tracking_fp);
1910 1.1.1.2 christos if (dst_membtype == CTF_ERR)
1911 1.1 christos {
1912 1.1 christos if (ctf_errno (dst_fp) != ECTF_NONREPRESENTABLE)
1913 1.1.1.2 christos {
1914 1.1.1.2 christos ctf_next_destroy (i);
1915 1.1.1.2 christos break;
1916 1.1.1.2 christos }
1917 1.1 christos }
1918 1.1 christos }
1919 1.1 christos
1920 1.1.1.2 christos if (ctf_add_member_offset (dst_fp, dst_type, membname,
1921 1.1.1.2 christos dst_membtype, offset) < 0)
1922 1.1.1.2 christos {
1923 1.1.1.2 christos ctf_next_destroy (i);
1924 1.1.1.2 christos break;
1925 1.1.1.2 christos }
1926 1.1.1.2 christos }
1927 1.1.1.2 christos if (ctf_errno (src_fp) != ECTF_NEXT_END)
1928 1.1 christos return CTF_ERR; /* errno is set for us. */
1929 1.1 christos break;
1930 1.1 christos }
1931 1.1 christos
1932 1.1 christos case CTF_K_ENUM:
1933 1.1 christos if (dst_type != CTF_ERR && kind != CTF_K_FORWARD
1934 1.1 christos && dst_kind != CTF_K_FORWARD)
1935 1.1 christos {
1936 1.1 christos if (ctf_enum_iter (src_fp, src_type, enumcmp, &dst)
1937 1.1 christos || ctf_enum_iter (dst_fp, dst_type, enumcmp, &src))
1938 1.1 christos {
1939 1.1 christos ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
1940 1.1 christos _("conflict for enum %s against ID %lx: members "
1941 1.1 christos "differ, see above"), name, dst_type);
1942 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
1943 1.1 christos }
1944 1.1 christos }
1945 1.1 christos else
1946 1.1 christos {
1947 1.1 christos dst_type = ctf_add_enum (dst_fp, flag, name);
1948 1.1 christos if ((dst.ctb_type = dst_type) == CTF_ERR
1949 1.1 christos || ctf_enum_iter (src_fp, src_type, enumadd, &dst))
1950 1.1 christos return CTF_ERR; /* errno is set for us */
1951 1.1 christos }
1952 1.1 christos break;
1953 1.1 christos
1954 1.1 christos case CTF_K_FORWARD:
1955 1.1 christos if (dst_type == CTF_ERR)
1956 1.1 christos dst_type = ctf_add_forward (dst_fp, flag, name, forward_kind);
1957 1.1 christos break;
1958 1.1 christos
1959 1.1 christos case CTF_K_TYPEDEF:
1960 1.1 christos src_type = ctf_type_reference (src_fp, src_type);
1961 1.1 christos src_type = ctf_add_type_internal (dst_fp, src_fp, src_type,
1962 1.1 christos proc_tracking_fp);
1963 1.1 christos
1964 1.1 christos if (src_type == CTF_ERR)
1965 1.1 christos return CTF_ERR; /* errno is set for us. */
1966 1.1 christos
1967 1.1 christos /* If dst_type is not CTF_ERR at this point, we should check if
1968 1.1 christos ctf_type_reference(dst_fp, dst_type) != src_type and if so fail with
1969 1.1 christos ECTF_CONFLICT. However, this causes problems with bitness typedefs
1970 1.1 christos that vary based on things like if 32-bit then pid_t is int otherwise
1971 1.1 christos long. We therefore omit this check and assume that if the identically
1972 1.1 christos named typedef already exists in dst_fp, it is correct or
1973 1.1 christos equivalent. */
1974 1.1 christos
1975 1.1 christos if (dst_type == CTF_ERR)
1976 1.1 christos dst_type = ctf_add_typedef (dst_fp, flag, name, src_type);
1977 1.1 christos
1978 1.1 christos break;
1979 1.1 christos
1980 1.1 christos default:
1981 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ECTF_CORRUPT));
1982 1.1 christos }
1983 1.1 christos
1984 1.1 christos if (dst_type != CTF_ERR)
1985 1.1 christos ctf_add_type_mapping (src_fp, orig_src_type, dst_fp, dst_type);
1986 1.1 christos return dst_type;
1987 1.1 christos }
1988 1.1 christos
1989 1.1 christos ctf_id_t
1990 1.1.1.2 christos ctf_add_type (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type)
1991 1.1 christos {
1992 1.1 christos ctf_id_t id;
1993 1.1 christos
1994 1.1 christos if (!src_fp->ctf_add_processing)
1995 1.1 christos src_fp->ctf_add_processing = ctf_dynhash_create (ctf_hash_integer,
1996 1.1 christos ctf_hash_eq_integer,
1997 1.1 christos NULL, NULL);
1998 1.1 christos
1999 1.1 christos /* We store the hash on the source, because it contains only source type IDs:
2000 1.1 christos but callers will invariably expect errors to appear on the dest. */
2001 1.1 christos if (!src_fp->ctf_add_processing)
2002 1.1.1.3 christos return (ctf_set_typed_errno (dst_fp, ENOMEM));
2003 1.1 christos
2004 1.1 christos id = ctf_add_type_internal (dst_fp, src_fp, src_type, src_fp);
2005 1.1 christos ctf_dynhash_empty (src_fp->ctf_add_processing);
2006 1.1 christos
2007 1.1 christos return id;
2008 1.1 christos }
2009