ctf_create.c revision 1.1.1.2 1 1.1 darran /*
2 1.1 darran * CDDL HEADER START
3 1.1 darran *
4 1.1 darran * The contents of this file are subject to the terms of the
5 1.1 darran * Common Development and Distribution License, Version 1.0 only
6 1.1 darran * (the "License"). You may not use this file except in compliance
7 1.1 darran * with the License.
8 1.1 darran *
9 1.1 darran * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 1.1 darran * or http://www.opensolaris.org/os/licensing.
11 1.1 darran * See the License for the specific language governing permissions
12 1.1 darran * and limitations under the License.
13 1.1 darran *
14 1.1 darran * When distributing Covered Code, include this CDDL HEADER in each
15 1.1 darran * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 1.1 darran * If applicable, add the following below this CDDL HEADER, with the
17 1.1 darran * fields enclosed by brackets "[]" replaced with your own identifying
18 1.1 darran * information: Portions Copyright [yyyy] [name of copyright owner]
19 1.1 darran *
20 1.1 darran * CDDL HEADER END
21 1.1 darran */
22 1.1 darran
23 1.1 darran /*
24 1.1 darran * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 1.1 darran * Use is subject to license terms.
26 1.1 darran */
27 1.1.1.2 chs /*
28 1.1.1.2 chs * Copyright (c) 2013, Joyent, Inc. All rights reserved.
29 1.1.1.2 chs */
30 1.1 darran
31 1.1 darran #include <sys/sysmacros.h>
32 1.1 darran #include <sys/param.h>
33 1.1 darran #include <sys/mman.h>
34 1.1 darran #include <ctf_impl.h>
35 1.1.1.2 chs #include <sys/debug.h>
36 1.1 darran
37 1.1 darran /*
38 1.1 darran * This static string is used as the template for initially populating a
39 1.1 darran * dynamic container's string table. We always store \0 in the first byte,
40 1.1 darran * and we use the generic string "PARENT" to mark this container's parent
41 1.1 darran * if one is associated with the container using ctf_import().
42 1.1 darran */
43 1.1 darran static const char _CTF_STRTAB_TEMPLATE[] = "\0PARENT";
44 1.1 darran
45 1.1 darran /*
46 1.1 darran * To create an empty CTF container, we just declare a zeroed header and call
47 1.1 darran * ctf_bufopen() on it. If ctf_bufopen succeeds, we mark the new container r/w
48 1.1 darran * and initialize the dynamic members. We set dtstrlen to 1 to reserve the
49 1.1 darran * first byte of the string table for a \0 byte, and we start assigning type
50 1.1 darran * IDs at 1 because type ID 0 is used as a sentinel.
51 1.1 darran */
52 1.1 darran ctf_file_t *
53 1.1 darran ctf_create(int *errp)
54 1.1 darran {
55 1.1 darran static const ctf_header_t hdr = { { CTF_MAGIC, CTF_VERSION, 0 } };
56 1.1 darran
57 1.1 darran const ulong_t hashlen = 128;
58 1.1 darran ctf_dtdef_t **hash = ctf_alloc(hashlen * sizeof (ctf_dtdef_t *));
59 1.1 darran ctf_sect_t cts;
60 1.1 darran ctf_file_t *fp;
61 1.1 darran
62 1.1 darran if (hash == NULL)
63 1.1 darran return (ctf_set_open_errno(errp, EAGAIN));
64 1.1 darran
65 1.1 darran cts.cts_name = _CTF_SECTION;
66 1.1 darran cts.cts_type = SHT_PROGBITS;
67 1.1 darran cts.cts_flags = 0;
68 1.1.1.2 chs cts.cts_data = (void *)&hdr;
69 1.1 darran cts.cts_size = sizeof (hdr);
70 1.1 darran cts.cts_entsize = 1;
71 1.1 darran cts.cts_offset = 0;
72 1.1 darran
73 1.1 darran if ((fp = ctf_bufopen(&cts, NULL, NULL, errp)) == NULL) {
74 1.1 darran ctf_free(hash, hashlen * sizeof (ctf_dtdef_t *));
75 1.1 darran return (NULL);
76 1.1 darran }
77 1.1 darran
78 1.1 darran fp->ctf_flags |= LCTF_RDWR;
79 1.1 darran fp->ctf_dthashlen = hashlen;
80 1.1 darran bzero(hash, hashlen * sizeof (ctf_dtdef_t *));
81 1.1 darran fp->ctf_dthash = hash;
82 1.1 darran fp->ctf_dtstrlen = sizeof (_CTF_STRTAB_TEMPLATE);
83 1.1 darran fp->ctf_dtnextid = 1;
84 1.1 darran fp->ctf_dtoldid = 0;
85 1.1 darran
86 1.1 darran return (fp);
87 1.1 darran }
88 1.1 darran
89 1.1 darran static uchar_t *
90 1.1 darran ctf_copy_smembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t)
91 1.1 darran {
92 1.1 darran ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
93 1.1 darran ctf_member_t ctm;
94 1.1 darran
95 1.1 darran for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
96 1.1 darran if (dmd->dmd_name) {
97 1.1 darran ctm.ctm_name = soff;
98 1.1 darran soff += strlen(dmd->dmd_name) + 1;
99 1.1 darran } else
100 1.1 darran ctm.ctm_name = 0;
101 1.1 darran
102 1.1 darran ctm.ctm_type = (ushort_t)dmd->dmd_type;
103 1.1 darran ctm.ctm_offset = (ushort_t)dmd->dmd_offset;
104 1.1 darran
105 1.1 darran bcopy(&ctm, t, sizeof (ctm));
106 1.1 darran t += sizeof (ctm);
107 1.1 darran }
108 1.1 darran
109 1.1 darran return (t);
110 1.1 darran }
111 1.1 darran
112 1.1 darran static uchar_t *
113 1.1 darran ctf_copy_lmembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t)
114 1.1 darran {
115 1.1 darran ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
116 1.1 darran ctf_lmember_t ctlm;
117 1.1 darran
118 1.1 darran for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
119 1.1 darran if (dmd->dmd_name) {
120 1.1 darran ctlm.ctlm_name = soff;
121 1.1 darran soff += strlen(dmd->dmd_name) + 1;
122 1.1 darran } else
123 1.1 darran ctlm.ctlm_name = 0;
124 1.1 darran
125 1.1 darran ctlm.ctlm_type = (ushort_t)dmd->dmd_type;
126 1.1 darran ctlm.ctlm_pad = 0;
127 1.1 darran ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI(dmd->dmd_offset);
128 1.1 darran ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO(dmd->dmd_offset);
129 1.1 darran
130 1.1 darran bcopy(&ctlm, t, sizeof (ctlm));
131 1.1 darran t += sizeof (ctlm);
132 1.1 darran }
133 1.1 darran
134 1.1 darran return (t);
135 1.1 darran }
136 1.1 darran
137 1.1 darran static uchar_t *
138 1.1 darran ctf_copy_emembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t)
139 1.1 darran {
140 1.1 darran ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
141 1.1 darran ctf_enum_t cte;
142 1.1 darran
143 1.1 darran for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
144 1.1 darran cte.cte_name = soff;
145 1.1 darran cte.cte_value = dmd->dmd_value;
146 1.1 darran soff += strlen(dmd->dmd_name) + 1;
147 1.1 darran bcopy(&cte, t, sizeof (cte));
148 1.1 darran t += sizeof (cte);
149 1.1 darran }
150 1.1 darran
151 1.1 darran return (t);
152 1.1 darran }
153 1.1 darran
154 1.1 darran static uchar_t *
155 1.1 darran ctf_copy_membnames(ctf_dtdef_t *dtd, uchar_t *s)
156 1.1 darran {
157 1.1 darran ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
158 1.1 darran size_t len;
159 1.1 darran
160 1.1 darran for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
161 1.1 darran if (dmd->dmd_name == NULL)
162 1.1 darran continue; /* skip anonymous members */
163 1.1 darran len = strlen(dmd->dmd_name) + 1;
164 1.1 darran bcopy(dmd->dmd_name, s, len);
165 1.1 darran s += len;
166 1.1 darran }
167 1.1 darran
168 1.1 darran return (s);
169 1.1 darran }
170 1.1 darran
171 1.1 darran /*
172 1.1.1.2 chs * Only types of dyanmic CTF containers contain reference counts. These
173 1.1.1.2 chs * containers are marked RD/WR. Because of that we basically make this a no-op
174 1.1.1.2 chs * for compatability with non-dynamic CTF sections. This is also a no-op for
175 1.1.1.2 chs * types which are not dynamic types. It is the responsibility of the caller to
176 1.1.1.2 chs * make sure it is a valid type. We help that caller out on debug builds.
177 1.1.1.2 chs *
178 1.1.1.2 chs * Note that the reference counts are not maintained for types that are not
179 1.1.1.2 chs * within this container. In other words if we have a type in a parent, that
180 1.1.1.2 chs * will not have its reference count increased. On the flip side, the parent
181 1.1.1.2 chs * will not be allowed to remove dynamic types if it has children.
182 1.1.1.2 chs */
183 1.1.1.2 chs static void
184 1.1.1.2 chs ctf_ref_inc(ctf_file_t *fp, ctf_id_t tid)
185 1.1.1.2 chs {
186 1.1.1.2 chs ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, tid);
187 1.1.1.2 chs
188 1.1.1.2 chs if (dtd == NULL)
189 1.1.1.2 chs return;
190 1.1.1.2 chs
191 1.1.1.2 chs if (!(fp->ctf_flags & LCTF_RDWR))
192 1.1.1.2 chs return;
193 1.1.1.2 chs
194 1.1.1.2 chs dtd->dtd_ref++;
195 1.1.1.2 chs }
196 1.1.1.2 chs
197 1.1.1.2 chs /*
198 1.1.1.2 chs * Just as with ctf_ref_inc, this is a no-op on non-writeable containers and the
199 1.1.1.2 chs * caller should ensure that this is already a valid type.
200 1.1.1.2 chs */
201 1.1.1.2 chs static void
202 1.1.1.2 chs ctf_ref_dec(ctf_file_t *fp, ctf_id_t tid)
203 1.1.1.2 chs {
204 1.1.1.2 chs ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, tid);
205 1.1.1.2 chs
206 1.1.1.2 chs if (dtd == NULL)
207 1.1.1.2 chs return;
208 1.1.1.2 chs
209 1.1.1.2 chs if (!(fp->ctf_flags & LCTF_RDWR))
210 1.1.1.2 chs return;
211 1.1.1.2 chs
212 1.1.1.2 chs ASSERT(dtd->dtd_ref >= 1);
213 1.1.1.2 chs dtd->dtd_ref--;
214 1.1.1.2 chs }
215 1.1.1.2 chs
216 1.1.1.2 chs /*
217 1.1 darran * If the specified CTF container is writable and has been modified, reload
218 1.1 darran * this container with the updated type definitions. In order to make this
219 1.1 darran * code and the rest of libctf as simple as possible, we perform updates by
220 1.1 darran * taking the dynamic type definitions and creating an in-memory CTF file
221 1.1 darran * containing the definitions, and then call ctf_bufopen() on it. This not
222 1.1 darran * only leverages ctf_bufopen(), but also avoids having to bifurcate the rest
223 1.1 darran * of the library code with different lookup paths for static and dynamic
224 1.1 darran * type definitions. We are therefore optimizing greatly for lookup over
225 1.1 darran * update, which we assume will be an uncommon operation. We perform one
226 1.1 darran * extra trick here for the benefit of callers and to keep our code simple:
227 1.1 darran * ctf_bufopen() will return a new ctf_file_t, but we want to keep the fp
228 1.1 darran * constant for the caller, so after ctf_bufopen() returns, we use bcopy to
229 1.1 darran * swap the interior of the old and new ctf_file_t's, and then free the old.
230 1.1.1.2 chs *
231 1.1.1.2 chs * Note that the lists of dynamic types stays around and the resulting container
232 1.1.1.2 chs * is still writeable. Furthermore, the reference counts that are on the dtd's
233 1.1.1.2 chs * are still valid.
234 1.1 darran */
235 1.1 darran int
236 1.1 darran ctf_update(ctf_file_t *fp)
237 1.1 darran {
238 1.1 darran ctf_file_t ofp, *nfp;
239 1.1 darran ctf_header_t hdr;
240 1.1 darran ctf_dtdef_t *dtd;
241 1.1 darran ctf_sect_t cts;
242 1.1 darran
243 1.1 darran uchar_t *s, *s0, *t;
244 1.1 darran size_t size;
245 1.1 darran void *buf;
246 1.1 darran int err;
247 1.1 darran
248 1.1 darran if (!(fp->ctf_flags & LCTF_RDWR))
249 1.1 darran return (ctf_set_errno(fp, ECTF_RDONLY));
250 1.1 darran
251 1.1 darran if (!(fp->ctf_flags & LCTF_DIRTY))
252 1.1 darran return (0); /* no update required */
253 1.1 darran
254 1.1 darran /*
255 1.1 darran * Fill in an initial CTF header. We will leave the label, object,
256 1.1 darran * and function sections empty and only output a header, type section,
257 1.1 darran * and string table. The type section begins at a 4-byte aligned
258 1.1 darran * boundary past the CTF header itself (at relative offset zero).
259 1.1 darran */
260 1.1 darran bzero(&hdr, sizeof (hdr));
261 1.1 darran hdr.cth_magic = CTF_MAGIC;
262 1.1 darran hdr.cth_version = CTF_VERSION;
263 1.1 darran
264 1.1 darran if (fp->ctf_flags & LCTF_CHILD)
265 1.1 darran hdr.cth_parname = 1; /* i.e. _CTF_STRTAB_TEMPLATE[1] */
266 1.1 darran
267 1.1 darran /*
268 1.1 darran * Iterate through the dynamic type definition list and compute the
269 1.1 darran * size of the CTF type section we will need to generate.
270 1.1 darran */
271 1.1 darran for (size = 0, dtd = ctf_list_next(&fp->ctf_dtdefs);
272 1.1 darran dtd != NULL; dtd = ctf_list_next(dtd)) {
273 1.1 darran
274 1.1 darran uint_t kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
275 1.1 darran uint_t vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
276 1.1 darran
277 1.1 darran if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
278 1.1 darran size += sizeof (ctf_stype_t);
279 1.1 darran else
280 1.1 darran size += sizeof (ctf_type_t);
281 1.1 darran
282 1.1 darran switch (kind) {
283 1.1 darran case CTF_K_INTEGER:
284 1.1 darran case CTF_K_FLOAT:
285 1.1 darran size += sizeof (uint_t);
286 1.1 darran break;
287 1.1 darran case CTF_K_ARRAY:
288 1.1 darran size += sizeof (ctf_array_t);
289 1.1 darran break;
290 1.1 darran case CTF_K_FUNCTION:
291 1.1 darran size += sizeof (ushort_t) * (vlen + (vlen & 1));
292 1.1 darran break;
293 1.1 darran case CTF_K_STRUCT:
294 1.1 darran case CTF_K_UNION:
295 1.1 darran if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
296 1.1 darran size += sizeof (ctf_member_t) * vlen;
297 1.1 darran else
298 1.1 darran size += sizeof (ctf_lmember_t) * vlen;
299 1.1 darran break;
300 1.1 darran case CTF_K_ENUM:
301 1.1 darran size += sizeof (ctf_enum_t) * vlen;
302 1.1 darran break;
303 1.1 darran }
304 1.1 darran }
305 1.1 darran
306 1.1 darran /*
307 1.1 darran * Fill in the string table offset and size, compute the size of the
308 1.1 darran * entire CTF buffer we need, and then allocate a new buffer and
309 1.1 darran * bcopy the finished header to the start of the buffer.
310 1.1 darran */
311 1.1 darran hdr.cth_stroff = hdr.cth_typeoff + size;
312 1.1 darran hdr.cth_strlen = fp->ctf_dtstrlen;
313 1.1 darran size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen;
314 1.1 darran
315 1.1 darran if ((buf = ctf_data_alloc(size)) == MAP_FAILED)
316 1.1 darran return (ctf_set_errno(fp, EAGAIN));
317 1.1 darran
318 1.1 darran bcopy(&hdr, buf, sizeof (ctf_header_t));
319 1.1 darran t = (uchar_t *)buf + sizeof (ctf_header_t);
320 1.1 darran s = s0 = (uchar_t *)buf + sizeof (ctf_header_t) + hdr.cth_stroff;
321 1.1 darran
322 1.1 darran bcopy(_CTF_STRTAB_TEMPLATE, s, sizeof (_CTF_STRTAB_TEMPLATE));
323 1.1 darran s += sizeof (_CTF_STRTAB_TEMPLATE);
324 1.1 darran
325 1.1 darran /*
326 1.1 darran * We now take a final lap through the dynamic type definition list and
327 1.1 darran * copy the appropriate type records and strings to the output buffer.
328 1.1 darran */
329 1.1 darran for (dtd = ctf_list_next(&fp->ctf_dtdefs);
330 1.1 darran dtd != NULL; dtd = ctf_list_next(dtd)) {
331 1.1 darran
332 1.1 darran uint_t kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
333 1.1 darran uint_t vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
334 1.1 darran
335 1.1 darran ctf_array_t cta;
336 1.1 darran uint_t encoding;
337 1.1 darran size_t len;
338 1.1 darran
339 1.1 darran if (dtd->dtd_name != NULL) {
340 1.1 darran dtd->dtd_data.ctt_name = (uint_t)(s - s0);
341 1.1 darran len = strlen(dtd->dtd_name) + 1;
342 1.1 darran bcopy(dtd->dtd_name, s, len);
343 1.1 darran s += len;
344 1.1 darran } else
345 1.1 darran dtd->dtd_data.ctt_name = 0;
346 1.1 darran
347 1.1 darran if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
348 1.1 darran len = sizeof (ctf_stype_t);
349 1.1 darran else
350 1.1 darran len = sizeof (ctf_type_t);
351 1.1 darran
352 1.1 darran bcopy(&dtd->dtd_data, t, len);
353 1.1 darran t += len;
354 1.1 darran
355 1.1 darran switch (kind) {
356 1.1 darran case CTF_K_INTEGER:
357 1.1 darran case CTF_K_FLOAT:
358 1.1 darran if (kind == CTF_K_INTEGER) {
359 1.1 darran encoding = CTF_INT_DATA(
360 1.1 darran dtd->dtd_u.dtu_enc.cte_format,
361 1.1 darran dtd->dtd_u.dtu_enc.cte_offset,
362 1.1 darran dtd->dtd_u.dtu_enc.cte_bits);
363 1.1 darran } else {
364 1.1 darran encoding = CTF_FP_DATA(
365 1.1 darran dtd->dtd_u.dtu_enc.cte_format,
366 1.1 darran dtd->dtd_u.dtu_enc.cte_offset,
367 1.1 darran dtd->dtd_u.dtu_enc.cte_bits);
368 1.1 darran }
369 1.1 darran bcopy(&encoding, t, sizeof (encoding));
370 1.1 darran t += sizeof (encoding);
371 1.1 darran break;
372 1.1 darran
373 1.1 darran case CTF_K_ARRAY:
374 1.1 darran cta.cta_contents = (ushort_t)
375 1.1 darran dtd->dtd_u.dtu_arr.ctr_contents;
376 1.1 darran cta.cta_index = (ushort_t)
377 1.1 darran dtd->dtd_u.dtu_arr.ctr_index;
378 1.1 darran cta.cta_nelems = dtd->dtd_u.dtu_arr.ctr_nelems;
379 1.1 darran bcopy(&cta, t, sizeof (cta));
380 1.1 darran t += sizeof (cta);
381 1.1 darran break;
382 1.1 darran
383 1.1 darran case CTF_K_FUNCTION: {
384 1.1 darran ushort_t *argv = (ushort_t *)(uintptr_t)t;
385 1.1 darran uint_t argc;
386 1.1 darran
387 1.1 darran for (argc = 0; argc < vlen; argc++)
388 1.1 darran *argv++ = (ushort_t)dtd->dtd_u.dtu_argv[argc];
389 1.1 darran
390 1.1 darran if (vlen & 1)
391 1.1 darran *argv++ = 0; /* pad to 4-byte boundary */
392 1.1 darran
393 1.1 darran t = (uchar_t *)argv;
394 1.1 darran break;
395 1.1 darran }
396 1.1 darran
397 1.1 darran case CTF_K_STRUCT:
398 1.1 darran case CTF_K_UNION:
399 1.1 darran if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
400 1.1 darran t = ctf_copy_smembers(dtd, (uint_t)(s - s0), t);
401 1.1 darran else
402 1.1 darran t = ctf_copy_lmembers(dtd, (uint_t)(s - s0), t);
403 1.1 darran s = ctf_copy_membnames(dtd, s);
404 1.1 darran break;
405 1.1 darran
406 1.1 darran case CTF_K_ENUM:
407 1.1 darran t = ctf_copy_emembers(dtd, (uint_t)(s - s0), t);
408 1.1 darran s = ctf_copy_membnames(dtd, s);
409 1.1 darran break;
410 1.1 darran }
411 1.1 darran }
412 1.1 darran
413 1.1 darran /*
414 1.1 darran * Finally, we are ready to ctf_bufopen() the new container. If this
415 1.1 darran * is successful, we then switch nfp and fp and free the old container.
416 1.1 darran */
417 1.1 darran ctf_data_protect(buf, size);
418 1.1 darran cts.cts_name = _CTF_SECTION;
419 1.1 darran cts.cts_type = SHT_PROGBITS;
420 1.1 darran cts.cts_flags = 0;
421 1.1 darran cts.cts_data = buf;
422 1.1 darran cts.cts_size = size;
423 1.1 darran cts.cts_entsize = 1;
424 1.1 darran cts.cts_offset = 0;
425 1.1 darran
426 1.1 darran if ((nfp = ctf_bufopen(&cts, NULL, NULL, &err)) == NULL) {
427 1.1 darran ctf_data_free(buf, size);
428 1.1 darran return (ctf_set_errno(fp, err));
429 1.1 darran }
430 1.1 darran
431 1.1 darran (void) ctf_setmodel(nfp, ctf_getmodel(fp));
432 1.1 darran (void) ctf_import(nfp, fp->ctf_parent);
433 1.1 darran
434 1.1 darran nfp->ctf_refcnt = fp->ctf_refcnt;
435 1.1 darran nfp->ctf_flags |= fp->ctf_flags & ~LCTF_DIRTY;
436 1.1 darran nfp->ctf_data.cts_data = NULL; /* force ctf_data_free() on close */
437 1.1 darran nfp->ctf_dthash = fp->ctf_dthash;
438 1.1 darran nfp->ctf_dthashlen = fp->ctf_dthashlen;
439 1.1 darran nfp->ctf_dtdefs = fp->ctf_dtdefs;
440 1.1 darran nfp->ctf_dtstrlen = fp->ctf_dtstrlen;
441 1.1 darran nfp->ctf_dtnextid = fp->ctf_dtnextid;
442 1.1 darran nfp->ctf_dtoldid = fp->ctf_dtnextid - 1;
443 1.1 darran nfp->ctf_specific = fp->ctf_specific;
444 1.1 darran
445 1.1 darran fp->ctf_dthash = NULL;
446 1.1 darran fp->ctf_dthashlen = 0;
447 1.1 darran bzero(&fp->ctf_dtdefs, sizeof (ctf_list_t));
448 1.1 darran
449 1.1 darran bcopy(fp, &ofp, sizeof (ctf_file_t));
450 1.1 darran bcopy(nfp, fp, sizeof (ctf_file_t));
451 1.1 darran bcopy(&ofp, nfp, sizeof (ctf_file_t));
452 1.1 darran
453 1.1 darran /*
454 1.1 darran * Initialize the ctf_lookup_by_name top-level dictionary. We keep an
455 1.1 darran * array of type name prefixes and the corresponding ctf_hash to use.
456 1.1 darran * NOTE: This code must be kept in sync with the code in ctf_bufopen().
457 1.1 darran */
458 1.1 darran fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs;
459 1.1 darran fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions;
460 1.1 darran fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums;
461 1.1 darran fp->ctf_lookups[3].ctl_hash = &fp->ctf_names;
462 1.1 darran
463 1.1 darran nfp->ctf_refcnt = 1; /* force nfp to be freed */
464 1.1 darran ctf_close(nfp);
465 1.1 darran
466 1.1 darran return (0);
467 1.1 darran }
468 1.1 darran
469 1.1 darran void
470 1.1 darran ctf_dtd_insert(ctf_file_t *fp, ctf_dtdef_t *dtd)
471 1.1 darran {
472 1.1 darran ulong_t h = dtd->dtd_type & (fp->ctf_dthashlen - 1);
473 1.1 darran
474 1.1 darran dtd->dtd_hash = fp->ctf_dthash[h];
475 1.1 darran fp->ctf_dthash[h] = dtd;
476 1.1 darran ctf_list_append(&fp->ctf_dtdefs, dtd);
477 1.1 darran }
478 1.1 darran
479 1.1 darran void
480 1.1 darran ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef_t *dtd)
481 1.1 darran {
482 1.1 darran ulong_t h = dtd->dtd_type & (fp->ctf_dthashlen - 1);
483 1.1 darran ctf_dtdef_t *p, **q = &fp->ctf_dthash[h];
484 1.1 darran ctf_dmdef_t *dmd, *nmd;
485 1.1 darran size_t len;
486 1.1.1.2 chs int kind, i;
487 1.1 darran
488 1.1 darran for (p = *q; p != NULL; p = p->dtd_hash) {
489 1.1 darran if (p != dtd)
490 1.1 darran q = &p->dtd_hash;
491 1.1 darran else
492 1.1 darran break;
493 1.1 darran }
494 1.1 darran
495 1.1 darran if (p != NULL)
496 1.1 darran *q = p->dtd_hash;
497 1.1 darran
498 1.1.1.2 chs kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
499 1.1.1.2 chs switch (kind) {
500 1.1 darran case CTF_K_STRUCT:
501 1.1 darran case CTF_K_UNION:
502 1.1 darran case CTF_K_ENUM:
503 1.1 darran for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
504 1.1 darran dmd != NULL; dmd = nmd) {
505 1.1 darran if (dmd->dmd_name != NULL) {
506 1.1 darran len = strlen(dmd->dmd_name) + 1;
507 1.1 darran ctf_free(dmd->dmd_name, len);
508 1.1 darran fp->ctf_dtstrlen -= len;
509 1.1 darran }
510 1.1.1.2 chs if (kind != CTF_K_ENUM)
511 1.1.1.2 chs ctf_ref_dec(fp, dmd->dmd_type);
512 1.1 darran nmd = ctf_list_next(dmd);
513 1.1 darran ctf_free(dmd, sizeof (ctf_dmdef_t));
514 1.1 darran }
515 1.1 darran break;
516 1.1 darran case CTF_K_FUNCTION:
517 1.1.1.2 chs ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
518 1.1.1.2 chs for (i = 0; i < CTF_INFO_VLEN(dtd->dtd_data.ctt_info); i++)
519 1.1.1.2 chs if (dtd->dtd_u.dtu_argv[i] != 0)
520 1.1.1.2 chs ctf_ref_dec(fp, dtd->dtd_u.dtu_argv[i]);
521 1.1 darran ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) *
522 1.1 darran CTF_INFO_VLEN(dtd->dtd_data.ctt_info));
523 1.1 darran break;
524 1.1.1.2 chs case CTF_K_ARRAY:
525 1.1.1.2 chs ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_contents);
526 1.1.1.2 chs ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_index);
527 1.1.1.2 chs break;
528 1.1.1.2 chs case CTF_K_TYPEDEF:
529 1.1.1.2 chs ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
530 1.1.1.2 chs break;
531 1.1.1.2 chs case CTF_K_POINTER:
532 1.1.1.2 chs case CTF_K_VOLATILE:
533 1.1.1.2 chs case CTF_K_CONST:
534 1.1.1.2 chs case CTF_K_RESTRICT:
535 1.1.1.2 chs ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
536 1.1.1.2 chs break;
537 1.1 darran }
538 1.1 darran
539 1.1 darran if (dtd->dtd_name) {
540 1.1 darran len = strlen(dtd->dtd_name) + 1;
541 1.1 darran ctf_free(dtd->dtd_name, len);
542 1.1 darran fp->ctf_dtstrlen -= len;
543 1.1 darran }
544 1.1 darran
545 1.1 darran ctf_list_delete(&fp->ctf_dtdefs, dtd);
546 1.1 darran ctf_free(dtd, sizeof (ctf_dtdef_t));
547 1.1 darran }
548 1.1 darran
549 1.1 darran ctf_dtdef_t *
550 1.1 darran ctf_dtd_lookup(ctf_file_t *fp, ctf_id_t type)
551 1.1 darran {
552 1.1 darran ulong_t h = type & (fp->ctf_dthashlen - 1);
553 1.1 darran ctf_dtdef_t *dtd;
554 1.1 darran
555 1.1 darran if (fp->ctf_dthash == NULL)
556 1.1 darran return (NULL);
557 1.1 darran
558 1.1 darran for (dtd = fp->ctf_dthash[h]; dtd != NULL; dtd = dtd->dtd_hash) {
559 1.1 darran if (dtd->dtd_type == type)
560 1.1 darran break;
561 1.1 darran }
562 1.1 darran
563 1.1 darran return (dtd);
564 1.1 darran }
565 1.1 darran
566 1.1 darran /*
567 1.1 darran * Discard all of the dynamic type definitions that have been added to the
568 1.1 darran * container since the last call to ctf_update(). We locate such types by
569 1.1 darran * scanning the list and deleting elements that have type IDs greater than
570 1.1.1.2 chs * ctf_dtoldid, which is set by ctf_update(), above. Note that to work properly
571 1.1.1.2 chs * with our reference counting schemes, we must delete the dynamic list in
572 1.1.1.2 chs * reverse.
573 1.1 darran */
574 1.1 darran int
575 1.1 darran ctf_discard(ctf_file_t *fp)
576 1.1 darran {
577 1.1 darran ctf_dtdef_t *dtd, *ntd;
578 1.1 darran
579 1.1 darran if (!(fp->ctf_flags & LCTF_RDWR))
580 1.1 darran return (ctf_set_errno(fp, ECTF_RDONLY));
581 1.1 darran
582 1.1 darran if (!(fp->ctf_flags & LCTF_DIRTY))
583 1.1 darran return (0); /* no update required */
584 1.1 darran
585 1.1.1.2 chs for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
586 1.1.1.2 chs ntd = ctf_list_prev(dtd);
587 1.1.1.2 chs if (CTF_TYPE_TO_INDEX(dtd->dtd_type) <= fp->ctf_dtoldid)
588 1.1 darran continue; /* skip types that have been committed */
589 1.1 darran
590 1.1 darran ctf_dtd_delete(fp, dtd);
591 1.1 darran }
592 1.1 darran
593 1.1 darran fp->ctf_dtnextid = fp->ctf_dtoldid + 1;
594 1.1 darran fp->ctf_flags &= ~LCTF_DIRTY;
595 1.1 darran
596 1.1 darran return (0);
597 1.1 darran }
598 1.1 darran
599 1.1 darran static ctf_id_t
600 1.1 darran ctf_add_generic(ctf_file_t *fp, uint_t flag, const char *name, ctf_dtdef_t **rp)
601 1.1 darran {
602 1.1 darran ctf_dtdef_t *dtd;
603 1.1 darran ctf_id_t type;
604 1.1 darran char *s = NULL;
605 1.1 darran
606 1.1 darran if (flag != CTF_ADD_NONROOT && flag != CTF_ADD_ROOT)
607 1.1 darran return (ctf_set_errno(fp, EINVAL));
608 1.1 darran
609 1.1 darran if (!(fp->ctf_flags & LCTF_RDWR))
610 1.1 darran return (ctf_set_errno(fp, ECTF_RDONLY));
611 1.1 darran
612 1.1 darran if (CTF_INDEX_TO_TYPE(fp->ctf_dtnextid, 1) > CTF_MAX_TYPE)
613 1.1 darran return (ctf_set_errno(fp, ECTF_FULL));
614 1.1 darran
615 1.1 darran if ((dtd = ctf_alloc(sizeof (ctf_dtdef_t))) == NULL)
616 1.1 darran return (ctf_set_errno(fp, EAGAIN));
617 1.1 darran
618 1.1 darran if (name != NULL && (s = ctf_strdup(name)) == NULL) {
619 1.1 darran ctf_free(dtd, sizeof (ctf_dtdef_t));
620 1.1 darran return (ctf_set_errno(fp, EAGAIN));
621 1.1 darran }
622 1.1 darran
623 1.1 darran type = fp->ctf_dtnextid++;
624 1.1 darran type = CTF_INDEX_TO_TYPE(type, (fp->ctf_flags & LCTF_CHILD));
625 1.1 darran
626 1.1 darran bzero(dtd, sizeof (ctf_dtdef_t));
627 1.1 darran dtd->dtd_name = s;
628 1.1 darran dtd->dtd_type = type;
629 1.1 darran
630 1.1 darran if (s != NULL)
631 1.1 darran fp->ctf_dtstrlen += strlen(s) + 1;
632 1.1 darran
633 1.1 darran ctf_dtd_insert(fp, dtd);
634 1.1 darran fp->ctf_flags |= LCTF_DIRTY;
635 1.1 darran
636 1.1 darran *rp = dtd;
637 1.1 darran return (type);
638 1.1 darran }
639 1.1 darran
640 1.1 darran /*
641 1.1 darran * When encoding integer sizes, we want to convert a byte count in the range
642 1.1 darran * 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc). The clp2() function
643 1.1 darran * is a clever implementation from "Hacker's Delight" by Henry Warren, Jr.
644 1.1 darran */
645 1.1 darran static size_t
646 1.1 darran clp2(size_t x)
647 1.1 darran {
648 1.1 darran x--;
649 1.1 darran
650 1.1 darran x |= (x >> 1);
651 1.1 darran x |= (x >> 2);
652 1.1 darran x |= (x >> 4);
653 1.1 darran x |= (x >> 8);
654 1.1 darran x |= (x >> 16);
655 1.1 darran
656 1.1 darran return (x + 1);
657 1.1 darran }
658 1.1 darran
659 1.1 darran static ctf_id_t
660 1.1 darran ctf_add_encoded(ctf_file_t *fp, uint_t flag,
661 1.1 darran const char *name, const ctf_encoding_t *ep, uint_t kind)
662 1.1 darran {
663 1.1 darran ctf_dtdef_t *dtd;
664 1.1 darran ctf_id_t type;
665 1.1 darran
666 1.1 darran if (ep == NULL)
667 1.1 darran return (ctf_set_errno(fp, EINVAL));
668 1.1 darran
669 1.1 darran if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
670 1.1 darran return (CTF_ERR); /* errno is set for us */
671 1.1 darran
672 1.1 darran dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0);
673 1.1 darran dtd->dtd_data.ctt_size = clp2(P2ROUNDUP(ep->cte_bits, NBBY) / NBBY);
674 1.1 darran dtd->dtd_u.dtu_enc = *ep;
675 1.1 darran
676 1.1 darran return (type);
677 1.1 darran }
678 1.1 darran
679 1.1 darran static ctf_id_t
680 1.1 darran ctf_add_reftype(ctf_file_t *fp, uint_t flag, ctf_id_t ref, uint_t kind)
681 1.1 darran {
682 1.1 darran ctf_dtdef_t *dtd;
683 1.1 darran ctf_id_t type;
684 1.1 darran
685 1.1 darran if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
686 1.1 darran return (ctf_set_errno(fp, EINVAL));
687 1.1 darran
688 1.1 darran if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
689 1.1 darran return (CTF_ERR); /* errno is set for us */
690 1.1 darran
691 1.1.1.2 chs ctf_ref_inc(fp, ref);
692 1.1.1.2 chs
693 1.1 darran dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0);
694 1.1 darran dtd->dtd_data.ctt_type = (ushort_t)ref;
695 1.1 darran
696 1.1 darran return (type);
697 1.1 darran }
698 1.1 darran
699 1.1 darran ctf_id_t
700 1.1 darran ctf_add_integer(ctf_file_t *fp, uint_t flag,
701 1.1 darran const char *name, const ctf_encoding_t *ep)
702 1.1 darran {
703 1.1 darran return (ctf_add_encoded(fp, flag, name, ep, CTF_K_INTEGER));
704 1.1 darran }
705 1.1 darran
706 1.1 darran ctf_id_t
707 1.1 darran ctf_add_float(ctf_file_t *fp, uint_t flag,
708 1.1 darran const char *name, const ctf_encoding_t *ep)
709 1.1 darran {
710 1.1 darran return (ctf_add_encoded(fp, flag, name, ep, CTF_K_FLOAT));
711 1.1 darran }
712 1.1 darran
713 1.1 darran ctf_id_t
714 1.1 darran ctf_add_pointer(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
715 1.1 darran {
716 1.1 darran return (ctf_add_reftype(fp, flag, ref, CTF_K_POINTER));
717 1.1 darran }
718 1.1 darran
719 1.1 darran ctf_id_t
720 1.1 darran ctf_add_array(ctf_file_t *fp, uint_t flag, const ctf_arinfo_t *arp)
721 1.1 darran {
722 1.1 darran ctf_dtdef_t *dtd;
723 1.1 darran ctf_id_t type;
724 1.1.1.2 chs ctf_file_t *fpd;
725 1.1 darran
726 1.1 darran if (arp == NULL)
727 1.1 darran return (ctf_set_errno(fp, EINVAL));
728 1.1 darran
729 1.1.1.2 chs fpd = fp;
730 1.1.1.2 chs if (ctf_lookup_by_id(&fpd, arp->ctr_contents) == NULL &&
731 1.1.1.2 chs ctf_dtd_lookup(fp, arp->ctr_contents) == NULL)
732 1.1.1.2 chs return (ctf_set_errno(fp, ECTF_BADID));
733 1.1.1.2 chs
734 1.1.1.2 chs fpd = fp;
735 1.1.1.2 chs if (ctf_lookup_by_id(&fpd, arp->ctr_index) == NULL &&
736 1.1.1.2 chs ctf_dtd_lookup(fp, arp->ctr_index) == NULL)
737 1.1.1.2 chs return (ctf_set_errno(fp, ECTF_BADID));
738 1.1.1.2 chs
739 1.1 darran if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
740 1.1 darran return (CTF_ERR); /* errno is set for us */
741 1.1 darran
742 1.1 darran dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, flag, 0);
743 1.1 darran dtd->dtd_data.ctt_size = 0;
744 1.1 darran dtd->dtd_u.dtu_arr = *arp;
745 1.1.1.2 chs ctf_ref_inc(fp, arp->ctr_contents);
746 1.1.1.2 chs ctf_ref_inc(fp, arp->ctr_index);
747 1.1 darran
748 1.1 darran return (type);
749 1.1 darran }
750 1.1 darran
751 1.1 darran int
752 1.1 darran ctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
753 1.1 darran {
754 1.1.1.2 chs ctf_file_t *fpd;
755 1.1 darran ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
756 1.1 darran
757 1.1 darran if (!(fp->ctf_flags & LCTF_RDWR))
758 1.1 darran return (ctf_set_errno(fp, ECTF_RDONLY));
759 1.1 darran
760 1.1 darran if (dtd == NULL || CTF_INFO_KIND(dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
761 1.1 darran return (ctf_set_errno(fp, ECTF_BADID));
762 1.1 darran
763 1.1.1.2 chs fpd = fp;
764 1.1.1.2 chs if (ctf_lookup_by_id(&fpd, arp->ctr_contents) == NULL &&
765 1.1.1.2 chs ctf_dtd_lookup(fp, arp->ctr_contents) == NULL)
766 1.1.1.2 chs return (ctf_set_errno(fp, ECTF_BADID));
767 1.1.1.2 chs
768 1.1.1.2 chs fpd = fp;
769 1.1.1.2 chs if (ctf_lookup_by_id(&fpd, arp->ctr_index) == NULL &&
770 1.1.1.2 chs ctf_dtd_lookup(fp, arp->ctr_index) == NULL)
771 1.1.1.2 chs return (ctf_set_errno(fp, ECTF_BADID));
772 1.1.1.2 chs
773 1.1.1.2 chs ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_contents);
774 1.1.1.2 chs ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_index);
775 1.1 darran fp->ctf_flags |= LCTF_DIRTY;
776 1.1 darran dtd->dtd_u.dtu_arr = *arp;
777 1.1.1.2 chs ctf_ref_inc(fp, arp->ctr_contents);
778 1.1.1.2 chs ctf_ref_inc(fp, arp->ctr_index);
779 1.1 darran
780 1.1 darran return (0);
781 1.1 darran }
782 1.1 darran
783 1.1 darran ctf_id_t
784 1.1 darran ctf_add_function(ctf_file_t *fp, uint_t flag,
785 1.1 darran const ctf_funcinfo_t *ctc, const ctf_id_t *argv)
786 1.1 darran {
787 1.1 darran ctf_dtdef_t *dtd;
788 1.1 darran ctf_id_t type;
789 1.1 darran uint_t vlen;
790 1.1.1.2 chs int i;
791 1.1 darran ctf_id_t *vdat = NULL;
792 1.1.1.2 chs ctf_file_t *fpd;
793 1.1 darran
794 1.1 darran if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0 ||
795 1.1 darran (ctc->ctc_argc != 0 && argv == NULL))
796 1.1 darran return (ctf_set_errno(fp, EINVAL));
797 1.1 darran
798 1.1 darran vlen = ctc->ctc_argc;
799 1.1 darran if (ctc->ctc_flags & CTF_FUNC_VARARG)
800 1.1 darran vlen++; /* add trailing zero to indicate varargs (see below) */
801 1.1 darran
802 1.1 darran if (vlen > CTF_MAX_VLEN)
803 1.1 darran return (ctf_set_errno(fp, EOVERFLOW));
804 1.1 darran
805 1.1.1.2 chs fpd = fp;
806 1.1.1.2 chs if (ctf_lookup_by_id(&fpd, ctc->ctc_return) == NULL &&
807 1.1.1.2 chs ctf_dtd_lookup(fp, ctc->ctc_return) == NULL)
808 1.1.1.2 chs return (ctf_set_errno(fp, ECTF_BADID));
809 1.1.1.2 chs
810 1.1.1.2 chs for (i = 0; i < ctc->ctc_argc; i++) {
811 1.1.1.2 chs fpd = fp;
812 1.1.1.2 chs if (ctf_lookup_by_id(&fpd, argv[i]) == NULL &&
813 1.1.1.2 chs ctf_dtd_lookup(fp, argv[i]) == NULL)
814 1.1.1.2 chs return (ctf_set_errno(fp, ECTF_BADID));
815 1.1.1.2 chs }
816 1.1.1.2 chs
817 1.1 darran if (vlen != 0 && (vdat = ctf_alloc(sizeof (ctf_id_t) * vlen)) == NULL)
818 1.1 darran return (ctf_set_errno(fp, EAGAIN));
819 1.1 darran
820 1.1 darran if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR) {
821 1.1 darran ctf_free(vdat, sizeof (ctf_id_t) * vlen);
822 1.1 darran return (CTF_ERR); /* errno is set for us */
823 1.1 darran }
824 1.1 darran
825 1.1 darran dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, flag, vlen);
826 1.1 darran dtd->dtd_data.ctt_type = (ushort_t)ctc->ctc_return;
827 1.1 darran
828 1.1.1.2 chs ctf_ref_inc(fp, ctc->ctc_return);
829 1.1.1.2 chs for (i = 0; i < ctc->ctc_argc; i++)
830 1.1.1.2 chs ctf_ref_inc(fp, argv[i]);
831 1.1.1.2 chs
832 1.1 darran bcopy(argv, vdat, sizeof (ctf_id_t) * ctc->ctc_argc);
833 1.1 darran if (ctc->ctc_flags & CTF_FUNC_VARARG)
834 1.1 darran vdat[vlen - 1] = 0; /* add trailing zero to indicate varargs */
835 1.1 darran dtd->dtd_u.dtu_argv = vdat;
836 1.1 darran
837 1.1 darran return (type);
838 1.1 darran }
839 1.1 darran
840 1.1 darran ctf_id_t
841 1.1 darran ctf_add_struct(ctf_file_t *fp, uint_t flag, const char *name)
842 1.1 darran {
843 1.1 darran ctf_hash_t *hp = &fp->ctf_structs;
844 1.1 darran ctf_helem_t *hep = NULL;
845 1.1 darran ctf_dtdef_t *dtd;
846 1.1 darran ctf_id_t type;
847 1.1 darran
848 1.1 darran if (name != NULL)
849 1.1 darran hep = ctf_hash_lookup(hp, fp, name, strlen(name));
850 1.1 darran
851 1.1 darran if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD)
852 1.1 darran dtd = ctf_dtd_lookup(fp, type = hep->h_type);
853 1.1 darran else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
854 1.1 darran return (CTF_ERR); /* errno is set for us */
855 1.1 darran
856 1.1 darran dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, flag, 0);
857 1.1 darran dtd->dtd_data.ctt_size = 0;
858 1.1 darran
859 1.1 darran return (type);
860 1.1 darran }
861 1.1 darran
862 1.1 darran ctf_id_t
863 1.1 darran ctf_add_union(ctf_file_t *fp, uint_t flag, const char *name)
864 1.1 darran {
865 1.1 darran ctf_hash_t *hp = &fp->ctf_unions;
866 1.1 darran ctf_helem_t *hep = NULL;
867 1.1 darran ctf_dtdef_t *dtd;
868 1.1 darran ctf_id_t type;
869 1.1 darran
870 1.1 darran if (name != NULL)
871 1.1 darran hep = ctf_hash_lookup(hp, fp, name, strlen(name));
872 1.1 darran
873 1.1 darran if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD)
874 1.1 darran dtd = ctf_dtd_lookup(fp, type = hep->h_type);
875 1.1 darran else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
876 1.1 darran return (CTF_ERR); /* errno is set for us */
877 1.1 darran
878 1.1 darran dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, flag, 0);
879 1.1 darran dtd->dtd_data.ctt_size = 0;
880 1.1 darran
881 1.1 darran return (type);
882 1.1 darran }
883 1.1 darran
884 1.1 darran ctf_id_t
885 1.1 darran ctf_add_enum(ctf_file_t *fp, uint_t flag, const char *name)
886 1.1 darran {
887 1.1 darran ctf_hash_t *hp = &fp->ctf_enums;
888 1.1 darran ctf_helem_t *hep = NULL;
889 1.1 darran ctf_dtdef_t *dtd;
890 1.1 darran ctf_id_t type;
891 1.1 darran
892 1.1 darran if (name != NULL)
893 1.1 darran hep = ctf_hash_lookup(hp, fp, name, strlen(name));
894 1.1 darran
895 1.1 darran if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD)
896 1.1 darran dtd = ctf_dtd_lookup(fp, type = hep->h_type);
897 1.1 darran else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
898 1.1 darran return (CTF_ERR); /* errno is set for us */
899 1.1 darran
900 1.1 darran dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, flag, 0);
901 1.1 darran dtd->dtd_data.ctt_size = fp->ctf_dmodel->ctd_int;
902 1.1 darran
903 1.1 darran return (type);
904 1.1 darran }
905 1.1 darran
906 1.1 darran ctf_id_t
907 1.1 darran ctf_add_forward(ctf_file_t *fp, uint_t flag, const char *name, uint_t kind)
908 1.1 darran {
909 1.1 darran ctf_hash_t *hp;
910 1.1 darran ctf_helem_t *hep;
911 1.1 darran ctf_dtdef_t *dtd;
912 1.1 darran ctf_id_t type;
913 1.1 darran
914 1.1 darran switch (kind) {
915 1.1 darran case CTF_K_STRUCT:
916 1.1 darran hp = &fp->ctf_structs;
917 1.1 darran break;
918 1.1 darran case CTF_K_UNION:
919 1.1 darran hp = &fp->ctf_unions;
920 1.1 darran break;
921 1.1 darran case CTF_K_ENUM:
922 1.1 darran hp = &fp->ctf_enums;
923 1.1 darran break;
924 1.1 darran default:
925 1.1 darran return (ctf_set_errno(fp, ECTF_NOTSUE));
926 1.1 darran }
927 1.1 darran
928 1.1 darran /*
929 1.1 darran * If the type is already defined or exists as a forward tag, just
930 1.1 darran * return the ctf_id_t of the existing definition.
931 1.1 darran */
932 1.1 darran if (name != NULL && (hep = ctf_hash_lookup(hp,
933 1.1 darran fp, name, strlen(name))) != NULL)
934 1.1 darran return (hep->h_type);
935 1.1 darran
936 1.1 darran if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
937 1.1 darran return (CTF_ERR); /* errno is set for us */
938 1.1 darran
939 1.1 darran dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FORWARD, flag, 0);
940 1.1 darran dtd->dtd_data.ctt_type = kind;
941 1.1 darran
942 1.1 darran return (type);
943 1.1 darran }
944 1.1 darran
945 1.1 darran ctf_id_t
946 1.1 darran ctf_add_typedef(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref)
947 1.1 darran {
948 1.1 darran ctf_dtdef_t *dtd;
949 1.1 darran ctf_id_t type;
950 1.1.1.2 chs ctf_file_t *fpd;
951 1.1 darran
952 1.1.1.2 chs fpd = fp;
953 1.1.1.2 chs if (ref == CTF_ERR || (ctf_lookup_by_id(&fpd, ref) == NULL &&
954 1.1.1.2 chs ctf_dtd_lookup(fp, ref) == NULL))
955 1.1 darran return (ctf_set_errno(fp, EINVAL));
956 1.1 darran
957 1.1 darran if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
958 1.1 darran return (CTF_ERR); /* errno is set for us */
959 1.1 darran
960 1.1 darran dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, flag, 0);
961 1.1 darran dtd->dtd_data.ctt_type = (ushort_t)ref;
962 1.1.1.2 chs ctf_ref_inc(fp, ref);
963 1.1 darran
964 1.1 darran return (type);
965 1.1 darran }
966 1.1 darran
967 1.1 darran ctf_id_t
968 1.1 darran ctf_add_volatile(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
969 1.1 darran {
970 1.1 darran return (ctf_add_reftype(fp, flag, ref, CTF_K_VOLATILE));
971 1.1 darran }
972 1.1 darran
973 1.1 darran ctf_id_t
974 1.1 darran ctf_add_const(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
975 1.1 darran {
976 1.1 darran return (ctf_add_reftype(fp, flag, ref, CTF_K_CONST));
977 1.1 darran }
978 1.1 darran
979 1.1 darran ctf_id_t
980 1.1 darran ctf_add_restrict(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
981 1.1 darran {
982 1.1 darran return (ctf_add_reftype(fp, flag, ref, CTF_K_RESTRICT));
983 1.1 darran }
984 1.1 darran
985 1.1 darran int
986 1.1 darran ctf_add_enumerator(ctf_file_t *fp, ctf_id_t enid, const char *name, int value)
987 1.1 darran {
988 1.1 darran ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, enid);
989 1.1 darran ctf_dmdef_t *dmd;
990 1.1 darran
991 1.1 darran uint_t kind, vlen, root;
992 1.1 darran char *s;
993 1.1 darran
994 1.1 darran if (name == NULL)
995 1.1 darran return (ctf_set_errno(fp, EINVAL));
996 1.1 darran
997 1.1 darran if (!(fp->ctf_flags & LCTF_RDWR))
998 1.1 darran return (ctf_set_errno(fp, ECTF_RDONLY));
999 1.1 darran
1000 1.1 darran if (dtd == NULL)
1001 1.1 darran return (ctf_set_errno(fp, ECTF_BADID));
1002 1.1 darran
1003 1.1 darran kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
1004 1.1 darran root = CTF_INFO_ISROOT(dtd->dtd_data.ctt_info);
1005 1.1 darran vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
1006 1.1 darran
1007 1.1 darran if (kind != CTF_K_ENUM)
1008 1.1 darran return (ctf_set_errno(fp, ECTF_NOTENUM));
1009 1.1 darran
1010 1.1 darran if (vlen == CTF_MAX_VLEN)
1011 1.1 darran return (ctf_set_errno(fp, ECTF_DTFULL));
1012 1.1 darran
1013 1.1 darran for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
1014 1.1 darran dmd != NULL; dmd = ctf_list_next(dmd)) {
1015 1.1 darran if (strcmp(dmd->dmd_name, name) == 0)
1016 1.1 darran return (ctf_set_errno(fp, ECTF_DUPMEMBER));
1017 1.1 darran }
1018 1.1 darran
1019 1.1 darran if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)
1020 1.1 darran return (ctf_set_errno(fp, EAGAIN));
1021 1.1 darran
1022 1.1 darran if ((s = ctf_strdup(name)) == NULL) {
1023 1.1 darran ctf_free(dmd, sizeof (ctf_dmdef_t));
1024 1.1 darran return (ctf_set_errno(fp, EAGAIN));
1025 1.1 darran }
1026 1.1 darran
1027 1.1 darran dmd->dmd_name = s;
1028 1.1 darran dmd->dmd_type = CTF_ERR;
1029 1.1 darran dmd->dmd_offset = 0;
1030 1.1 darran dmd->dmd_value = value;
1031 1.1 darran
1032 1.1 darran dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1);
1033 1.1 darran ctf_list_append(&dtd->dtd_u.dtu_members, dmd);
1034 1.1 darran
1035 1.1 darran fp->ctf_dtstrlen += strlen(s) + 1;
1036 1.1 darran fp->ctf_flags |= LCTF_DIRTY;
1037 1.1 darran
1038 1.1 darran return (0);
1039 1.1 darran }
1040 1.1 darran
1041 1.1 darran int
1042 1.1 darran ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type)
1043 1.1 darran {
1044 1.1 darran ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, souid);
1045 1.1 darran ctf_dmdef_t *dmd;
1046 1.1 darran
1047 1.1 darran ssize_t msize, malign, ssize;
1048 1.1 darran uint_t kind, vlen, root;
1049 1.1 darran char *s = NULL;
1050 1.1 darran
1051 1.1 darran if (!(fp->ctf_flags & LCTF_RDWR))
1052 1.1 darran return (ctf_set_errno(fp, ECTF_RDONLY));
1053 1.1 darran
1054 1.1 darran if (dtd == NULL)
1055 1.1 darran return (ctf_set_errno(fp, ECTF_BADID));
1056 1.1 darran
1057 1.1 darran kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
1058 1.1 darran root = CTF_INFO_ISROOT(dtd->dtd_data.ctt_info);
1059 1.1 darran vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
1060 1.1 darran
1061 1.1 darran if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
1062 1.1 darran return (ctf_set_errno(fp, ECTF_NOTSOU));
1063 1.1 darran
1064 1.1 darran if (vlen == CTF_MAX_VLEN)
1065 1.1 darran return (ctf_set_errno(fp, ECTF_DTFULL));
1066 1.1 darran
1067 1.1 darran if (name != NULL) {
1068 1.1 darran for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
1069 1.1 darran dmd != NULL; dmd = ctf_list_next(dmd)) {
1070 1.1 darran if (dmd->dmd_name != NULL &&
1071 1.1 darran strcmp(dmd->dmd_name, name) == 0)
1072 1.1 darran return (ctf_set_errno(fp, ECTF_DUPMEMBER));
1073 1.1 darran }
1074 1.1 darran }
1075 1.1 darran
1076 1.1 darran if ((msize = ctf_type_size(fp, type)) == CTF_ERR ||
1077 1.1 darran (malign = ctf_type_align(fp, type)) == CTF_ERR)
1078 1.1 darran return (CTF_ERR); /* errno is set for us */
1079 1.1 darran
1080 1.1 darran if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)
1081 1.1 darran return (ctf_set_errno(fp, EAGAIN));
1082 1.1 darran
1083 1.1 darran if (name != NULL && (s = ctf_strdup(name)) == NULL) {
1084 1.1 darran ctf_free(dmd, sizeof (ctf_dmdef_t));
1085 1.1 darran return (ctf_set_errno(fp, EAGAIN));
1086 1.1 darran }
1087 1.1 darran
1088 1.1 darran dmd->dmd_name = s;
1089 1.1 darran dmd->dmd_type = type;
1090 1.1 darran dmd->dmd_value = -1;
1091 1.1 darran
1092 1.1 darran if (kind == CTF_K_STRUCT && vlen != 0) {
1093 1.1 darran ctf_dmdef_t *lmd = ctf_list_prev(&dtd->dtd_u.dtu_members);
1094 1.1 darran ctf_id_t ltype = ctf_type_resolve(fp, lmd->dmd_type);
1095 1.1 darran size_t off = lmd->dmd_offset;
1096 1.1 darran
1097 1.1 darran ctf_encoding_t linfo;
1098 1.1 darran ssize_t lsize;
1099 1.1 darran
1100 1.1 darran if (ctf_type_encoding(fp, ltype, &linfo) != CTF_ERR)
1101 1.1 darran off += linfo.cte_bits;
1102 1.1 darran else if ((lsize = ctf_type_size(fp, ltype)) != CTF_ERR)
1103 1.1 darran off += lsize * NBBY;
1104 1.1 darran
1105 1.1 darran /*
1106 1.1 darran * Round up the offset of the end of the last member to the
1107 1.1 darran * next byte boundary, convert 'off' to bytes, and then round
1108 1.1 darran * it up again to the next multiple of the alignment required
1109 1.1 darran * by the new member. Finally, convert back to bits and store
1110 1.1 darran * the result in dmd_offset. Technically we could do more
1111 1.1 darran * efficient packing if the new member is a bit-field, but
1112 1.1 darran * we're the "compiler" and ANSI says we can do as we choose.
1113 1.1 darran */
1114 1.1 darran off = roundup(off, NBBY) / NBBY;
1115 1.1 darran off = roundup(off, MAX(malign, 1));
1116 1.1 darran dmd->dmd_offset = off * NBBY;
1117 1.1 darran ssize = off + msize;
1118 1.1 darran } else {
1119 1.1 darran dmd->dmd_offset = 0;
1120 1.1 darran ssize = ctf_get_ctt_size(fp, &dtd->dtd_data, NULL, NULL);
1121 1.1 darran ssize = MAX(ssize, msize);
1122 1.1 darran }
1123 1.1 darran
1124 1.1 darran if (ssize > CTF_MAX_SIZE) {
1125 1.1 darran dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
1126 1.1 darran dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(ssize);
1127 1.1 darran dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(ssize);
1128 1.1 darran } else
1129 1.1 darran dtd->dtd_data.ctt_size = (ushort_t)ssize;
1130 1.1 darran
1131 1.1 darran dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1);
1132 1.1 darran ctf_list_append(&dtd->dtd_u.dtu_members, dmd);
1133 1.1 darran
1134 1.1 darran if (s != NULL)
1135 1.1 darran fp->ctf_dtstrlen += strlen(s) + 1;
1136 1.1 darran
1137 1.1.1.2 chs ctf_ref_inc(fp, type);
1138 1.1.1.2 chs fp->ctf_flags |= LCTF_DIRTY;
1139 1.1.1.2 chs return (0);
1140 1.1.1.2 chs }
1141 1.1.1.2 chs
1142 1.1.1.2 chs /*
1143 1.1.1.2 chs * This removes a type from the dynamic section. This will fail if the type is
1144 1.1.1.2 chs * referenced by another type. Note that the CTF ID is never reused currently by
1145 1.1.1.2 chs * CTF. Note that if this container is a parent container then we just outright
1146 1.1.1.2 chs * refuse to remove the type. There currently is no notion of searching for the
1147 1.1.1.2 chs * ctf_dtdef_t in parent containers. If there is, then this constraint could
1148 1.1.1.2 chs * become finer grained.
1149 1.1.1.2 chs */
1150 1.1.1.2 chs int
1151 1.1.1.2 chs ctf_delete_type(ctf_file_t *fp, ctf_id_t type)
1152 1.1.1.2 chs {
1153 1.1.1.2 chs ctf_file_t *fpd;
1154 1.1.1.2 chs ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
1155 1.1.1.2 chs
1156 1.1.1.2 chs if (!(fp->ctf_flags & LCTF_RDWR))
1157 1.1.1.2 chs return (ctf_set_errno(fp, ECTF_RDONLY));
1158 1.1.1.2 chs
1159 1.1.1.2 chs /*
1160 1.1.1.2 chs * We want to give as useful an errno as possible. That means that we
1161 1.1.1.2 chs * want to distinguish between a type which does not exist and one for
1162 1.1.1.2 chs * which the type is not dynamic.
1163 1.1.1.2 chs */
1164 1.1.1.2 chs fpd = fp;
1165 1.1.1.2 chs if (ctf_lookup_by_id(&fpd, type) == NULL &&
1166 1.1.1.2 chs ctf_dtd_lookup(fp, type) == NULL)
1167 1.1.1.2 chs return (CTF_ERR); /* errno is set for us */
1168 1.1.1.2 chs
1169 1.1.1.2 chs if (dtd == NULL)
1170 1.1.1.2 chs return (ctf_set_errno(fp, ECTF_NOTDYN));
1171 1.1.1.2 chs
1172 1.1.1.2 chs if (dtd->dtd_ref != 0 || fp->ctf_refcnt > 1)
1173 1.1.1.2 chs return (ctf_set_errno(fp, ECTF_REFERENCED));
1174 1.1.1.2 chs
1175 1.1.1.2 chs ctf_dtd_delete(fp, dtd);
1176 1.1 darran fp->ctf_flags |= LCTF_DIRTY;
1177 1.1 darran return (0);
1178 1.1 darran }
1179 1.1 darran
1180 1.1 darran static int
1181 1.1 darran enumcmp(const char *name, int value, void *arg)
1182 1.1 darran {
1183 1.1 darran ctf_bundle_t *ctb = arg;
1184 1.1 darran int bvalue;
1185 1.1 darran
1186 1.1 darran return (ctf_enum_value(ctb->ctb_file, ctb->ctb_type,
1187 1.1 darran name, &bvalue) == CTF_ERR || value != bvalue);
1188 1.1 darran }
1189 1.1 darran
1190 1.1 darran static int
1191 1.1 darran enumadd(const char *name, int value, void *arg)
1192 1.1 darran {
1193 1.1 darran ctf_bundle_t *ctb = arg;
1194 1.1 darran
1195 1.1 darran return (ctf_add_enumerator(ctb->ctb_file, ctb->ctb_type,
1196 1.1 darran name, value) == CTF_ERR);
1197 1.1 darran }
1198 1.1 darran
1199 1.1 darran /*ARGSUSED*/
1200 1.1 darran static int
1201 1.1 darran membcmp(const char *name, ctf_id_t type, ulong_t offset, void *arg)
1202 1.1 darran {
1203 1.1 darran ctf_bundle_t *ctb = arg;
1204 1.1 darran ctf_membinfo_t ctm;
1205 1.1 darran
1206 1.1 darran return (ctf_member_info(ctb->ctb_file, ctb->ctb_type,
1207 1.1 darran name, &ctm) == CTF_ERR || ctm.ctm_offset != offset);
1208 1.1 darran }
1209 1.1 darran
1210 1.1 darran static int
1211 1.1 darran membadd(const char *name, ctf_id_t type, ulong_t offset, void *arg)
1212 1.1 darran {
1213 1.1 darran ctf_bundle_t *ctb = arg;
1214 1.1 darran ctf_dmdef_t *dmd;
1215 1.1 darran char *s = NULL;
1216 1.1 darran
1217 1.1 darran if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)
1218 1.1 darran return (ctf_set_errno(ctb->ctb_file, EAGAIN));
1219 1.1 darran
1220 1.1 darran if (name != NULL && (s = ctf_strdup(name)) == NULL) {
1221 1.1 darran ctf_free(dmd, sizeof (ctf_dmdef_t));
1222 1.1 darran return (ctf_set_errno(ctb->ctb_file, EAGAIN));
1223 1.1 darran }
1224 1.1 darran
1225 1.1 darran /*
1226 1.1 darran * For now, dmd_type is copied as the src_fp's type; it is reset to an
1227 1.1 darran * equivalent dst_fp type by a final loop in ctf_add_type(), below.
1228 1.1 darran */
1229 1.1 darran dmd->dmd_name = s;
1230 1.1 darran dmd->dmd_type = type;
1231 1.1 darran dmd->dmd_offset = offset;
1232 1.1 darran dmd->dmd_value = -1;
1233 1.1 darran
1234 1.1 darran ctf_list_append(&ctb->ctb_dtd->dtd_u.dtu_members, dmd);
1235 1.1 darran
1236 1.1 darran if (s != NULL)
1237 1.1 darran ctb->ctb_file->ctf_dtstrlen += strlen(s) + 1;
1238 1.1 darran
1239 1.1 darran ctb->ctb_file->ctf_flags |= LCTF_DIRTY;
1240 1.1 darran return (0);
1241 1.1 darran }
1242 1.1 darran
1243 1.1 darran /*
1244 1.1 darran * The ctf_add_type routine is used to copy a type from a source CTF container
1245 1.1 darran * to a dynamic destination container. This routine operates recursively by
1246 1.1 darran * following the source type's links and embedded member types. If the
1247 1.1 darran * destination container already contains a named type which has the same
1248 1.1 darran * attributes, then we succeed and return this type but no changes occur.
1249 1.1 darran */
1250 1.1 darran ctf_id_t
1251 1.1 darran ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
1252 1.1 darran {
1253 1.1 darran ctf_id_t dst_type = CTF_ERR;
1254 1.1 darran uint_t dst_kind = CTF_K_UNKNOWN;
1255 1.1 darran
1256 1.1 darran const ctf_type_t *tp;
1257 1.1 darran const char *name;
1258 1.1 darran uint_t kind, flag, vlen;
1259 1.1 darran
1260 1.1 darran ctf_bundle_t src, dst;
1261 1.1 darran ctf_encoding_t src_en, dst_en;
1262 1.1 darran ctf_arinfo_t src_ar, dst_ar;
1263 1.1 darran
1264 1.1 darran ctf_dtdef_t *dtd;
1265 1.1 darran ctf_funcinfo_t ctc;
1266 1.1 darran ssize_t size;
1267 1.1 darran
1268 1.1 darran ctf_hash_t *hp;
1269 1.1 darran ctf_helem_t *hep;
1270 1.1 darran
1271 1.1.1.2 chs if (dst_fp == src_fp)
1272 1.1.1.2 chs return (src_type);
1273 1.1.1.2 chs
1274 1.1 darran if (!(dst_fp->ctf_flags & LCTF_RDWR))
1275 1.1 darran return (ctf_set_errno(dst_fp, ECTF_RDONLY));
1276 1.1 darran
1277 1.1 darran if ((tp = ctf_lookup_by_id(&src_fp, src_type)) == NULL)
1278 1.1 darran return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));
1279 1.1 darran
1280 1.1 darran name = ctf_strptr(src_fp, tp->ctt_name);
1281 1.1 darran kind = LCTF_INFO_KIND(src_fp, tp->ctt_info);
1282 1.1 darran flag = LCTF_INFO_ROOT(src_fp, tp->ctt_info);
1283 1.1 darran vlen = LCTF_INFO_VLEN(src_fp, tp->ctt_info);
1284 1.1 darran
1285 1.1 darran switch (kind) {
1286 1.1 darran case CTF_K_STRUCT:
1287 1.1 darran hp = &dst_fp->ctf_structs;
1288 1.1 darran break;
1289 1.1 darran case CTF_K_UNION:
1290 1.1 darran hp = &dst_fp->ctf_unions;
1291 1.1 darran break;
1292 1.1 darran case CTF_K_ENUM:
1293 1.1 darran hp = &dst_fp->ctf_enums;
1294 1.1 darran break;
1295 1.1 darran default:
1296 1.1 darran hp = &dst_fp->ctf_names;
1297 1.1 darran break;
1298 1.1 darran }
1299 1.1 darran
1300 1.1 darran /*
1301 1.1 darran * If the source type has a name and is a root type (visible at the
1302 1.1 darran * top-level scope), lookup the name in the destination container and
1303 1.1 darran * verify that it is of the same kind before we do anything else.
1304 1.1 darran */
1305 1.1 darran if ((flag & CTF_ADD_ROOT) && name[0] != '\0' &&
1306 1.1 darran (hep = ctf_hash_lookup(hp, dst_fp, name, strlen(name))) != NULL) {
1307 1.1 darran dst_type = (ctf_id_t)hep->h_type;
1308 1.1 darran dst_kind = ctf_type_kind(dst_fp, dst_type);
1309 1.1 darran }
1310 1.1 darran
1311 1.1 darran /*
1312 1.1 darran * If an identically named dst_type exists, fail with ECTF_CONFLICT
1313 1.1 darran * unless dst_type is a forward declaration and src_type is a struct,
1314 1.1 darran * union, or enum (i.e. the definition of the previous forward decl).
1315 1.1 darran */
1316 1.1.1.2 chs if (dst_type != CTF_ERR && dst_kind != kind) {
1317 1.1.1.2 chs if (dst_kind != CTF_K_FORWARD || (kind != CTF_K_ENUM &&
1318 1.1.1.2 chs kind != CTF_K_STRUCT && kind != CTF_K_UNION))
1319 1.1.1.2 chs return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1320 1.1.1.2 chs else
1321 1.1.1.2 chs dst_type = CTF_ERR;
1322 1.1.1.2 chs }
1323 1.1 darran
1324 1.1 darran /*
1325 1.1 darran * If the non-empty name was not found in the appropriate hash, search
1326 1.1 darran * the list of pending dynamic definitions that are not yet committed.
1327 1.1 darran * If a matching name and kind are found, assume this is the type that
1328 1.1 darran * we are looking for. This is necessary to permit ctf_add_type() to
1329 1.1 darran * operate recursively on entities such as a struct that contains a
1330 1.1 darran * pointer member that refers to the same struct type.
1331 1.1.1.2 chs *
1332 1.1.1.2 chs * In the case of integer and floating point types, we match using the
1333 1.1.1.2 chs * type encoding as well - else we may incorrectly return a bitfield
1334 1.1.1.2 chs * type, for instance.
1335 1.1 darran */
1336 1.1 darran if (dst_type == CTF_ERR && name[0] != '\0') {
1337 1.1 darran for (dtd = ctf_list_prev(&dst_fp->ctf_dtdefs); dtd != NULL &&
1338 1.1.1.2 chs CTF_TYPE_TO_INDEX(dtd->dtd_type) > dst_fp->ctf_dtoldid;
1339 1.1 darran dtd = ctf_list_prev(dtd)) {
1340 1.1.1.2 chs if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) != kind ||
1341 1.1.1.2 chs dtd->dtd_name == NULL ||
1342 1.1.1.2 chs strcmp(dtd->dtd_name, name) != 0)
1343 1.1.1.2 chs continue;
1344 1.1.1.2 chs if (kind == CTF_K_INTEGER || kind == CTF_K_FLOAT) {
1345 1.1.1.2 chs if (ctf_type_encoding(src_fp, src_type,
1346 1.1.1.2 chs &src_en) != 0)
1347 1.1.1.2 chs continue;
1348 1.1.1.2 chs if (bcmp(&src_en, &dtd->dtd_u.dtu_enc,
1349 1.1.1.2 chs sizeof (ctf_encoding_t)) != 0)
1350 1.1.1.2 chs continue;
1351 1.1.1.2 chs }
1352 1.1.1.2 chs return (dtd->dtd_type);
1353 1.1 darran }
1354 1.1 darran }
1355 1.1 darran
1356 1.1 darran src.ctb_file = src_fp;
1357 1.1 darran src.ctb_type = src_type;
1358 1.1 darran src.ctb_dtd = NULL;
1359 1.1 darran
1360 1.1 darran dst.ctb_file = dst_fp;
1361 1.1 darran dst.ctb_type = dst_type;
1362 1.1 darran dst.ctb_dtd = NULL;
1363 1.1 darran
1364 1.1 darran /*
1365 1.1 darran * Now perform kind-specific processing. If dst_type is CTF_ERR, then
1366 1.1 darran * we add a new type with the same properties as src_type to dst_fp.
1367 1.1 darran * If dst_type is not CTF_ERR, then we verify that dst_type has the
1368 1.1 darran * same attributes as src_type. We recurse for embedded references.
1369 1.1 darran */
1370 1.1 darran switch (kind) {
1371 1.1 darran case CTF_K_INTEGER:
1372 1.1 darran case CTF_K_FLOAT:
1373 1.1 darran if (ctf_type_encoding(src_fp, src_type, &src_en) != 0)
1374 1.1 darran return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));
1375 1.1 darran
1376 1.1 darran if (dst_type != CTF_ERR) {
1377 1.1 darran if (ctf_type_encoding(dst_fp, dst_type, &dst_en) != 0)
1378 1.1 darran return (CTF_ERR); /* errno is set for us */
1379 1.1 darran
1380 1.1 darran if (bcmp(&src_en, &dst_en, sizeof (ctf_encoding_t)))
1381 1.1 darran return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1382 1.1 darran
1383 1.1 darran } else if (kind == CTF_K_INTEGER) {
1384 1.1 darran dst_type = ctf_add_integer(dst_fp, flag, name, &src_en);
1385 1.1 darran } else
1386 1.1 darran dst_type = ctf_add_float(dst_fp, flag, name, &src_en);
1387 1.1 darran break;
1388 1.1 darran
1389 1.1 darran case CTF_K_POINTER:
1390 1.1 darran case CTF_K_VOLATILE:
1391 1.1 darran case CTF_K_CONST:
1392 1.1 darran case CTF_K_RESTRICT:
1393 1.1 darran src_type = ctf_type_reference(src_fp, src_type);
1394 1.1 darran src_type = ctf_add_type(dst_fp, src_fp, src_type);
1395 1.1 darran
1396 1.1 darran if (src_type == CTF_ERR)
1397 1.1 darran return (CTF_ERR); /* errno is set for us */
1398 1.1 darran
1399 1.1 darran dst_type = ctf_add_reftype(dst_fp, flag, src_type, kind);
1400 1.1 darran break;
1401 1.1 darran
1402 1.1 darran case CTF_K_ARRAY:
1403 1.1 darran if (ctf_array_info(src_fp, src_type, &src_ar) == CTF_ERR)
1404 1.1 darran return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));
1405 1.1 darran
1406 1.1 darran src_ar.ctr_contents =
1407 1.1 darran ctf_add_type(dst_fp, src_fp, src_ar.ctr_contents);
1408 1.1 darran src_ar.ctr_index =
1409 1.1 darran ctf_add_type(dst_fp, src_fp, src_ar.ctr_index);
1410 1.1 darran src_ar.ctr_nelems = src_ar.ctr_nelems;
1411 1.1 darran
1412 1.1 darran if (src_ar.ctr_contents == CTF_ERR ||
1413 1.1 darran src_ar.ctr_index == CTF_ERR)
1414 1.1 darran return (CTF_ERR); /* errno is set for us */
1415 1.1 darran
1416 1.1 darran if (dst_type != CTF_ERR) {
1417 1.1 darran if (ctf_array_info(dst_fp, dst_type, &dst_ar) != 0)
1418 1.1 darran return (CTF_ERR); /* errno is set for us */
1419 1.1 darran
1420 1.1 darran if (bcmp(&src_ar, &dst_ar, sizeof (ctf_arinfo_t)))
1421 1.1 darran return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1422 1.1 darran } else
1423 1.1 darran dst_type = ctf_add_array(dst_fp, flag, &src_ar);
1424 1.1 darran break;
1425 1.1 darran
1426 1.1 darran case CTF_K_FUNCTION:
1427 1.1 darran ctc.ctc_return = ctf_add_type(dst_fp, src_fp, tp->ctt_type);
1428 1.1 darran ctc.ctc_argc = 0;
1429 1.1 darran ctc.ctc_flags = 0;
1430 1.1 darran
1431 1.1 darran if (ctc.ctc_return == CTF_ERR)
1432 1.1 darran return (CTF_ERR); /* errno is set for us */
1433 1.1 darran
1434 1.1 darran dst_type = ctf_add_function(dst_fp, flag, &ctc, NULL);
1435 1.1 darran break;
1436 1.1 darran
1437 1.1 darran case CTF_K_STRUCT:
1438 1.1 darran case CTF_K_UNION: {
1439 1.1 darran ctf_dmdef_t *dmd;
1440 1.1 darran int errs = 0;
1441 1.1 darran
1442 1.1 darran /*
1443 1.1 darran * Technically to match a struct or union we need to check both
1444 1.1 darran * ways (src members vs. dst, dst members vs. src) but we make
1445 1.1 darran * this more optimal by only checking src vs. dst and comparing
1446 1.1 darran * the total size of the structure (which we must do anyway)
1447 1.1 darran * which covers the possibility of dst members not in src.
1448 1.1 darran * This optimization can be defeated for unions, but is so
1449 1.1 darran * pathological as to render it irrelevant for our purposes.
1450 1.1 darran */
1451 1.1 darran if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) {
1452 1.1 darran if (ctf_type_size(src_fp, src_type) !=
1453 1.1 darran ctf_type_size(dst_fp, dst_type))
1454 1.1 darran return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1455 1.1 darran
1456 1.1 darran if (ctf_member_iter(src_fp, src_type, membcmp, &dst))
1457 1.1 darran return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1458 1.1 darran
1459 1.1 darran break;
1460 1.1 darran }
1461 1.1 darran
1462 1.1 darran /*
1463 1.1 darran * Unlike the other cases, copying structs and unions is done
1464 1.1 darran * manually so as to avoid repeated lookups in ctf_add_member
1465 1.1 darran * and to ensure the exact same member offsets as in src_type.
1466 1.1 darran */
1467 1.1 darran dst_type = ctf_add_generic(dst_fp, flag, name, &dtd);
1468 1.1 darran if (dst_type == CTF_ERR)
1469 1.1 darran return (CTF_ERR); /* errno is set for us */
1470 1.1 darran
1471 1.1 darran dst.ctb_type = dst_type;
1472 1.1 darran dst.ctb_dtd = dtd;
1473 1.1 darran
1474 1.1 darran if (ctf_member_iter(src_fp, src_type, membadd, &dst) != 0)
1475 1.1 darran errs++; /* increment errs and fail at bottom of case */
1476 1.1 darran
1477 1.1 darran if ((size = ctf_type_size(src_fp, src_type)) > CTF_MAX_SIZE) {
1478 1.1 darran dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
1479 1.1 darran dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);
1480 1.1 darran dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);
1481 1.1 darran } else
1482 1.1 darran dtd->dtd_data.ctt_size = (ushort_t)size;
1483 1.1 darran
1484 1.1 darran dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, vlen);
1485 1.1 darran
1486 1.1 darran /*
1487 1.1 darran * Make a final pass through the members changing each dmd_type
1488 1.1 darran * (a src_fp type) to an equivalent type in dst_fp. We pass
1489 1.1 darran * through all members, leaving any that fail set to CTF_ERR.
1490 1.1 darran */
1491 1.1 darran for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
1492 1.1 darran dmd != NULL; dmd = ctf_list_next(dmd)) {
1493 1.1 darran if ((dmd->dmd_type = ctf_add_type(dst_fp, src_fp,
1494 1.1 darran dmd->dmd_type)) == CTF_ERR)
1495 1.1 darran errs++;
1496 1.1 darran }
1497 1.1 darran
1498 1.1 darran if (errs)
1499 1.1 darran return (CTF_ERR); /* errno is set for us */
1500 1.1.1.2 chs
1501 1.1.1.2 chs /*
1502 1.1.1.2 chs * Now that we know that we can't fail, we go through and bump
1503 1.1.1.2 chs * all the reference counts on the member types.
1504 1.1.1.2 chs */
1505 1.1.1.2 chs for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
1506 1.1.1.2 chs dmd != NULL; dmd = ctf_list_next(dmd))
1507 1.1.1.2 chs ctf_ref_inc(dst_fp, dmd->dmd_type);
1508 1.1 darran break;
1509 1.1 darran }
1510 1.1 darran
1511 1.1 darran case CTF_K_ENUM:
1512 1.1 darran if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) {
1513 1.1 darran if (ctf_enum_iter(src_fp, src_type, enumcmp, &dst) ||
1514 1.1 darran ctf_enum_iter(dst_fp, dst_type, enumcmp, &src))
1515 1.1 darran return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1516 1.1 darran } else {
1517 1.1 darran dst_type = ctf_add_enum(dst_fp, flag, name);
1518 1.1 darran if ((dst.ctb_type = dst_type) == CTF_ERR ||
1519 1.1 darran ctf_enum_iter(src_fp, src_type, enumadd, &dst))
1520 1.1 darran return (CTF_ERR); /* errno is set for us */
1521 1.1 darran }
1522 1.1 darran break;
1523 1.1 darran
1524 1.1 darran case CTF_K_FORWARD:
1525 1.1 darran if (dst_type == CTF_ERR) {
1526 1.1 darran dst_type = ctf_add_forward(dst_fp,
1527 1.1 darran flag, name, CTF_K_STRUCT); /* assume STRUCT */
1528 1.1 darran }
1529 1.1 darran break;
1530 1.1 darran
1531 1.1 darran case CTF_K_TYPEDEF:
1532 1.1 darran src_type = ctf_type_reference(src_fp, src_type);
1533 1.1 darran src_type = ctf_add_type(dst_fp, src_fp, src_type);
1534 1.1 darran
1535 1.1 darran if (src_type == CTF_ERR)
1536 1.1 darran return (CTF_ERR); /* errno is set for us */
1537 1.1 darran
1538 1.1 darran /*
1539 1.1 darran * If dst_type is not CTF_ERR at this point, we should check if
1540 1.1 darran * ctf_type_reference(dst_fp, dst_type) != src_type and if so
1541 1.1 darran * fail with ECTF_CONFLICT. However, this causes problems with
1542 1.1 darran * <sys/types.h> typedefs that vary based on things like if
1543 1.1 darran * _ILP32x then pid_t is int otherwise long. We therefore omit
1544 1.1 darran * this check and assume that if the identically named typedef
1545 1.1 darran * already exists in dst_fp, it is correct or equivalent.
1546 1.1 darran */
1547 1.1 darran if (dst_type == CTF_ERR) {
1548 1.1 darran dst_type = ctf_add_typedef(dst_fp, flag,
1549 1.1 darran name, src_type);
1550 1.1 darran }
1551 1.1 darran break;
1552 1.1 darran
1553 1.1 darran default:
1554 1.1 darran return (ctf_set_errno(dst_fp, ECTF_CORRUPT));
1555 1.1 darran }
1556 1.1 darran
1557 1.1 darran return (dst_type);
1558 1.1 darran }
1559