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