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