[BACK]Return to parse.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ctfconv

Annotation of src/usr.bin/ctfconv/parse.c, Revision 1.1

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