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