Annotation of src/usr.bin/ctfconv/parse.c, Revision 1.9
1.9 ! mpi 1: /* $OpenBSD: parse.c,v 1.8 2017/10/28 09:34:17 mpi Exp $ */
1.2 jasper 2:
1.1 mpi 3: /*
4: * Copyright (c) 2016-2017 Martin Pieuchot
5: * Copyright (c) 2016 Jasper Lievisse Adriaanse <jasper@openbsd.org>
6: *
7: * Permission to use, copy, modify, and distribute this software for any
8: * purpose with or without fee is hereby granted, provided that the above
9: * copyright notice and this permission notice appear in all copies.
10: *
11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18: */
19:
20: /*
21: * DWARF to IT (internal type) representation parser.
22: */
23:
24: #include <sys/queue.h>
25: #include <sys/tree.h>
1.8 mpi 26: #include <sys/types.h>
1.1 mpi 27: #include <sys/ctf.h>
28:
29: #include <assert.h>
1.5 deraadt 30: #include <limits.h>
1.1 mpi 31: #include <err.h>
32: #include <stdlib.h>
33: #include <string.h>
34:
35: #include "itype.h"
36: #include "xmalloc.h"
37: #include "dwarf.h"
38: #include "dw.h"
39: #include "pool.h"
40:
41: #ifdef DEBUG
42: #include <stdio.h>
43: #endif
44:
45: #ifndef NOPOOL
46: struct pool it_pool, im_pool, ir_pool;
47: #endif /* NOPOOL */
1.8 mpi 48:
49: #ifndef nitems
50: #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
51: #endif
1.1 mpi 52:
53: #define DPRINTF(x...) do { /*printf(x)*/ } while (0)
54:
55: #define VOID_OFFSET 1 /* Fake offset for generating "void" type. */
56:
57: /*
58: * Tree used to resolve per-CU types based on their offset in
59: * the abbrev section.
60: */
61: RB_HEAD(ioff_tree, itype);
62:
63: /*
1.9 ! mpi 64: * Per-type trees used to merge existing types with the ones of
1.1 mpi 65: * a newly parsed CU.
66: */
67: RB_HEAD(itype_tree, itype) itypet[CTF_K_MAX];
68:
69: /*
70: * Tree of symbols used to build a list matching the order of
71: * the ELF symbol table.
72: */
73: struct isymb_tree isymbt;
74:
1.9 ! mpi 75: struct itype *void_it; /* no type is emited for void */
1.1 mpi 76: uint16_t tidx, fidx, oidx; /* type, func & object IDs */
77: uint16_t long_tidx; /* index of "long", for array */
78:
79:
80: void cu_stat(void);
81: void cu_parse(struct dwcu *, struct itype_queue *,
82: struct ioff_tree *);
83: void cu_resolve(struct dwcu *, struct itype_queue *,
84: struct ioff_tree *);
85: void cu_reference(struct dwcu *, struct itype_queue *);
86: void cu_merge(struct dwcu *, struct itype_queue *);
87:
88: struct itype *parse_base(struct dwdie *, size_t);
89: struct itype *parse_refers(struct dwdie *, size_t, int);
90: struct itype *parse_array(struct dwdie *, size_t);
91: struct itype *parse_enum(struct dwdie *, size_t);
92: struct itype *parse_struct(struct dwdie *, size_t, int, size_t);
93: struct itype *parse_function(struct dwdie *, size_t);
94: struct itype *parse_funcptr(struct dwdie *, size_t);
95: struct itype *parse_variable(struct dwdie *, size_t);
96:
97: void subparse_subrange(struct dwdie *, size_t, struct itype *);
98: void subparse_enumerator(struct dwdie *, size_t, struct itype *);
99: void subparse_member(struct dwdie *, size_t, struct itype *, size_t);
100: void subparse_arguments(struct dwdie *, size_t, struct itype *);
101:
102: size_t dav2val(struct dwaval *, size_t);
103: const char *dav2str(struct dwaval *);
104: const char *enc2name(unsigned short);
105:
106: struct itype *it_new(uint64_t, size_t, const char *, uint32_t, uint16_t,
107: uint64_t, uint16_t, unsigned int);
108: void it_reference(struct itype *);
109: void it_free(struct itype *);
110: int it_cmp(struct itype *, struct itype *);
111: int it_name_cmp(struct itype *, struct itype *);
112: int it_off_cmp(struct itype *, struct itype *);
113: void ir_add(struct itype *, struct itype *);
114: void ir_purge(struct itype *);
115: struct imember *im_new(const char *, size_t, size_t);
116:
117: RB_GENERATE(itype_tree, itype, it_node, it_cmp);
118: RB_GENERATE(isymb_tree, itype, it_node, it_name_cmp);
119: RB_GENERATE(ioff_tree, itype, it_node, it_off_cmp);
120:
121: /*
122: * Construct a list of internal type and functions based on DWARF
123: * INFO and ABBREV sections.
124: *
125: * Multiple CUs are supported.
126: */
127: void
128: dwarf_parse(const char *infobuf, size_t infolen, const char *abbuf,
129: size_t ablen)
130: {
131: struct dwbuf info = { .buf = infobuf, .len = infolen };
132: struct dwbuf abbrev = { .buf = abbuf, .len = ablen };
133: struct dwcu *dcu = NULL;
134: struct ioff_tree cu_iofft;
135: struct itype_queue cu_itypeq;
136: struct itype *it;
137: int i;
138:
139: for (i = 0; i < CTF_K_MAX; i++)
140: RB_INIT(&itypet[i]);
141: RB_INIT(&isymbt);
142:
143: void_it = it_new(++tidx, VOID_OFFSET, "void", 0,
144: CTF_INT_SIGNED, 0, CTF_K_INTEGER, 0);
145: TAILQ_INSERT_TAIL(&itypeq, void_it, it_next);
146:
147: while (dw_cu_parse(&info, &abbrev, infolen, &dcu) == 0) {
148: TAILQ_INIT(&cu_itypeq);
1.9 ! mpi 149:
! 150: /* We use a tree to speed-up type resolution. */
1.1 mpi 151: RB_INIT(&cu_iofft);
152:
153: /* Parse this CU */
154: cu_parse(dcu, &cu_itypeq, &cu_iofft);
155:
156: /* Resolve its types. */
157: cu_resolve(dcu, &cu_itypeq, &cu_iofft);
158: assert(RB_EMPTY(&cu_iofft));
159:
160: /* Mark used type as such. */
161: cu_reference(dcu, &cu_itypeq);
162:
163: #ifdef DEBUG
164: /* Dump statistics for current CU. */
165: cu_stat();
166: #endif
167:
168: /* Merge them with the common type list. */
169: cu_merge(dcu, &cu_itypeq);
170:
171: dw_dcu_free(dcu);
172: }
173:
174: /* We force array's index type to be 'long', for that we need its ID. */
175: RB_FOREACH(it, itype_tree, &itypet[CTF_K_INTEGER]) {
176: if (it_name(it) == NULL || it->it_size != (8 * sizeof(long)))
177: continue;
178:
179: if (strcmp(it_name(it), "unsigned") == 0) {
180: long_tidx = it->it_idx;
181: break;
182: }
183: }
184: }
185:
186: struct itype *
187: it_new(uint64_t index, size_t off, const char *name, uint32_t size,
188: uint16_t enc, uint64_t ref, uint16_t type, unsigned int flags)
189: {
190: struct itype *it;
191: #ifndef NOPOOL
192: static int it_pool_inited = 0;
193:
194: if (!it_pool_inited) {
195: pool_init(&it_pool, "it", 512, sizeof(struct itype));
196: pool_init(&im_pool, "im", 1024, sizeof(struct imember));
197: pool_init(&ir_pool, "ir", 1024, sizeof(struct itref));
198: it_pool_inited = 1;
199: }
200: #endif
201:
202: assert((name != NULL) || !(flags & (ITF_FUNC|ITF_OBJ)));
203:
204: it = pmalloc(&it_pool, sizeof(*it));
205: SIMPLEQ_INIT(&it->it_refs);
206: TAILQ_INIT(&it->it_members);
207: it->it_off = off;
208: it->it_ref = ref;
209: it->it_refp = NULL;
210: it->it_size = size;
211: it->it_nelems = 0;
212: it->it_enc = enc;
213: it->it_idx = index;
214: it->it_type = type;
215: it->it_flags = flags;
216:
217: if (name == NULL) {
218: it->it_flags |= ITF_ANON;
219: } else {
220: size_t n;
221:
222: if ((n = strlcpy(it->it_name, name, ITNAME_MAX)) > ITNAME_MAX)
223: warnx("name %s too long %zd > %d", name, n, ITNAME_MAX);
224: }
225:
226: return it;
227: }
228:
229: struct itype *
230: it_dup(struct itype *it)
231: {
232: struct imember *copim, *im;
233: struct itype *copit;
234:
235: copit = it_new(it->it_idx, it->it_off, it_name(it), it->it_size,
236: it->it_enc, it->it_ref, it->it_type, it->it_flags);
237:
238: copit->it_refp = it->it_refp;
239: copit->it_nelems = it->it_nelems;
240:
241: TAILQ_FOREACH(im, &it->it_members, im_next) {
1.3 mpi 242: copim = im_new(im_name(im), im->im_ref, im->im_off);
1.1 mpi 243: copim->im_refp = im->im_refp;
244: TAILQ_INSERT_TAIL(&copit->it_members, copim, im_next);
245: }
246:
247: return copit;
248: }
249:
250: const char *
251: it_name(struct itype *it)
252: {
253: if (!(it->it_flags & ITF_ANON))
254: return it->it_name;
255:
256: return NULL;
257: }
258:
259: void
260: it_reference(struct itype *it)
261: {
262: struct imember *im;
263:
264: if (it == NULL || it->it_flags & ITF_USED)
265: return;
266:
267: it->it_flags |= ITF_USED;
268:
269: it_reference(it->it_refp);
270: TAILQ_FOREACH(im, &it->it_members, im_next)
271: it_reference(im->im_refp);
272: }
273:
274: void
275: it_free(struct itype *it)
276: {
277: struct imember *im;
278:
279: if (it == NULL)
280: return;
281:
282: while ((im = TAILQ_FIRST(&it->it_members)) != NULL) {
283: TAILQ_REMOVE(&it->it_members, im, im_next);
284: pfree(&im_pool, im);
285: }
286:
287: ir_purge(it);
288: pfree(&it_pool, it);
289: }
290:
291: /*
292: * Return 0 if ``a'' matches ``b''.
293: */
294: int
295: it_cmp(struct itype *a, struct itype *b)
296: {
297: int diff;
298:
299: if ((diff = (a->it_type - b->it_type)) != 0)
300: return diff;
301:
302: if ((diff = (a->it_size - b->it_size)) != 0)
303: return diff;
304:
305: if ((diff = (a->it_nelems - b->it_nelems)) != 0)
306: return diff;
307:
308: /* Match by name */
309: if (!(a->it_flags & ITF_ANON) && !(b->it_flags & ITF_ANON))
310: return strcmp(it_name(a), it_name(b));
311:
312: /* Only one of them is anonym */
313: if ((a->it_flags & ITF_ANON) != (b->it_flags & ITF_ANON))
314: return (a->it_flags & ITF_ANON) ? -1 : 1;
315:
316: /* Match by reference */
317: if ((a->it_refp != NULL) && (b->it_refp != NULL))
318: return it_cmp(a->it_refp, b->it_refp);
319:
320: return 1;
321: }
322:
323: int
324: it_name_cmp(struct itype *a, struct itype *b)
325: {
326: int diff;
327:
328: if ((diff = strcmp(it_name(a), it_name(b))) != 0)
329: return diff;
330:
331: return ((a->it_flags|ITF_MASK) - (b->it_flags|ITF_MASK));
332: }
333:
334: int
335: it_off_cmp(struct itype *a, struct itype *b)
336: {
337: return a->it_off - b->it_off;
338: }
339:
340: void
341: ir_add(struct itype *it, struct itype *tmp)
342: {
343: struct itref *ir;
344:
345: SIMPLEQ_FOREACH(ir, &tmp->it_refs, ir_next) {
346: if (ir->ir_itp == it)
347: return;
348: }
349:
350: ir = pmalloc(&ir_pool, sizeof(*ir));
351: ir->ir_itp = it;
352: SIMPLEQ_INSERT_TAIL(&tmp->it_refs, ir, ir_next);
353: }
354:
355: void
356: ir_purge(struct itype *it)
357: {
358: struct itref *ir;
359:
360: while ((ir = SIMPLEQ_FIRST(&it->it_refs)) != NULL) {
361: SIMPLEQ_REMOVE_HEAD(&it->it_refs, ir_next);
362: pfree(&ir_pool, ir);
363: }
364: }
365:
366: struct imember *
367: im_new(const char *name, size_t ref, size_t off)
368: {
369: struct imember *im;
370:
371: im = pmalloc(&im_pool, sizeof(*im));
372: im->im_ref = ref;
373: im->im_off = off;
374: im->im_refp = NULL;
375: if (name == NULL) {
1.3 mpi 376: im->im_flags = IMF_ANON;
1.1 mpi 377: } else {
378: size_t n;
379:
380: n = strlcpy(im->im_name, name, ITNAME_MAX);
381: if (n > ITNAME_MAX)
382: warnx("name %s too long %zd > %d", name, n,
383: ITNAME_MAX);
384: im->im_flags = 0;
385: }
386:
387: return im;
388: }
389:
1.3 mpi 390: const char *
391: im_name(struct imember *im)
392: {
393: if (!(im->im_flags & IMF_ANON))
394: return im->im_name;
395:
396: return NULL;
397: }
398:
1.1 mpi 399: void
400: cu_stat(void)
401: {
402: #ifndef NOPOOL
403: pool_dump();
404: #endif
405: }
1.9 ! mpi 406:
1.1 mpi 407: /*
1.9 ! mpi 408: * Iterate over all types found in a given CU. For all non-resolved types
! 409: * use their DWARF relative offset to find the relative type they are pointing
! 410: * to. The CU offset tree, `cuot', is used to speedup relative type lookup.
1.1 mpi 411: */
412: void
413: cu_resolve(struct dwcu *dcu, struct itype_queue *cutq, struct ioff_tree *cuot)
414: {
415: struct itype *it, *ref, tmp;
416: struct imember *im;
417: unsigned int toresolve;
418: size_t off = dcu->dcu_offset;
419:
420: TAILQ_FOREACH(it, cutq, it_next) {
421: if (!(it->it_flags & (ITF_UNRES|ITF_UNRES_MEMB)))
422: continue;
423:
1.9 ! mpi 424: /* If this type references another one, try to find it. */
1.1 mpi 425: if (it->it_flags & ITF_UNRES) {
426: tmp.it_off = it->it_ref + off;
427: ref = RB_FIND(ioff_tree, cuot, &tmp);
428: if (ref != NULL) {
429: it->it_refp = ref;
430: ir_add(it, ref);
431: it->it_flags &= ~ITF_UNRES;
432: }
433: }
434:
1.9 ! mpi 435: /* If this type has members, resolve all of them. */
1.1 mpi 436: toresolve = it->it_nelems;
437: if ((it->it_flags & ITF_UNRES_MEMB) && toresolve > 0) {
438: TAILQ_FOREACH(im, &it->it_members, im_next) {
439: tmp.it_off = im->im_ref + off;
440: ref = RB_FIND(ioff_tree, cuot, &tmp);
441: if (ref != NULL) {
442: im->im_refp = ref;
443: ir_add(it, ref);
444: toresolve--;
445: }
446: }
447: if (toresolve == 0)
448: it->it_flags &= ~ITF_UNRES_MEMB;
449: }
450: #if defined(DEBUG)
451: if (it->it_flags & (ITF_UNRES|ITF_UNRES_MEMB)) {
452: printf("0x%zx: %s type=%d unresolved 0x%llx",
453: it->it_off, it_name(it), it->it_type, it->it_ref);
454: if (toresolve)
455: printf(": %d members", toresolve);
456: TAILQ_FOREACH(im, &it->it_members, im_next) {
1.3 mpi 457: if (im->im_refp != NULL)
458: continue;
459: printf("\n%zu: %s", im->im_ref, im_name(im));
1.1 mpi 460: }
461: printf("\n");
462: }
463: #endif /* defined(DEBUG) */
464: }
465:
1.9 ! mpi 466: /* We'll reuse the tree for the next CU, so empty it. */
1.1 mpi 467: RB_FOREACH_SAFE(it, ioff_tree, cuot, ref)
468: RB_REMOVE(ioff_tree, cuot, it);
469: }
470:
471: void
472: cu_reference(struct dwcu *dcu, struct itype_queue *cutq)
473: {
474: struct itype *it;
475:
476: TAILQ_FOREACH(it, cutq, it_next) {
477: if (it->it_flags & (ITF_OBJ|ITF_FUNC))
478: it_reference(it);
479: }
480: }
481:
482: /*
483: * Merge type representation from a CU with already known types.
484: */
485: void
486: cu_merge(struct dwcu *dcu, struct itype_queue *cutq)
487: {
488: struct itype *it, *nit, *prev, *first;
489: int diff;
490:
491: /* First ``it'' that needs a duplicate check. */
492: first = TAILQ_FIRST(cutq);
493: if (first == NULL)
494: return;
495:
496: TAILQ_CONCAT(&itypeq, cutq, it_next);
497:
498: /*
499: * First pass: merge types
500: */
501: for (it = first; it != NULL; it = nit) {
502: nit = TAILQ_NEXT(it, it_next);
503:
504: /* Move functions & variable to their own list. */
505: if (it->it_flags & (ITF_FUNC|ITF_OBJ)) {
506: /*
507: * FIXME: allow static variables with the same name
508: * to be of different type.
509: */
510: if (RB_FIND(isymb_tree, &isymbt, it) == NULL)
511: RB_INSERT(isymb_tree, &isymbt, it);
512: continue;
513: }
514:
515: /* Look if we already have this type. */
516: if (it->it_flags & ITF_USED)
517: prev = RB_FIND(itype_tree, &itypet[it->it_type], it);
518: else
519: prev = NULL;
520:
521: if (prev != NULL) {
522: struct itype *old = it;
523: struct itref *ir;
524: struct imember *im;
525:
526: /* Substitute references */
527: while ((ir = SIMPLEQ_FIRST(&old->it_refs)) != NULL) {
528: it = ir->ir_itp;
529:
530: SIMPLEQ_REMOVE_HEAD(&old->it_refs, ir_next);
531: pfree(&ir_pool, ir);
532:
533: if (it->it_refp == old)
534: it->it_refp = prev;
535:
536: TAILQ_FOREACH(im, &it->it_members, im_next) {
537: if (im->im_refp == old)
538: im->im_refp = prev;
539: }
540: }
541:
542: old->it_flags &= ~ITF_USED;
543: } else if (it->it_flags & ITF_USED) {
544: RB_INSERT(itype_tree, &itypet[it->it_type], it);
545: }
546: }
547:
548: /*
549: * Second pass: update indexes
550: */
551: diff = 0;
552: for (it = first; it != NULL; it = nit) {
553: nit = TAILQ_NEXT(it, it_next);
554:
555: if (it->it_flags & (ITF_FUNC|ITF_OBJ))
556: continue;
557:
558: /* Adjust indexes */
559: if (it->it_flags & ITF_USED) {
560: it->it_idx -= diff;
561: continue;
562: }
563:
564: /* Remove unused */
565: TAILQ_REMOVE(&itypeq, it, it_next);
566: it_free(it);
567: diff++;
568: }
569:
570: /* Update global index to match removed entries. */
571: it = TAILQ_LAST(&itypeq, itype_queue);
572: while (it->it_flags & (ITF_FUNC|ITF_OBJ))
573: it = TAILQ_PREV(it, itype_queue, it_next);
574:
575: tidx = it->it_idx;
576: }
577:
578: /*
579: * Parse a CU.
580: */
581: void
582: cu_parse(struct dwcu *dcu, struct itype_queue *cutq, struct ioff_tree *cuot)
583: {
584: struct itype *it = NULL;
585: struct dwdie *die;
586: size_t psz = dcu->dcu_psize;
587: size_t off = dcu->dcu_offset;
588:
589: assert(RB_EMPTY(cuot));
590:
591: SIMPLEQ_FOREACH(die, &dcu->dcu_dies, die_next) {
592: uint64_t tag = die->die_dab->dab_tag;
593:
594: switch (tag) {
595: case DW_TAG_array_type:
596: it = parse_array(die, dcu->dcu_psize);
597: break;
598: case DW_TAG_enumeration_type:
599: it = parse_enum(die, dcu->dcu_psize);
600: break;
601: case DW_TAG_pointer_type:
602: it = parse_refers(die, psz, CTF_K_POINTER);
603: break;
604: case DW_TAG_structure_type:
605: it = parse_struct(die, psz, CTF_K_STRUCT, off);
606: if (it == NULL)
607: continue;
608: break;
609: case DW_TAG_typedef:
610: it = parse_refers(die, psz, CTF_K_TYPEDEF);
611: break;
612: case DW_TAG_union_type:
613: it = parse_struct(die, psz, CTF_K_UNION, off);
614: if (it == NULL)
615: continue;
616: break;
617: case DW_TAG_base_type:
618: it = parse_base(die, psz);
1.7 jsg 619: if (it == NULL)
620: continue;
1.1 mpi 621: break;
622: case DW_TAG_const_type:
623: it = parse_refers(die, psz, CTF_K_CONST);
624: break;
625: case DW_TAG_volatile_type:
626: it = parse_refers(die, psz, CTF_K_VOLATILE);
627: break;
628: case DW_TAG_restrict_type:
629: it = parse_refers(die, psz, CTF_K_RESTRICT);
630: break;
631: case DW_TAG_subprogram:
632: it = parse_function(die, psz);
633: if (it == NULL)
634: continue;
635: break;
636: case DW_TAG_subroutine_type:
637: it = parse_funcptr(die, psz);
638: break;
639: /*
640: * Children are assumed to be right after their parent in
641: * the list. The parent parsing function takes care of
642: * parsing them.
643: */
644: case DW_TAG_member:
645: assert(it->it_type == CTF_K_STRUCT ||
646: it->it_type == CTF_K_UNION ||
647: it->it_type == CTF_K_ENUM);
648: continue;
649: case DW_TAG_subrange_type:
650: assert(it->it_type == CTF_K_ARRAY);
651: continue;
652: case DW_TAG_formal_parameter:
653: /*
654: * If we skipped the second inline definition,
655: * skip its arguments.
656: */
657: if (it == NULL)
658: continue;
659:
660: /* See comment in subparse_arguments(). */
661: if (it->it_type == CTF_K_STRUCT ||
662: it->it_type == CTF_K_UNION ||
663: it->it_type == CTF_K_ENUM ||
664: it->it_type == CTF_K_TYPEDEF)
665: continue;
666:
667: if (it->it_flags & ITF_OBJ)
668: continue;
669:
670: assert(it->it_type == CTF_K_FUNCTION);
671: continue;
672: case DW_TAG_variable:
673: it = parse_variable(die, psz);
674: /* Unnamed variables are discarded. */
675: if (it == NULL)
676: continue;
677: break;
678: #if 1
679: case DW_TAG_lexical_block:
680: case DW_TAG_inlined_subroutine:
681: continue;
682: #endif
683: case DW_TAG_compile_unit:
684: default:
685: DPRINTF("%s\n", dw_tag2name(tag));
686: continue;
687: }
688:
689: TAILQ_INSERT_TAIL(cutq, it, it_next);
690: RB_INSERT(ioff_tree, cuot, it);
691: }
692: }
693:
694: struct itype *
695: parse_base(struct dwdie *die, size_t psz)
696: {
697: struct itype *it;
698: struct dwaval *dav;
699: uint16_t encoding, enc = 0, bits = 0;
700: int type;
701:
702: SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
703: switch (dav->dav_dat->dat_attr) {
704: case DW_AT_encoding:
705: enc = dav2val(dav, psz);
706: break;
707: case DW_AT_byte_size:
708: bits = 8 * dav2val(dav, psz);
709: break;
710: default:
711: DPRINTF("%s\n", dw_at2name(dav->dav_dat->dat_attr));
712: break;
713: }
714: }
715:
716: switch (enc) {
717: case DW_ATE_unsigned:
718: case DW_ATE_address:
719: encoding = 0;
720: type = CTF_K_INTEGER;
721: break;
722: case DW_ATE_unsigned_char:
723: encoding = CTF_INT_CHAR;
724: type = CTF_K_INTEGER;
725: break;
726: case DW_ATE_signed:
727: encoding = CTF_INT_SIGNED;
728: type = CTF_K_INTEGER;
729: break;
730: case DW_ATE_signed_char:
731: encoding = CTF_INT_SIGNED | CTF_INT_CHAR;
732: type = CTF_K_INTEGER;
733: break;
734: case DW_ATE_boolean:
735: encoding = CTF_INT_SIGNED | CTF_INT_BOOL;
736: type = CTF_K_INTEGER;
737: break;
738: case DW_ATE_float:
739: if (bits < psz)
740: encoding = CTF_FP_SINGLE;
741: else if (bits == psz)
742: encoding = CTF_FP_DOUBLE;
743: else
744: encoding = CTF_FP_LDOUBLE;
745: type = CTF_K_FLOAT;
746: break;
747: case DW_ATE_complex_float:
748: if (bits < psz)
749: encoding = CTF_FP_CPLX;
750: else if (bits == psz)
751: encoding = CTF_FP_DCPLX;
752: else
753: encoding = CTF_FP_LDCPLX;
754: type = CTF_K_FLOAT;
755: break;
756: case DW_ATE_imaginary_float:
757: if (bits < psz)
758: encoding = CTF_FP_IMAGRY;
759: else if (bits == psz)
760: encoding = CTF_FP_DIMAGRY;
761: else
762: encoding = CTF_FP_LDIMAGRY;
763: type = CTF_K_FLOAT;
764: break;
765: default:
766: DPRINTF("unknown encoding: %d\n", enc);
767: return (NULL);
768: }
769:
770: it = it_new(++tidx, die->die_offset, enc2name(enc), bits,
771: encoding, 0, type, 0);
772:
773: return it;
774: }
775:
776: struct itype *
777: parse_refers(struct dwdie *die, size_t psz, int type)
778: {
779: struct itype *it;
780: struct dwaval *dav;
781: const char *name = NULL;
782: size_t ref = 0, size = 0;
783:
784: SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
785: switch (dav->dav_dat->dat_attr) {
786: case DW_AT_name:
787: name = dav2str(dav);
788: break;
789: case DW_AT_type:
790: ref = dav2val(dav, psz);
791: break;
792: case DW_AT_byte_size:
793: size = dav2val(dav, psz);
794: assert(size < UINT_MAX);
795: break;
796: default:
797: DPRINTF("%s\n", dw_at2name(dav->dav_dat->dat_attr));
798: break;
799: }
800: }
801:
802: it = it_new(++tidx, die->die_offset, name, size, 0, ref, type,
803: ITF_UNRES);
804:
805: if (it->it_ref == 0 && (it->it_size == sizeof(void *) ||
806: type == CTF_K_CONST || type == CTF_K_VOLATILE ||
807: type == CTF_K_POINTER)) {
808: /* Work around GCC/clang not emiting a type for void */
809: it->it_flags &= ~ITF_UNRES;
810: it->it_ref = VOID_OFFSET;
811: it->it_refp = void_it;
812: }
813:
814: return it;
815: }
816:
817: struct itype *
818: parse_array(struct dwdie *die, size_t psz)
819: {
820: struct itype *it;
821: struct dwaval *dav;
822: const char *name = NULL;
823: size_t ref = 0;
824:
825: SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
826: switch (dav->dav_dat->dat_attr) {
827: case DW_AT_name:
828: name = dav2str(dav);
829: break;
830: case DW_AT_type:
831: ref = dav2val(dav, psz);
832: break;
833: default:
834: DPRINTF("%s\n", dw_at2name(dav->dav_dat->dat_attr));
835: break;
836: }
837: }
838:
839: it = it_new(++tidx, die->die_offset, name, 0, 0, ref, CTF_K_ARRAY,
840: ITF_UNRES);
841:
842: subparse_subrange(die, psz, it);
843:
844: return it;
845: }
846:
847: struct itype *
848: parse_enum(struct dwdie *die, size_t psz)
849: {
850: struct itype *it;
851: struct dwaval *dav;
852: const char *name = NULL;
853: size_t size = 0;
854:
855: SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
856: switch (dav->dav_dat->dat_attr) {
857: case DW_AT_byte_size:
858: size = dav2val(dav, psz);
859: assert(size < UINT_MAX);
860: break;
861: case DW_AT_name:
862: name = dav2str(dav);
863: break;
864: default:
865: DPRINTF("%s\n", dw_at2name(dav->dav_dat->dat_attr));
866: break;
867: }
868: }
869:
870: it = it_new(++tidx, die->die_offset, name, size, 0, 0, CTF_K_ENUM, 0);
871:
872: subparse_enumerator(die, psz, it);
873:
874: return it;
875: }
876:
877: void
878: subparse_subrange(struct dwdie *die, size_t psz, struct itype *it)
879: {
880: struct dwaval *dav;
881:
882: assert(it->it_type == CTF_K_ARRAY);
883:
884: if (die->die_dab->dab_children == DW_CHILDREN_no)
885: return;
886:
887: /*
888: * This loop assumes that the children of a DIE are just
889: * after it on the list.
890: */
891: while ((die = SIMPLEQ_NEXT(die, die_next)) != NULL) {
892: uint64_t tag = die->die_dab->dab_tag;
893: size_t nelems = 0;
894:
895: if (tag != DW_TAG_subrange_type)
896: break;
897:
898: SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
899: switch (dav->dav_dat->dat_attr) {
900: case DW_AT_count:
901: nelems = dav2val(dav, psz);
902: break;
903: case DW_AT_upper_bound:
904: nelems = dav2val(dav, psz) + 1;
905: break;
906: default:
907: DPRINTF("%s\n",
908: dw_at2name(dav->dav_dat->dat_attr));
909: break;
910: }
911: }
912:
913: assert(nelems < UINT_MAX);
914: it->it_nelems = nelems;
915: }
916: }
917:
918: void
919: subparse_enumerator(struct dwdie *die, size_t psz, struct itype *it)
920: {
921: struct imember *im;
922: struct dwaval *dav;
923:
924: assert(it->it_type == CTF_K_ENUM);
925:
926: if (die->die_dab->dab_children == DW_CHILDREN_no)
927: return;
928:
929: /*
930: * This loop assumes that the children of a DIE are just
931: * after it on the list.
932: */
933: while ((die = SIMPLEQ_NEXT(die, die_next)) != NULL) {
934: uint64_t tag = die->die_dab->dab_tag;
935: size_t val = 0;
936: const char *name = NULL;
937:
938: if (tag != DW_TAG_enumerator)
939: break;
940:
941: SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
942: switch (dav->dav_dat->dat_attr) {
943: case DW_AT_name:
944: name = dav2str(dav);
945: break;
946: case DW_AT_const_value:
947: val = dav2val(dav, psz);
948: break;
949: default:
950: DPRINTF("%s\n",
951: dw_at2name(dav->dav_dat->dat_attr));
952: break;
953: }
954: }
955:
956: if (name == NULL) {
957: warnx("%s with anon member", it_name(it));
958: continue;
959: }
960:
961: im = im_new(name, val, 0);
962: assert(it->it_nelems < UINT_MAX);
963: it->it_nelems++;
964: TAILQ_INSERT_TAIL(&it->it_members, im, im_next);
965: }
966: }
967:
968: struct itype *
969: parse_struct(struct dwdie *die, size_t psz, int type, size_t off)
970: {
971: struct itype *it = NULL;
972: struct dwaval *dav;
973: const char *name = NULL;
974: size_t size = 0;
975:
976: SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
977: switch (dav->dav_dat->dat_attr) {
978: case DW_AT_byte_size:
979: size = dav2val(dav, psz);
980: assert(size < UINT_MAX);
981: break;
982: case DW_AT_name:
983: name = dav2str(dav);
984: break;
985: default:
986: DPRINTF("%s\n", dw_at2name(dav->dav_dat->dat_attr));
987: break;
988: }
989: }
990:
991: it = it_new(++tidx, die->die_offset, name, size, 0, 0, type, 0);
992:
993: subparse_member(die, psz, it, off);
994:
995: return it;
996: }
997:
998: void
999: subparse_member(struct dwdie *die, size_t psz, struct itype *it, size_t offset)
1000: {
1001: struct imember *im;
1002: struct dwaval *dav;
1003: const char *name;
1004: size_t off = 0, ref = 0, bits = 0;
1005: uint8_t lvl = die->die_lvl;
1006:
1007: assert(it->it_type == CTF_K_STRUCT || it->it_type == CTF_K_UNION);
1008:
1009: if (die->die_dab->dab_children == DW_CHILDREN_no)
1010: return;
1011:
1012: /*
1013: * This loop assumes that the children of a DIE are just
1014: * after it on the list.
1015: */
1016: while ((die = SIMPLEQ_NEXT(die, die_next)) != NULL) {
1017: int64_t tag = die->die_dab->dab_tag;
1018:
1019: name = NULL;
1020: if (die->die_lvl <= lvl)
1021: break;
1022:
1023: /* Skip members of members */
1024: if (die->die_lvl > lvl + 1)
1.4 mpi 1025: continue;
1026: /*
1027: * Nested declaration.
1028: *
1029: * This matches the case where a ``struct'', ``union'',
1030: * ``enum'' or ``typedef'' is first declared "inside" a
1031: * union or struct declaration.
1032: */
1033: if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type ||
1034: tag == DW_TAG_enumeration_type || tag == DW_TAG_typedef)
1.1 mpi 1035: continue;
1036:
1037: it->it_flags |= ITF_UNRES_MEMB;
1038:
1039: SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
1040: switch (dav->dav_dat->dat_attr) {
1041: case DW_AT_name:
1042: name = dav2str(dav);
1043: break;
1044: case DW_AT_type:
1045: ref = dav2val(dav, psz);
1046: break;
1047: case DW_AT_data_member_location:
1048: off = 8 * dav2val(dav, psz);
1049: break;
1050: case DW_AT_bit_size:
1051: bits = dav2val(dav, psz);
1052: assert(bits < USHRT_MAX);
1053: break;
1054: default:
1055: DPRINTF("%s\n",
1056: dw_at2name(dav->dav_dat->dat_attr));
1057: break;
1058: }
1059: }
1060:
1061: /*
1062: * When a structure is declared inside an union, we
1063: * have to generate a reference to make the resolver
1064: * happy.
1065: */
1066: if ((ref == 0) && (tag == DW_TAG_structure_type))
1067: ref = die->die_offset - offset;
1068:
1069: im = im_new(name, ref, off);
1070: assert(it->it_nelems < UINT_MAX);
1071: it->it_nelems++;
1072: TAILQ_INSERT_TAIL(&it->it_members, im, im_next);
1073: }
1074: }
1075:
1076:
1077: void
1078: subparse_arguments(struct dwdie *die, size_t psz, struct itype *it)
1079: {
1080: struct imember *im;
1081: struct dwaval *dav;
1082: size_t ref = 0;
1083:
1084: assert(it->it_type == CTF_K_FUNCTION);
1085:
1086: if (die->die_dab->dab_children == DW_CHILDREN_no)
1087: return;
1088:
1089: /*
1090: * This loop assumes that the children of a DIE are after it
1091: * on the list.
1092: */
1093: while ((die = SIMPLEQ_NEXT(die, die_next)) != NULL) {
1094: uint64_t tag = die->die_dab->dab_tag;
1095:
1096: if (tag == DW_TAG_unspecified_parameters) {
1097: it->it_flags |= ITF_VARARGS;
1098: continue;
1099: }
1100:
1101: /*
1102: * Nested declaration.
1103: *
1104: * This matches the case where a ``struct'', ``union'',
1105: * ``enum'' or ``typedef'' is first declared "inside" a
1106: * function declaration.
1107: */
1108: if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type ||
1109: tag == DW_TAG_enumeration_type || tag == DW_TAG_typedef)
1110: continue;
1111:
1112: if (tag != DW_TAG_formal_parameter)
1113: break;
1114:
1115: it->it_flags |= ITF_UNRES_MEMB;
1116:
1117: SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
1118: switch (dav->dav_dat->dat_attr) {
1119: case DW_AT_type:
1120: ref = dav2val(dav, psz);
1121: break;
1122: default:
1123: DPRINTF("%s\n",
1124: dw_at2name(dav->dav_dat->dat_attr));
1125: break;
1126: }
1127: }
1128:
1129: im = im_new(NULL, ref, 0);
1130: assert(it->it_nelems < UINT_MAX);
1131: it->it_nelems++;
1132: TAILQ_INSERT_TAIL(&it->it_members, im, im_next);
1133: }
1134: }
1135:
1136: struct itype *
1137: parse_function(struct dwdie *die, size_t psz)
1138: {
1139: struct itype *it;
1140: struct dwaval *dav;
1141: const char *name = NULL;
1142: size_t ref = 0;
1143:
1144: SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
1145: switch (dav->dav_dat->dat_attr) {
1146: case DW_AT_name:
1147: name = dav2str(dav);
1148: break;
1149: case DW_AT_type:
1150: ref = dav2val(dav, psz);
1151: break;
1152: case DW_AT_abstract_origin:
1153: /*
1154: * Skip second empty definition for inline
1155: * functions.
1156: */
1157: return NULL;
1158: default:
1159: DPRINTF("%s\n", dw_at2name(dav->dav_dat->dat_attr));
1160: break;
1161: }
1162: }
1163:
1164: /*
1165: * Work around for clang 4.0 generating DW_TAG_subprogram without
1166: * any attribute.
1167: */
1168: if (name == NULL)
1169: return NULL;
1170:
1171: it = it_new(++fidx, die->die_offset, name, 0, 0, ref, CTF_K_FUNCTION,
1172: ITF_UNRES|ITF_FUNC);
1173:
1174: subparse_arguments(die, psz, it);
1175:
1176: if (it->it_ref == 0) {
1177: /* Work around GCC not emiting a type for void */
1178: it->it_flags &= ~ITF_UNRES;
1179: it->it_ref = VOID_OFFSET;
1180: it->it_refp = void_it;
1181: }
1182:
1183: return it;
1184: }
1185:
1186: struct itype *
1187: parse_funcptr(struct dwdie *die, size_t psz)
1188: {
1189: struct itype *it;
1190: struct dwaval *dav;
1191: const char *name = NULL;
1192: size_t ref = 0;
1193:
1194: SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
1195: switch (dav->dav_dat->dat_attr) {
1196: case DW_AT_name:
1197: name = dav2str(dav);
1198: break;
1199: case DW_AT_type:
1200: ref = dav2val(dav, psz);
1201: break;
1202: default:
1203: DPRINTF("%s\n", dw_at2name(dav->dav_dat->dat_attr));
1204: break;
1205: }
1206: }
1207:
1208: it = it_new(++tidx, die->die_offset, name, 0, 0, ref, CTF_K_FUNCTION,
1209: ITF_UNRES);
1210:
1211: subparse_arguments(die, psz, it);
1212:
1213: if (it->it_ref == 0) {
1214: /* Work around GCC not emiting a type for void */
1215: it->it_flags &= ~ITF_UNRES;
1216: it->it_ref = VOID_OFFSET;
1217: it->it_refp = void_it;
1218: }
1219:
1220: return it;
1221: }
1222:
1223: struct itype *
1224: parse_variable(struct dwdie *die, size_t psz)
1225: {
1226: struct itype *it = NULL;
1227: struct dwaval *dav;
1228: const char *name = NULL;
1229: size_t ref = 0;
1230: int declaration = 0;
1231:
1232: SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
1233: switch (dav->dav_dat->dat_attr) {
1234: case DW_AT_declaration:
1235: declaration = dav2val(dav, psz);
1236: break;
1237: case DW_AT_name:
1238: name = dav2str(dav);
1239: break;
1240: case DW_AT_type:
1241: ref = dav2val(dav, psz);
1242: break;
1243: default:
1244: DPRINTF("%s\n", dw_at2name(dav->dav_dat->dat_attr));
1245: break;
1246: }
1247: }
1248:
1249:
1250: if (!declaration && name != NULL) {
1251: it = it_new(++oidx, die->die_offset, name, 0, 0, ref, 0,
1252: ITF_UNRES|ITF_OBJ);
1253: }
1254:
1255: return it;
1256: }
1257:
1258: size_t
1259: dav2val(struct dwaval *dav, size_t psz)
1260: {
1261: uint64_t val = (uint64_t)-1;
1262:
1263: switch (dav->dav_dat->dat_form) {
1264: case DW_FORM_addr:
1265: case DW_FORM_ref_addr:
1266: if (psz == sizeof(uint32_t))
1267: val = dav->dav_u32;
1268: else
1269: val = dav->dav_u64;
1270: break;
1271: case DW_FORM_block1:
1272: case DW_FORM_block2:
1273: case DW_FORM_block4:
1274: case DW_FORM_block:
1275: dw_loc_parse(&dav->dav_buf, NULL, &val, NULL);
1276: break;
1277: case DW_FORM_flag:
1278: case DW_FORM_data1:
1279: case DW_FORM_ref1:
1280: val = dav->dav_u8;
1281: break;
1282: case DW_FORM_data2:
1283: case DW_FORM_ref2:
1284: val = dav->dav_u16;
1285: break;
1286: case DW_FORM_data4:
1287: case DW_FORM_ref4:
1288: val = dav->dav_u32;
1289: break;
1290: case DW_FORM_sdata:
1291: case DW_FORM_data8:
1292: case DW_FORM_ref8:
1293: val = dav->dav_u64;
1294: break;
1295: case DW_FORM_strp:
1296: val = dav->dav_u32;
1297: break;
1298: case DW_FORM_flag_present:
1299: val = 1;
1300: break;
1301: default:
1302: break;
1303: }
1304:
1305: return val;
1306: }
1307:
1308: const char *
1309: dav2str(struct dwaval *dav)
1310: {
1311: const char *str = NULL;
1312: extern const char *dstrbuf;
1.6 jsg 1313: extern size_t dstrlen;
1.1 mpi 1314:
1315: switch (dav->dav_dat->dat_form) {
1316: case DW_FORM_string:
1317: str = dav->dav_str;
1318: break;
1319: case DW_FORM_strp:
1.6 jsg 1320: if (dav->dav_u32 >= dstrlen)
1321: str = NULL;
1322: else
1323: str = dstrbuf + dav->dav_u32;
1.1 mpi 1324: break;
1325: default:
1326: break;
1327: }
1328:
1329: return str;
1330: }
1331:
1332: const char *
1333: enc2name(unsigned short enc)
1334: {
1335: static const char *enc_name[] = { "address", "boolean", "complex float",
1336: "float", "signed", "char", "unsigned", "unsigned char",
1337: "imaginary float", "packed decimal", "numeric string", "edited",
1338: "signed fixed", "unsigned fixed", "decimal float" };
1339:
1340: if (enc > 0 && enc <= nitems(enc_name))
1341: return enc_name[enc - 1];
1342:
1343: return "invalid";
1344: }