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