1 | /* |
2 | * CDDL HEADER START |
3 | * |
4 | * The contents of this file are subject to the terms of the |
5 | * Common Development and Distribution License, Version 1.0 only |
6 | * (the "License"). You may not use this file except in compliance |
7 | * with the License. |
8 | * |
9 | * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
10 | * or http://www.opensolaris.org/os/licensing. |
11 | * See the License for the specific language governing permissions |
12 | * and limitations under the License. |
13 | * |
14 | * When distributing Covered Code, include this CDDL HEADER in each |
15 | * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
16 | * If applicable, add the following below this CDDL HEADER, with the |
17 | * fields enclosed by brackets "[]" replaced with your own identifying |
18 | * information: Portions Copyright [yyyy] [name of copyright owner] |
19 | * |
20 | * CDDL HEADER END |
21 | */ |
22 | |
23 | #ifdef HAVE_NBTOOL_CONFIG_H |
24 | #include "nbtool_config.h" |
25 | #endif |
26 | /* |
27 | * Copyright 2006 Sun Microsystems, Inc. All rights reserved. |
28 | * Use is subject to license terms. |
29 | */ |
30 | /* |
31 | * Copyright (c) 2013, Joyent, Inc. All rights reserved. |
32 | */ |
33 | |
34 | #include <ctf_impl.h> |
35 | #include <sys/mman.h> |
36 | #include <sys/zmod.h> |
37 | |
38 | static const ctf_dmodel_t _libctf_models[] = { |
39 | { "ILP32" , CTF_MODEL_ILP32, 4, 1, 2, 4, 4 }, |
40 | { "LP64" , CTF_MODEL_LP64, 8, 1, 2, 4, 8 }, |
41 | { NULL, 0, 0, 0, 0, 0, 0 } |
42 | }; |
43 | |
44 | const char _CTF_SECTION[] = ".SUNW_ctf" ; |
45 | const char _CTF_NULLSTR[] = "" ; |
46 | |
47 | int _libctf_version = CTF_VERSION; /* library client version */ |
48 | int _libctf_debug = 0; /* debugging messages enabled */ |
49 | |
50 | static ushort_t |
51 | get_kind_v1(ushort_t info) |
52 | { |
53 | return (CTF_INFO_KIND_V1(info)); |
54 | } |
55 | |
56 | static ushort_t |
57 | get_kind_v2(ushort_t info) |
58 | { |
59 | return (CTF_INFO_KIND(info)); |
60 | } |
61 | |
62 | static ushort_t |
63 | get_root_v1(ushort_t info) |
64 | { |
65 | return (CTF_INFO_ISROOT_V1(info)); |
66 | } |
67 | |
68 | static ushort_t |
69 | get_root_v2(ushort_t info) |
70 | { |
71 | return (CTF_INFO_ISROOT(info)); |
72 | } |
73 | |
74 | static ushort_t |
75 | get_vlen_v1(ushort_t info) |
76 | { |
77 | return (CTF_INFO_VLEN_V1(info)); |
78 | } |
79 | |
80 | static ushort_t |
81 | get_vlen_v2(ushort_t info) |
82 | { |
83 | return (CTF_INFO_VLEN(info)); |
84 | } |
85 | |
86 | static const ctf_fileops_t ctf_fileops[] = { |
87 | { NULL, NULL, NULL }, |
88 | { get_kind_v1, get_root_v1, get_vlen_v1 }, |
89 | { get_kind_v2, get_root_v2, get_vlen_v2 }, |
90 | }; |
91 | |
92 | /* |
93 | * Convert a 32-bit ELF symbol into GElf (Elf64) and return a pointer to it. |
94 | */ |
95 | static Elf64_Sym * |
96 | sym_to_gelf(const Elf32_Sym *src, Elf64_Sym *dst) |
97 | { |
98 | dst->st_name = src->st_name; |
99 | dst->st_value = src->st_value; |
100 | dst->st_size = src->st_size; |
101 | dst->st_info = src->st_info; |
102 | dst->st_other = src->st_other; |
103 | dst->st_shndx = src->st_shndx; |
104 | |
105 | return (dst); |
106 | } |
107 | |
108 | /* |
109 | * Initialize the symtab translation table by filling each entry with the |
110 | * offset of the CTF type or function data corresponding to each STT_FUNC or |
111 | * STT_OBJECT entry in the symbol table. |
112 | */ |
113 | static int |
114 | init_symtab(ctf_file_t *fp, const ctf_header_t *hp, |
115 | const ctf_sect_t *sp, const ctf_sect_t *strp) |
116 | { |
117 | const uchar_t *symp = sp->cts_data; |
118 | uint_t *xp = fp->ctf_sxlate; |
119 | uint_t *xend = xp + fp->ctf_nsyms; |
120 | |
121 | uint_t objtoff = hp->cth_objtoff; |
122 | uint_t funcoff = hp->cth_funcoff; |
123 | |
124 | ushort_t info, vlen; |
125 | Elf64_Sym sym, *gsp; |
126 | const char *name; |
127 | |
128 | /* |
129 | * The CTF data object and function type sections are ordered to match |
130 | * the relative order of the respective symbol types in the symtab. |
131 | * If no type information is available for a symbol table entry, a |
132 | * pad is inserted in the CTF section. As a further optimization, |
133 | * anonymous or undefined symbols are omitted from the CTF data. |
134 | */ |
135 | for (; xp < xend; xp++, symp += sp->cts_entsize) { |
136 | if (sp->cts_entsize == sizeof (Elf32_Sym)) |
137 | gsp = sym_to_gelf((Elf32_Sym *)(uintptr_t)symp, &sym); |
138 | else |
139 | gsp = (Elf64_Sym *)(uintptr_t)symp; |
140 | |
141 | if (gsp->st_name < strp->cts_size) |
142 | name = (const char *)strp->cts_data + gsp->st_name; |
143 | else |
144 | name = _CTF_NULLSTR; |
145 | |
146 | if (gsp->st_name == 0 || gsp->st_shndx == SHN_UNDEF || |
147 | strcmp(name, "_START_" ) == 0 || |
148 | strcmp(name, "_END_" ) == 0) { |
149 | *xp = -1u; |
150 | continue; |
151 | } |
152 | |
153 | switch (ELF64_ST_TYPE(gsp->st_info)) { |
154 | case STT_OBJECT: |
155 | if (objtoff >= hp->cth_funcoff || |
156 | (gsp->st_shndx == SHN_ABS && gsp->st_value == 0)) { |
157 | *xp = -1u; |
158 | break; |
159 | } |
160 | |
161 | *xp = objtoff; |
162 | objtoff += sizeof (ushort_t); |
163 | break; |
164 | |
165 | case STT_FUNC: |
166 | if (funcoff >= hp->cth_typeoff) { |
167 | *xp = -1u; |
168 | break; |
169 | } |
170 | |
171 | *xp = funcoff; |
172 | |
173 | info = *(ushort_t *)((uintptr_t)fp->ctf_buf + funcoff); |
174 | vlen = LCTF_INFO_VLEN(fp, info); |
175 | |
176 | /* |
177 | * If we encounter a zero pad at the end, just skip it. |
178 | * Otherwise skip over the function and its return type |
179 | * (+2) and the argument list (vlen). |
180 | */ |
181 | if (LCTF_INFO_KIND(fp, info) == CTF_K_UNKNOWN && |
182 | vlen == 0) |
183 | funcoff += sizeof (ushort_t); /* skip pad */ |
184 | else |
185 | funcoff += sizeof (ushort_t) * (vlen + 2); |
186 | break; |
187 | |
188 | default: |
189 | *xp = -1u; |
190 | break; |
191 | } |
192 | } |
193 | |
194 | ctf_dprintf("loaded %lu symtab entries\n" , fp->ctf_nsyms); |
195 | return (0); |
196 | } |
197 | |
198 | /* |
199 | * Initialize the type ID translation table with the byte offset of each type, |
200 | * and initialize the hash tables of each named type. |
201 | */ |
202 | static int |
203 | init_types(ctf_file_t *fp, const ctf_header_t *cth) |
204 | { |
205 | /* LINTED - pointer alignment */ |
206 | const ctf_type_t *tbuf = (const ctf_type_t *)(fp->ctf_buf + cth->cth_typeoff); |
207 | /* LINTED - pointer alignment */ |
208 | const ctf_type_t *tend = (const ctf_type_t *)(fp->ctf_buf + cth->cth_stroff); |
209 | |
210 | ulong_t pop[CTF_K_MAX + 1] = { 0 }; |
211 | const ctf_type_t *tp; |
212 | ctf_hash_t *hp; |
213 | ushort_t id, dst; |
214 | uint_t *xp; |
215 | |
216 | /* |
217 | * We initially determine whether the container is a child or a parent |
218 | * based on the value of cth_parname. To support containers that pre- |
219 | * date cth_parname, we also scan the types themselves for references |
220 | * to values in the range reserved for child types in our first pass. |
221 | */ |
222 | int child = cth->cth_parname != 0; |
223 | int nlstructs = 0, nlunions = 0; |
224 | int err; |
225 | |
226 | /* |
227 | * We make two passes through the entire type section. In this first |
228 | * pass, we count the number of each type and the total number of types. |
229 | */ |
230 | for (tp = tbuf; tp < tend; fp->ctf_typemax++) { |
231 | ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info); |
232 | ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info); |
233 | ssize_t size, increment; |
234 | |
235 | size_t vbytes; |
236 | uint_t n; |
237 | |
238 | (void) ctf_get_ctt_size(fp, tp, &size, &increment); |
239 | |
240 | switch (kind) { |
241 | case CTF_K_INTEGER: |
242 | case CTF_K_FLOAT: |
243 | vbytes = sizeof (uint_t); |
244 | break; |
245 | case CTF_K_ARRAY: |
246 | vbytes = sizeof (ctf_array_t); |
247 | break; |
248 | case CTF_K_FUNCTION: |
249 | vbytes = sizeof (ushort_t) * (vlen + (vlen & 1)); |
250 | break; |
251 | case CTF_K_STRUCT: |
252 | case CTF_K_UNION: |
253 | if (fp->ctf_version == CTF_VERSION_1 || |
254 | size < CTF_LSTRUCT_THRESH) { |
255 | ctf_member_t *mp = (ctf_member_t *) |
256 | ((uintptr_t)tp + increment); |
257 | |
258 | vbytes = sizeof (ctf_member_t) * vlen; |
259 | for (n = vlen; n != 0; n--, mp++) |
260 | child |= CTF_TYPE_ISCHILD(mp->ctm_type); |
261 | } else { |
262 | ctf_lmember_t *lmp = (ctf_lmember_t *) |
263 | ((uintptr_t)tp + increment); |
264 | |
265 | vbytes = sizeof (ctf_lmember_t) * vlen; |
266 | for (n = vlen; n != 0; n--, lmp++) |
267 | child |= |
268 | CTF_TYPE_ISCHILD(lmp->ctlm_type); |
269 | } |
270 | break; |
271 | case CTF_K_ENUM: |
272 | vbytes = sizeof (ctf_enum_t) * vlen; |
273 | break; |
274 | case CTF_K_FORWARD: |
275 | /* |
276 | * For forward declarations, ctt_type is the CTF_K_* |
277 | * kind for the tag, so bump that population count too. |
278 | * If ctt_type is unknown, treat the tag as a struct. |
279 | */ |
280 | if (tp->ctt_type == CTF_K_UNKNOWN || |
281 | tp->ctt_type >= CTF_K_MAX) |
282 | pop[CTF_K_STRUCT]++; |
283 | else |
284 | pop[tp->ctt_type]++; |
285 | /*FALLTHRU*/ |
286 | case CTF_K_UNKNOWN: |
287 | vbytes = 0; |
288 | break; |
289 | case CTF_K_POINTER: |
290 | case CTF_K_TYPEDEF: |
291 | case CTF_K_VOLATILE: |
292 | case CTF_K_CONST: |
293 | case CTF_K_RESTRICT: |
294 | child |= CTF_TYPE_ISCHILD(tp->ctt_type); |
295 | vbytes = 0; |
296 | break; |
297 | default: |
298 | ctf_dprintf("detected invalid CTF kind -- %u\n" , kind); |
299 | return (ECTF_CORRUPT); |
300 | } |
301 | tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes); |
302 | pop[kind]++; |
303 | } |
304 | |
305 | /* |
306 | * If we detected a reference to a child type ID, then we know this |
307 | * container is a child and may have a parent's types imported later. |
308 | */ |
309 | if (child) { |
310 | ctf_dprintf("CTF container %p is a child\n" , (void *)fp); |
311 | fp->ctf_flags |= LCTF_CHILD; |
312 | } else |
313 | ctf_dprintf("CTF container %p is a parent\n" , (void *)fp); |
314 | |
315 | /* |
316 | * Now that we've counted up the number of each type, we can allocate |
317 | * the hash tables, type translation table, and pointer table. |
318 | */ |
319 | if ((err = ctf_hash_create(&fp->ctf_structs, pop[CTF_K_STRUCT])) != 0) |
320 | return (err); |
321 | |
322 | if ((err = ctf_hash_create(&fp->ctf_unions, pop[CTF_K_UNION])) != 0) |
323 | return (err); |
324 | |
325 | if ((err = ctf_hash_create(&fp->ctf_enums, pop[CTF_K_ENUM])) != 0) |
326 | return (err); |
327 | |
328 | if ((err = ctf_hash_create(&fp->ctf_names, |
329 | pop[CTF_K_INTEGER] + pop[CTF_K_FLOAT] + pop[CTF_K_FUNCTION] + |
330 | pop[CTF_K_TYPEDEF] + pop[CTF_K_POINTER] + pop[CTF_K_VOLATILE] + |
331 | pop[CTF_K_CONST] + pop[CTF_K_RESTRICT])) != 0) |
332 | return (err); |
333 | |
334 | fp->ctf_txlate = ctf_alloc(sizeof (uint_t) * (fp->ctf_typemax + 1)); |
335 | fp->ctf_ptrtab = ctf_alloc(sizeof (ushort_t) * (fp->ctf_typemax + 1)); |
336 | |
337 | if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL) |
338 | return (EAGAIN); /* memory allocation failed */ |
339 | |
340 | xp = fp->ctf_txlate; |
341 | *xp++ = 0; /* type id 0 is used as a sentinel value */ |
342 | |
343 | bzero(fp->ctf_txlate, sizeof (uint_t) * (fp->ctf_typemax + 1)); |
344 | bzero(fp->ctf_ptrtab, sizeof (ushort_t) * (fp->ctf_typemax + 1)); |
345 | |
346 | /* |
347 | * In the second pass through the types, we fill in each entry of the |
348 | * type and pointer tables and add names to the appropriate hashes. |
349 | */ |
350 | for (id = 1, tp = tbuf; tp < tend; xp++, id++) { |
351 | ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info); |
352 | ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info); |
353 | ssize_t size, increment; |
354 | |
355 | const char *name; |
356 | size_t vbytes; |
357 | ctf_helem_t *hep; |
358 | ctf_encoding_t cte; |
359 | |
360 | (void) ctf_get_ctt_size(fp, tp, &size, &increment); |
361 | name = ctf_strptr(fp, tp->ctt_name); |
362 | |
363 | switch (kind) { |
364 | case CTF_K_INTEGER: |
365 | case CTF_K_FLOAT: |
366 | /* |
367 | * Only insert a new integer base type definition if |
368 | * this type name has not been defined yet. We re-use |
369 | * the names with different encodings for bit-fields. |
370 | */ |
371 | if ((hep = ctf_hash_lookup(&fp->ctf_names, fp, |
372 | name, strlen(name))) == NULL) { |
373 | err = ctf_hash_insert(&fp->ctf_names, fp, |
374 | CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); |
375 | if (err != 0 && err != ECTF_STRTAB) |
376 | return (err); |
377 | } else if (ctf_type_encoding(fp, hep->h_type, |
378 | &cte) == 0 && cte.cte_bits == 0) { |
379 | /* |
380 | * Work-around SOS8 stabs bug: replace existing |
381 | * intrinsic w/ same name if it was zero bits. |
382 | */ |
383 | hep->h_type = CTF_INDEX_TO_TYPE(id, child); |
384 | } |
385 | vbytes = sizeof (uint_t); |
386 | break; |
387 | |
388 | case CTF_K_ARRAY: |
389 | vbytes = sizeof (ctf_array_t); |
390 | break; |
391 | |
392 | case CTF_K_FUNCTION: |
393 | err = ctf_hash_insert(&fp->ctf_names, fp, |
394 | CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); |
395 | if (err != 0 && err != ECTF_STRTAB) |
396 | return (err); |
397 | vbytes = sizeof (ushort_t) * (vlen + (vlen & 1)); |
398 | break; |
399 | |
400 | case CTF_K_STRUCT: |
401 | err = ctf_hash_define(&fp->ctf_structs, fp, |
402 | CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); |
403 | |
404 | if (err != 0 && err != ECTF_STRTAB) |
405 | return (err); |
406 | |
407 | if (fp->ctf_version == CTF_VERSION_1 || |
408 | size < CTF_LSTRUCT_THRESH) |
409 | vbytes = sizeof (ctf_member_t) * vlen; |
410 | else { |
411 | vbytes = sizeof (ctf_lmember_t) * vlen; |
412 | nlstructs++; |
413 | } |
414 | break; |
415 | |
416 | case CTF_K_UNION: |
417 | err = ctf_hash_define(&fp->ctf_unions, fp, |
418 | CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); |
419 | |
420 | if (err != 0 && err != ECTF_STRTAB) |
421 | return (err); |
422 | |
423 | if (fp->ctf_version == CTF_VERSION_1 || |
424 | size < CTF_LSTRUCT_THRESH) |
425 | vbytes = sizeof (ctf_member_t) * vlen; |
426 | else { |
427 | vbytes = sizeof (ctf_lmember_t) * vlen; |
428 | nlunions++; |
429 | } |
430 | break; |
431 | |
432 | case CTF_K_ENUM: |
433 | err = ctf_hash_define(&fp->ctf_enums, fp, |
434 | CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); |
435 | |
436 | if (err != 0 && err != ECTF_STRTAB) |
437 | return (err); |
438 | |
439 | vbytes = sizeof (ctf_enum_t) * vlen; |
440 | break; |
441 | |
442 | case CTF_K_TYPEDEF: |
443 | err = ctf_hash_insert(&fp->ctf_names, fp, |
444 | CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); |
445 | if (err != 0 && err != ECTF_STRTAB) |
446 | return (err); |
447 | vbytes = 0; |
448 | break; |
449 | |
450 | case CTF_K_FORWARD: |
451 | /* |
452 | * Only insert forward tags into the given hash if the |
453 | * type or tag name is not already present. |
454 | */ |
455 | switch (tp->ctt_type) { |
456 | case CTF_K_STRUCT: |
457 | hp = &fp->ctf_structs; |
458 | break; |
459 | case CTF_K_UNION: |
460 | hp = &fp->ctf_unions; |
461 | break; |
462 | case CTF_K_ENUM: |
463 | hp = &fp->ctf_enums; |
464 | break; |
465 | default: |
466 | hp = &fp->ctf_structs; |
467 | } |
468 | |
469 | if (ctf_hash_lookup(hp, fp, |
470 | name, strlen(name)) == NULL) { |
471 | err = ctf_hash_insert(hp, fp, |
472 | CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); |
473 | if (err != 0 && err != ECTF_STRTAB) |
474 | return (err); |
475 | } |
476 | vbytes = 0; |
477 | break; |
478 | |
479 | case CTF_K_POINTER: |
480 | /* |
481 | * If the type referenced by the pointer is in this CTF |
482 | * container, then store the index of the pointer type |
483 | * in fp->ctf_ptrtab[ index of referenced type ]. |
484 | */ |
485 | if (CTF_TYPE_ISCHILD(tp->ctt_type) == child && |
486 | CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax) |
487 | fp->ctf_ptrtab[ |
488 | CTF_TYPE_TO_INDEX(tp->ctt_type)] = id; |
489 | /*FALLTHRU*/ |
490 | |
491 | case CTF_K_VOLATILE: |
492 | case CTF_K_CONST: |
493 | case CTF_K_RESTRICT: |
494 | err = ctf_hash_insert(&fp->ctf_names, fp, |
495 | CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); |
496 | if (err != 0 && err != ECTF_STRTAB) |
497 | return (err); |
498 | /*FALLTHRU*/ |
499 | |
500 | default: |
501 | vbytes = 0; |
502 | break; |
503 | } |
504 | |
505 | *xp = (uint_t)((uintptr_t)tp - (uintptr_t)fp->ctf_buf); |
506 | tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes); |
507 | } |
508 | |
509 | ctf_dprintf("%lu total types processed\n" , fp->ctf_typemax); |
510 | ctf_dprintf("%u enum names hashed\n" , ctf_hash_size(&fp->ctf_enums)); |
511 | ctf_dprintf("%u struct names hashed (%d long)\n" , |
512 | ctf_hash_size(&fp->ctf_structs), nlstructs); |
513 | ctf_dprintf("%u union names hashed (%d long)\n" , |
514 | ctf_hash_size(&fp->ctf_unions), nlunions); |
515 | ctf_dprintf("%u base type names hashed\n" , |
516 | ctf_hash_size(&fp->ctf_names)); |
517 | |
518 | /* |
519 | * Make an additional pass through the pointer table to find pointers |
520 | * that point to anonymous typedef nodes. If we find one, modify the |
521 | * pointer table so that the pointer is also known to point to the |
522 | * node that is referenced by the anonymous typedef node. |
523 | */ |
524 | for (id = 1; id <= fp->ctf_typemax; id++) { |
525 | if ((dst = fp->ctf_ptrtab[id]) != 0) { |
526 | tp = LCTF_INDEX_TO_TYPEPTR(fp, id); |
527 | |
528 | if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_TYPEDEF && |
529 | strcmp(ctf_strptr(fp, tp->ctt_name), "" ) == 0 && |
530 | CTF_TYPE_ISCHILD(tp->ctt_type) == child && |
531 | CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax) |
532 | fp->ctf_ptrtab[ |
533 | CTF_TYPE_TO_INDEX(tp->ctt_type)] = dst; |
534 | } |
535 | } |
536 | |
537 | return (0); |
538 | } |
539 | |
540 | /* |
541 | * Decode the specified CTF buffer and optional symbol table and create a new |
542 | * CTF container representing the symbolic debugging information. This code |
543 | * can be used directly by the debugger, or it can be used as the engine for |
544 | * ctf_fdopen() or ctf_open(), below. |
545 | */ |
546 | ctf_file_t * |
547 | ctf_bufopen(const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, |
548 | const ctf_sect_t *strsect, int *errp) |
549 | { |
550 | const ctf_preamble_t *pp; |
551 | ctf_header_t hp; |
552 | ctf_file_t *fp; |
553 | void *buf, *base; |
554 | size_t size, hdrsz; |
555 | int err; |
556 | |
557 | if (ctfsect == NULL || ((symsect == NULL) != (strsect == NULL))) |
558 | return (ctf_set_open_errno(errp, EINVAL)); |
559 | |
560 | if (symsect != NULL && symsect->cts_entsize != sizeof (Elf32_Sym) && |
561 | symsect->cts_entsize != sizeof (Elf64_Sym)) |
562 | return (ctf_set_open_errno(errp, ECTF_SYMTAB)); |
563 | |
564 | if (symsect != NULL && symsect->cts_data == NULL) |
565 | return (ctf_set_open_errno(errp, ECTF_SYMBAD)); |
566 | |
567 | if (strsect != NULL && strsect->cts_data == NULL) |
568 | return (ctf_set_open_errno(errp, ECTF_STRBAD)); |
569 | |
570 | if (ctfsect->cts_size < sizeof (ctf_preamble_t)) |
571 | return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); |
572 | |
573 | pp = (const ctf_preamble_t *)ctfsect->cts_data; |
574 | |
575 | ctf_dprintf("ctf_bufopen: magic=0x%x version=%u\n" , |
576 | pp->ctp_magic, pp->ctp_version); |
577 | |
578 | /* |
579 | * Validate each part of the CTF header (either V1 or V2). |
580 | * First, we validate the preamble (common to all versions). At that |
581 | * point, we know specific header version, and can validate the |
582 | * version-specific parts including section offsets and alignments. |
583 | */ |
584 | if (pp->ctp_magic != CTF_MAGIC) |
585 | return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); |
586 | |
587 | if (pp->ctp_version == CTF_VERSION_2) { |
588 | if (ctfsect->cts_size < sizeof (ctf_header_t)) |
589 | return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); |
590 | |
591 | bcopy(ctfsect->cts_data, &hp, sizeof (hp)); |
592 | hdrsz = sizeof (ctf_header_t); |
593 | |
594 | } else if (pp->ctp_version == CTF_VERSION_1) { |
595 | const ctf_header_v1_t *h1p = |
596 | (const ctf_header_v1_t *)ctfsect->cts_data; |
597 | |
598 | if (ctfsect->cts_size < sizeof (ctf_header_v1_t)) |
599 | return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); |
600 | |
601 | bzero(&hp, sizeof (hp)); |
602 | hp.cth_preamble = h1p->cth_preamble; |
603 | hp.cth_objtoff = h1p->cth_objtoff; |
604 | hp.cth_funcoff = h1p->cth_funcoff; |
605 | hp.cth_typeoff = h1p->cth_typeoff; |
606 | hp.cth_stroff = h1p->cth_stroff; |
607 | hp.cth_strlen = h1p->cth_strlen; |
608 | |
609 | hdrsz = sizeof (ctf_header_v1_t); |
610 | } else |
611 | return (ctf_set_open_errno(errp, ECTF_CTFVERS)); |
612 | |
613 | size = hp.cth_stroff + hp.cth_strlen; |
614 | |
615 | ctf_dprintf("ctf_bufopen: uncompressed size=%lu\n" , (ulong_t)size); |
616 | |
617 | if (hp.cth_lbloff > size || hp.cth_objtoff > size || |
618 | hp.cth_funcoff > size || hp.cth_typeoff > size || |
619 | hp.cth_stroff > size) |
620 | return (ctf_set_open_errno(errp, ECTF_CORRUPT)); |
621 | |
622 | if (hp.cth_lbloff > hp.cth_objtoff || |
623 | hp.cth_objtoff > hp.cth_funcoff || |
624 | hp.cth_funcoff > hp.cth_typeoff || |
625 | hp.cth_typeoff > hp.cth_stroff) |
626 | return (ctf_set_open_errno(errp, ECTF_CORRUPT)); |
627 | |
628 | if ((hp.cth_lbloff & 3) || (hp.cth_objtoff & 1) || |
629 | (hp.cth_funcoff & 1) || (hp.cth_typeoff & 3)) |
630 | return (ctf_set_open_errno(errp, ECTF_CORRUPT)); |
631 | |
632 | /* |
633 | * Once everything is determined to be valid, attempt to decompress |
634 | * the CTF data buffer if it is compressed. Otherwise we just put |
635 | * the data section's buffer pointer into ctf_buf, below. |
636 | */ |
637 | if (hp.cth_flags & CTF_F_COMPRESS) { |
638 | size_t srclen, dstlen; |
639 | const void *src; |
640 | int rc = Z_OK; |
641 | |
642 | if (ctf_zopen(errp) == NULL) |
643 | return (NULL); /* errp is set for us */ |
644 | |
645 | if ((base = ctf_data_alloc(size + hdrsz)) == MAP_FAILED) |
646 | return (ctf_set_open_errno(errp, ECTF_ZALLOC)); |
647 | |
648 | bcopy(ctfsect->cts_data, base, hdrsz); |
649 | ((ctf_preamble_t *)base)->ctp_flags &= ~CTF_F_COMPRESS; |
650 | buf = (uchar_t *)base + hdrsz; |
651 | |
652 | src = (uchar_t *)ctfsect->cts_data + hdrsz; |
653 | srclen = ctfsect->cts_size - hdrsz; |
654 | dstlen = size; |
655 | |
656 | if ((rc = z_uncompress(buf, &dstlen, src, srclen)) != Z_OK) { |
657 | ctf_dprintf("zlib inflate err: %s\n" , z_strerror(rc)); |
658 | ctf_data_free(base, size + hdrsz); |
659 | return (ctf_set_open_errno(errp, ECTF_DECOMPRESS)); |
660 | } |
661 | |
662 | if (dstlen != size) { |
663 | ctf_dprintf("zlib inflate short -- got %lu of %lu " |
664 | "bytes\n" , (ulong_t)dstlen, (ulong_t)size); |
665 | ctf_data_free(base, size + hdrsz); |
666 | return (ctf_set_open_errno(errp, ECTF_CORRUPT)); |
667 | } |
668 | |
669 | ctf_data_protect(base, size + hdrsz); |
670 | |
671 | } else { |
672 | base = (void *)ctfsect->cts_data; |
673 | buf = (uchar_t *)base + hdrsz; |
674 | } |
675 | |
676 | /* |
677 | * Once we have uncompressed and validated the CTF data buffer, we can |
678 | * proceed with allocating a ctf_file_t and initializing it. |
679 | */ |
680 | if ((fp = ctf_alloc(sizeof (ctf_file_t))) == NULL) |
681 | return (ctf_set_open_errno(errp, EAGAIN)); |
682 | |
683 | bzero(fp, sizeof (ctf_file_t)); |
684 | fp->ctf_version = hp.cth_version; |
685 | fp->ctf_fileops = &ctf_fileops[hp.cth_version]; |
686 | bcopy(ctfsect, &fp->ctf_data, sizeof (ctf_sect_t)); |
687 | |
688 | if (symsect != NULL) { |
689 | bcopy(symsect, &fp->ctf_symtab, sizeof (ctf_sect_t)); |
690 | bcopy(strsect, &fp->ctf_strtab, sizeof (ctf_sect_t)); |
691 | } |
692 | |
693 | if (fp->ctf_data.cts_name != NULL) |
694 | fp->ctf_data.cts_name = ctf_strdup(fp->ctf_data.cts_name); |
695 | if (fp->ctf_symtab.cts_name != NULL) |
696 | fp->ctf_symtab.cts_name = ctf_strdup(fp->ctf_symtab.cts_name); |
697 | if (fp->ctf_strtab.cts_name != NULL) |
698 | fp->ctf_strtab.cts_name = ctf_strdup(fp->ctf_strtab.cts_name); |
699 | |
700 | if (fp->ctf_data.cts_name == NULL) |
701 | fp->ctf_data.cts_name = __UNCONST(_CTF_NULLSTR); |
702 | if (fp->ctf_symtab.cts_name == NULL) |
703 | fp->ctf_symtab.cts_name = __UNCONST(_CTF_NULLSTR); |
704 | if (fp->ctf_strtab.cts_name == NULL) |
705 | fp->ctf_strtab.cts_name = __UNCONST(_CTF_NULLSTR); |
706 | |
707 | fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *)buf + hp.cth_stroff; |
708 | fp->ctf_str[CTF_STRTAB_0].cts_len = hp.cth_strlen; |
709 | |
710 | if (strsect != NULL) { |
711 | fp->ctf_str[CTF_STRTAB_1].cts_strs = strsect->cts_data; |
712 | fp->ctf_str[CTF_STRTAB_1].cts_len = strsect->cts_size; |
713 | } |
714 | |
715 | fp->ctf_base = base; |
716 | fp->ctf_buf = buf; |
717 | fp->ctf_size = size + hdrsz; |
718 | |
719 | /* |
720 | * If we have a parent container name and label, store the relocated |
721 | * string pointers in the CTF container for easy access later. |
722 | */ |
723 | if (hp.cth_parlabel != 0) |
724 | fp->ctf_parlabel = ctf_strptr(fp, hp.cth_parlabel); |
725 | if (hp.cth_parname != 0) |
726 | fp->ctf_parname = ctf_strptr(fp, hp.cth_parname); |
727 | |
728 | ctf_dprintf("ctf_bufopen: parent name %s (label %s)\n" , |
729 | fp->ctf_parname ? fp->ctf_parname : "<NULL>" , |
730 | fp->ctf_parlabel ? fp->ctf_parlabel : "<NULL>" ); |
731 | |
732 | /* |
733 | * If we have a symbol table section, allocate and initialize |
734 | * the symtab translation table, pointed to by ctf_sxlate. |
735 | */ |
736 | if (symsect != NULL) { |
737 | fp->ctf_nsyms = symsect->cts_size / symsect->cts_entsize; |
738 | fp->ctf_sxlate = ctf_alloc(fp->ctf_nsyms * sizeof (uint_t)); |
739 | |
740 | if (fp->ctf_sxlate == NULL) { |
741 | (void) ctf_set_open_errno(errp, EAGAIN); |
742 | goto bad; |
743 | } |
744 | |
745 | if ((err = init_symtab(fp, &hp, symsect, strsect)) != 0) { |
746 | (void) ctf_set_open_errno(errp, err); |
747 | goto bad; |
748 | } |
749 | } |
750 | |
751 | if ((err = init_types(fp, &hp)) != 0) { |
752 | (void) ctf_set_open_errno(errp, err); |
753 | goto bad; |
754 | } |
755 | |
756 | /* |
757 | * Initialize the ctf_lookup_by_name top-level dictionary. We keep an |
758 | * array of type name prefixes and the corresponding ctf_hash to use. |
759 | * NOTE: This code must be kept in sync with the code in ctf_update(). |
760 | */ |
761 | fp->ctf_lookups[0].ctl_prefix = "struct" ; |
762 | fp->ctf_lookups[0].ctl_len = strlen(fp->ctf_lookups[0].ctl_prefix); |
763 | fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs; |
764 | fp->ctf_lookups[1].ctl_prefix = "union" ; |
765 | fp->ctf_lookups[1].ctl_len = strlen(fp->ctf_lookups[1].ctl_prefix); |
766 | fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions; |
767 | fp->ctf_lookups[2].ctl_prefix = "enum" ; |
768 | fp->ctf_lookups[2].ctl_len = strlen(fp->ctf_lookups[2].ctl_prefix); |
769 | fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums; |
770 | fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR; |
771 | fp->ctf_lookups[3].ctl_len = strlen(fp->ctf_lookups[3].ctl_prefix); |
772 | fp->ctf_lookups[3].ctl_hash = &fp->ctf_names; |
773 | fp->ctf_lookups[4].ctl_prefix = NULL; |
774 | fp->ctf_lookups[4].ctl_len = 0; |
775 | fp->ctf_lookups[4].ctl_hash = NULL; |
776 | |
777 | if (symsect != NULL) { |
778 | if (symsect->cts_entsize == sizeof (Elf64_Sym)) |
779 | (void) ctf_setmodel(fp, CTF_MODEL_LP64); |
780 | else |
781 | (void) ctf_setmodel(fp, CTF_MODEL_ILP32); |
782 | } else |
783 | (void) ctf_setmodel(fp, CTF_MODEL_NATIVE); |
784 | |
785 | fp->ctf_refcnt = 1; |
786 | return (fp); |
787 | |
788 | bad: |
789 | ctf_close(fp); |
790 | return (NULL); |
791 | } |
792 | |
793 | /* |
794 | * Dupliate a ctf_file_t and its underlying section information into a new |
795 | * container. This works by copying the three ctf_sect_t's of the original |
796 | * container if they exist and passing those into ctf_bufopen. To copy those, we |
797 | * mmap anonymous memory with ctf_data_alloc and bcopy the data across. It's not |
798 | * the cheapest thing, but it's what we've got. |
799 | */ |
800 | ctf_file_t * |
801 | ctf_dup(ctf_file_t *ofp) |
802 | { |
803 | ctf_file_t *fp; |
804 | ctf_sect_t ctfsect, symsect, strsect; |
805 | ctf_sect_t *ctp, *symp, *strp; |
806 | void *cbuf, *symbuf, *strbuf; |
807 | int err; |
808 | |
809 | cbuf = symbuf = strbuf = NULL; |
810 | /* |
811 | * The ctfsect isn't allowed to not exist, but the symbol and string |
812 | * section might not. We only need to copy the data of the section, not |
813 | * the name, as ctf_bufopen will take care of that. |
814 | */ |
815 | bcopy(&ofp->ctf_data, &ctfsect, sizeof (ctf_sect_t)); |
816 | cbuf = ctf_data_alloc(ctfsect.cts_size); |
817 | if (cbuf == NULL) { |
818 | (void) ctf_set_errno(ofp, ECTF_MMAP); |
819 | return (NULL); |
820 | } |
821 | |
822 | bcopy(ctfsect.cts_data, cbuf, ctfsect.cts_size); |
823 | ctf_data_protect(cbuf, ctfsect.cts_size); |
824 | ctfsect.cts_data = cbuf; |
825 | ctfsect.cts_offset = 0; |
826 | ctp = &ctfsect; |
827 | |
828 | if (ofp->ctf_symtab.cts_data != NULL) { |
829 | bcopy(&ofp->ctf_symtab, &symsect, sizeof (ctf_sect_t)); |
830 | symbuf = ctf_data_alloc(symsect.cts_size); |
831 | if (symbuf == NULL) { |
832 | (void) ctf_set_errno(ofp, ECTF_MMAP); |
833 | goto err; |
834 | } |
835 | bcopy(symsect.cts_data, symbuf, symsect.cts_size); |
836 | ctf_data_protect(symbuf, symsect.cts_size); |
837 | symsect.cts_data = symbuf; |
838 | symsect.cts_offset = 0; |
839 | symp = &symsect; |
840 | } else { |
841 | symp = NULL; |
842 | } |
843 | |
844 | if (ofp->ctf_strtab.cts_data != NULL) { |
845 | bcopy(&ofp->ctf_strtab, &strsect, sizeof (ctf_sect_t)); |
846 | strbuf = ctf_data_alloc(strsect.cts_size); |
847 | if (strbuf == NULL) { |
848 | (void) ctf_set_errno(ofp, ECTF_MMAP); |
849 | goto err; |
850 | } |
851 | bcopy(strsect.cts_data, strbuf, strsect.cts_size); |
852 | ctf_data_protect(strbuf, strsect.cts_size); |
853 | strsect.cts_data = strbuf; |
854 | strsect.cts_offset = 0; |
855 | strp = &strsect; |
856 | } else { |
857 | strp = NULL; |
858 | } |
859 | |
860 | fp = ctf_bufopen(ctp, symp, strp, &err); |
861 | if (fp == NULL) { |
862 | (void) ctf_set_errno(ofp, err); |
863 | goto err; |
864 | } |
865 | |
866 | fp->ctf_flags |= LCTF_MMAP; |
867 | |
868 | return (fp); |
869 | |
870 | err: |
871 | ctf_data_free(cbuf, ctfsect.cts_size); |
872 | if (symbuf != NULL) |
873 | ctf_data_free(symbuf, symsect.cts_size); |
874 | if (strbuf != NULL) |
875 | ctf_data_free(strbuf, strsect.cts_size); |
876 | return (NULL); |
877 | } |
878 | |
879 | /* |
880 | * Close the specified CTF container and free associated data structures. Note |
881 | * that ctf_close() is a reference counted operation: if the specified file is |
882 | * the parent of other active containers, its reference count will be greater |
883 | * than one and it will be freed later when no active children exist. |
884 | */ |
885 | void |
886 | ctf_close(ctf_file_t *fp) |
887 | { |
888 | ctf_dtdef_t *dtd, *ntd; |
889 | |
890 | if (fp == NULL) |
891 | return; /* allow ctf_close(NULL) to simplify caller code */ |
892 | |
893 | ctf_dprintf("ctf_close(%p) refcnt=%u\n" , (void *)fp, fp->ctf_refcnt); |
894 | |
895 | if (fp->ctf_refcnt > 1) { |
896 | fp->ctf_refcnt--; |
897 | return; |
898 | } |
899 | |
900 | if (fp->ctf_parent != NULL) |
901 | ctf_close(fp->ctf_parent); |
902 | |
903 | /* |
904 | * Note, to work properly with reference counting on the dynamic |
905 | * section, we must delete the list in reverse. |
906 | */ |
907 | for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) { |
908 | ntd = ctf_list_prev(dtd); |
909 | ctf_dtd_delete(fp, dtd); |
910 | } |
911 | |
912 | ctf_free(fp->ctf_dthash, fp->ctf_dthashlen * sizeof (ctf_dtdef_t *)); |
913 | |
914 | if (fp->ctf_flags & LCTF_MMAP) { |
915 | if (fp->ctf_data.cts_data != NULL) |
916 | ctf_sect_munmap(&fp->ctf_data); |
917 | if (fp->ctf_symtab.cts_data != NULL) |
918 | ctf_sect_munmap(&fp->ctf_symtab); |
919 | if (fp->ctf_strtab.cts_data != NULL) |
920 | ctf_sect_munmap(&fp->ctf_strtab); |
921 | } |
922 | |
923 | if (fp->ctf_data.cts_name != _CTF_NULLSTR && |
924 | fp->ctf_data.cts_name != NULL) { |
925 | ctf_free(__UNCONST(fp->ctf_data.cts_name), |
926 | strlen(fp->ctf_data.cts_name) + 1); |
927 | } |
928 | |
929 | if (fp->ctf_symtab.cts_name != _CTF_NULLSTR && |
930 | fp->ctf_symtab.cts_name != NULL) { |
931 | ctf_free(__UNCONST(fp->ctf_symtab.cts_name), |
932 | strlen(fp->ctf_symtab.cts_name) + 1); |
933 | } |
934 | |
935 | if (fp->ctf_strtab.cts_name != _CTF_NULLSTR && |
936 | fp->ctf_strtab.cts_name != NULL) { |
937 | ctf_free(__UNCONST(fp->ctf_strtab.cts_name), |
938 | strlen(fp->ctf_strtab.cts_name) + 1); |
939 | } |
940 | |
941 | if (fp->ctf_base != fp->ctf_data.cts_data && fp->ctf_base != NULL) |
942 | ctf_data_free(__UNCONST(fp->ctf_base), fp->ctf_size); |
943 | |
944 | if (fp->ctf_sxlate != NULL) |
945 | ctf_free(fp->ctf_sxlate, sizeof (uint_t) * fp->ctf_nsyms); |
946 | |
947 | if (fp->ctf_txlate != NULL) { |
948 | ctf_free(fp->ctf_txlate, |
949 | sizeof (uint_t) * (fp->ctf_typemax + 1)); |
950 | } |
951 | |
952 | if (fp->ctf_ptrtab != NULL) { |
953 | ctf_free(fp->ctf_ptrtab, |
954 | sizeof (ushort_t) * (fp->ctf_typemax + 1)); |
955 | } |
956 | |
957 | ctf_hash_destroy(&fp->ctf_structs); |
958 | ctf_hash_destroy(&fp->ctf_unions); |
959 | ctf_hash_destroy(&fp->ctf_enums); |
960 | ctf_hash_destroy(&fp->ctf_names); |
961 | |
962 | ctf_free(fp, sizeof (ctf_file_t)); |
963 | } |
964 | |
965 | /* |
966 | * Return the CTF handle for the parent CTF container, if one exists. |
967 | * Otherwise return NULL to indicate this container has no imported parent. |
968 | */ |
969 | ctf_file_t * |
970 | ctf_parent_file(ctf_file_t *fp) |
971 | { |
972 | return (fp->ctf_parent); |
973 | } |
974 | |
975 | /* |
976 | * Return the name of the parent CTF container, if one exists. Otherwise |
977 | * return NULL to indicate this container is a root container. |
978 | */ |
979 | const char * |
980 | ctf_parent_name(ctf_file_t *fp) |
981 | { |
982 | return (fp->ctf_parname); |
983 | } |
984 | |
985 | /* |
986 | * Import the types from the specified parent container by storing a pointer |
987 | * to it in ctf_parent and incrementing its reference count. Only one parent |
988 | * is allowed: if a parent already exists, it is replaced by the new parent. |
989 | */ |
990 | int |
991 | ctf_import(ctf_file_t *fp, ctf_file_t *pfp) |
992 | { |
993 | if (fp == NULL || fp == pfp || (pfp != NULL && pfp->ctf_refcnt == 0)) |
994 | return (ctf_set_errno(fp, EINVAL)); |
995 | |
996 | if (pfp != NULL && pfp->ctf_dmodel != fp->ctf_dmodel) |
997 | return (ctf_set_errno(fp, ECTF_DMODEL)); |
998 | |
999 | if (fp->ctf_parent != NULL) |
1000 | ctf_close(fp->ctf_parent); |
1001 | |
1002 | if (pfp != NULL) { |
1003 | fp->ctf_flags |= LCTF_CHILD; |
1004 | pfp->ctf_refcnt++; |
1005 | } |
1006 | |
1007 | fp->ctf_parent = pfp; |
1008 | return (0); |
1009 | } |
1010 | |
1011 | /* |
1012 | * Set the data model constant for the CTF container. |
1013 | */ |
1014 | int |
1015 | ctf_setmodel(ctf_file_t *fp, int model) |
1016 | { |
1017 | const ctf_dmodel_t *dp; |
1018 | |
1019 | for (dp = _libctf_models; dp->ctd_name != NULL; dp++) { |
1020 | if (dp->ctd_code == model) { |
1021 | fp->ctf_dmodel = dp; |
1022 | return (0); |
1023 | } |
1024 | } |
1025 | |
1026 | return (ctf_set_errno(fp, EINVAL)); |
1027 | } |
1028 | |
1029 | /* |
1030 | * Return the data model constant for the CTF container. |
1031 | */ |
1032 | int |
1033 | ctf_getmodel(ctf_file_t *fp) |
1034 | { |
1035 | return (fp->ctf_dmodel->ctd_code); |
1036 | } |
1037 | |
1038 | void |
1039 | ctf_setspecific(ctf_file_t *fp, void *data) |
1040 | { |
1041 | fp->ctf_specific = data; |
1042 | } |
1043 | |
1044 | void * |
1045 | ctf_getspecific(ctf_file_t *fp) |
1046 | { |
1047 | return (fp->ctf_specific); |
1048 | } |
1049 | |