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