10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51882Sjohnlev * Common Development and Distribution License (the "License"). 61882Sjohnlev * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 221882Sjohnlev * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * DWARF to tdata conversion 300Sstevel@tonic-gate * 310Sstevel@tonic-gate * For the most part, conversion is straightforward, proceeding in two passes. 320Sstevel@tonic-gate * On the first pass, we iterate through every die, creating new type nodes as 330Sstevel@tonic-gate * necessary. Referenced tdesc_t's are created in an uninitialized state, thus 340Sstevel@tonic-gate * allowing type reference pointers to be filled in. If the tdesc_t 350Sstevel@tonic-gate * corresponding to a given die can be completely filled out (sizes and offsets 360Sstevel@tonic-gate * calculated, and so forth) without using any referenced types, the tdesc_t is 370Sstevel@tonic-gate * marked as resolved. Consider an array type. If the type corresponding to 380Sstevel@tonic-gate * the array contents has not yet been processed, we will create a blank tdesc 390Sstevel@tonic-gate * for the contents type (only the type ID will be filled in, relying upon the 400Sstevel@tonic-gate * later portion of the first pass to encounter and complete the referenced 410Sstevel@tonic-gate * type). We will then attempt to determine the size of the array. If the 420Sstevel@tonic-gate * array has a byte size attribute, we will have completely characterized the 430Sstevel@tonic-gate * array type, and will be able to mark it as resolved. The lack of a byte 440Sstevel@tonic-gate * size attribute, on the other hand, will prevent us from fully resolving the 450Sstevel@tonic-gate * type, as the size will only be calculable with reference to the contents 460Sstevel@tonic-gate * type, which has not, as yet, been encountered. The array type will thus be 470Sstevel@tonic-gate * left without the resolved flag, and the first pass will continue. 480Sstevel@tonic-gate * 490Sstevel@tonic-gate * When we begin the second pass, we will have created tdesc_t nodes for every 500Sstevel@tonic-gate * type in the section. We will traverse the tree, from the iidescs down, 510Sstevel@tonic-gate * processing each unresolved node. As the referenced nodes will have been 520Sstevel@tonic-gate * populated, the array type used in our example above will be able to use the 530Sstevel@tonic-gate * size of the referenced types (if available) to determine its own type. The 540Sstevel@tonic-gate * traversal will be repeated until all types have been resolved or we have 550Sstevel@tonic-gate * failed to make progress. When all tdescs have been resolved, the conversion 560Sstevel@tonic-gate * is complete. 570Sstevel@tonic-gate * 580Sstevel@tonic-gate * There are, as always, a few special cases that are handled during the first 590Sstevel@tonic-gate * and second passes: 600Sstevel@tonic-gate * 610Sstevel@tonic-gate * 1. Empty enums - GCC will occasionally emit an enum without any members. 620Sstevel@tonic-gate * Later on in the file, it will emit the same enum type, though this time 630Sstevel@tonic-gate * with the full complement of members. All references to the memberless 640Sstevel@tonic-gate * enum need to be redirected to the full definition. During the first 650Sstevel@tonic-gate * pass, each enum is entered in dm_enumhash, along with a pointer to its 660Sstevel@tonic-gate * corresponding tdesc_t. If, during the second pass, we encounter a 670Sstevel@tonic-gate * memberless enum, we use the hash to locate the full definition. All 680Sstevel@tonic-gate * tdescs referencing the empty enum are then redirected. 690Sstevel@tonic-gate * 700Sstevel@tonic-gate * 2. Forward declarations - If the compiler sees a forward declaration for 710Sstevel@tonic-gate * a structure, followed by the definition of that structure, it will emit 720Sstevel@tonic-gate * DWARF data for both the forward declaration and the definition. We need 730Sstevel@tonic-gate * to resolve the forward declarations when possible, by redirecting 740Sstevel@tonic-gate * forward-referencing tdescs to the actual struct/union definitions. This 750Sstevel@tonic-gate * redirection is done completely within the first pass. We begin by 760Sstevel@tonic-gate * recording all forward declarations in dw_fwdhash. When we define a 770Sstevel@tonic-gate * structure, we check to see if there have been any corresponding forward 780Sstevel@tonic-gate * declarations. If so, we redirect the tdescs which referenced the forward 790Sstevel@tonic-gate * declarations to the structure or union definition. 800Sstevel@tonic-gate * 810Sstevel@tonic-gate * XXX see if a post traverser will allow the elimination of repeated pass 2 820Sstevel@tonic-gate * traversals. 830Sstevel@tonic-gate */ 840Sstevel@tonic-gate 850Sstevel@tonic-gate #include <stdio.h> 860Sstevel@tonic-gate #include <stdlib.h> 870Sstevel@tonic-gate #include <strings.h> 880Sstevel@tonic-gate #include <errno.h> 890Sstevel@tonic-gate #include <libelf.h> 900Sstevel@tonic-gate #include <libdwarf.h> 910Sstevel@tonic-gate #include <libgen.h> 920Sstevel@tonic-gate #include <dwarf.h> 930Sstevel@tonic-gate 940Sstevel@tonic-gate #include "ctf_headers.h" 950Sstevel@tonic-gate #include "ctftools.h" 960Sstevel@tonic-gate #include "memory.h" 970Sstevel@tonic-gate #include "list.h" 980Sstevel@tonic-gate #include "traverse.h" 990Sstevel@tonic-gate 1000Sstevel@tonic-gate /* The version of DWARF which we support. */ 1010Sstevel@tonic-gate #define DWARF_VERSION 2 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate /* 1040Sstevel@tonic-gate * We need to define a couple of our own intrinsics, to smooth out some of the 1050Sstevel@tonic-gate * differences between the GCC and DevPro DWARF emitters. See the referenced 1060Sstevel@tonic-gate * routines and the special cases in the file comment for more details. 1070Sstevel@tonic-gate * 1080Sstevel@tonic-gate * Type IDs are 32 bits wide. We're going to use the top of that field to 1090Sstevel@tonic-gate * indicate types that we've created ourselves. 1100Sstevel@tonic-gate */ 1110Sstevel@tonic-gate #define TID_FILEMAX 0x3fffffff /* highest tid from file */ 1120Sstevel@tonic-gate #define TID_VOID 0x40000001 /* see die_void() */ 1130Sstevel@tonic-gate #define TID_LONG 0x40000002 /* see die_array() */ 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate #define TID_MFGTID_BASE 0x40000003 /* first mfg'd tid */ 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate /* 1180Sstevel@tonic-gate * To reduce the staggering amount of error-handling code that would otherwise 1190Sstevel@tonic-gate * be required, the attribute-retrieval routines handle most of their own 1200Sstevel@tonic-gate * errors. If the following flag is supplied as the value of the `req' 1210Sstevel@tonic-gate * argument, they will also handle the absence of a requested attribute by 1220Sstevel@tonic-gate * terminating the program. 1230Sstevel@tonic-gate */ 1240Sstevel@tonic-gate #define DW_ATTR_REQ 1 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate #define TDESC_HASH_BUCKETS 511 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate typedef struct dwarf { 1290Sstevel@tonic-gate Dwarf_Debug dw_dw; /* for libdwarf */ 1300Sstevel@tonic-gate Dwarf_Error dw_err; /* for libdwarf */ 1310Sstevel@tonic-gate Dwarf_Unsigned dw_maxoff; /* highest legal offset in this cu */ 1320Sstevel@tonic-gate tdata_t *dw_td; /* root of the tdesc/iidesc tree */ 1330Sstevel@tonic-gate hash_t *dw_tidhash; /* hash of tdescs by t_id */ 1340Sstevel@tonic-gate hash_t *dw_fwdhash; /* hash of fwd decls by name */ 1350Sstevel@tonic-gate hash_t *dw_enumhash; /* hash of memberless enums by name */ 1360Sstevel@tonic-gate tdesc_t *dw_void; /* manufactured void type */ 1370Sstevel@tonic-gate tdesc_t *dw_long; /* manufactured long type for arrays */ 1380Sstevel@tonic-gate size_t dw_ptrsz; /* size of a pointer in this file */ 1390Sstevel@tonic-gate tid_t dw_mfgtid_last; /* last mfg'd type ID used */ 1400Sstevel@tonic-gate uint_t dw_nunres; /* count of unresolved types */ 1410Sstevel@tonic-gate char *dw_cuname; /* name of compilation unit */ 1420Sstevel@tonic-gate } dwarf_t; 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate static void die_create_one(dwarf_t *, Dwarf_Die); 1450Sstevel@tonic-gate static void die_create(dwarf_t *, Dwarf_Die); 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate static tid_t 1480Sstevel@tonic-gate mfgtid_next(dwarf_t *dw) 1490Sstevel@tonic-gate { 1500Sstevel@tonic-gate return (++dw->dw_mfgtid_last); 1510Sstevel@tonic-gate } 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate static void 1540Sstevel@tonic-gate tdesc_add(dwarf_t *dw, tdesc_t *tdp) 1550Sstevel@tonic-gate { 1560Sstevel@tonic-gate hash_add(dw->dw_tidhash, tdp); 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate static tdesc_t * 1600Sstevel@tonic-gate tdesc_lookup(dwarf_t *dw, int tid) 1610Sstevel@tonic-gate { 1620Sstevel@tonic-gate tdesc_t tmpl, *tdp; 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate tmpl.t_id = tid; 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate if (hash_find(dw->dw_tidhash, &tmpl, (void **)&tdp)) 1670Sstevel@tonic-gate return (tdp); 1680Sstevel@tonic-gate else 1690Sstevel@tonic-gate return (NULL); 1700Sstevel@tonic-gate } 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate /* 1730Sstevel@tonic-gate * Resolve a tdesc down to a node which should have a size. Returns the size, 1740Sstevel@tonic-gate * zero if the size hasn't yet been determined. 1750Sstevel@tonic-gate */ 1760Sstevel@tonic-gate static size_t 1770Sstevel@tonic-gate tdesc_size(tdesc_t *tdp) 1780Sstevel@tonic-gate { 1790Sstevel@tonic-gate for (;;) { 1800Sstevel@tonic-gate switch (tdp->t_type) { 1810Sstevel@tonic-gate case INTRINSIC: 1820Sstevel@tonic-gate case POINTER: 1830Sstevel@tonic-gate case ARRAY: 1840Sstevel@tonic-gate case FUNCTION: 1850Sstevel@tonic-gate case STRUCT: 1860Sstevel@tonic-gate case UNION: 1870Sstevel@tonic-gate case ENUM: 1880Sstevel@tonic-gate return (tdp->t_size); 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate case FORWARD: 1910Sstevel@tonic-gate return (0); 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate case TYPEDEF: 1940Sstevel@tonic-gate case VOLATILE: 1950Sstevel@tonic-gate case CONST: 1960Sstevel@tonic-gate case RESTRICT: 1970Sstevel@tonic-gate tdp = tdp->t_tdesc; 1980Sstevel@tonic-gate continue; 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate case 0: /* not yet defined */ 2010Sstevel@tonic-gate return (0); 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate default: 2040Sstevel@tonic-gate terminate("tdp %u: tdesc_size on unknown type %d\n", 2050Sstevel@tonic-gate tdp->t_id, tdp->t_type); 2060Sstevel@tonic-gate } 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate static size_t 2110Sstevel@tonic-gate tdesc_bitsize(tdesc_t *tdp) 2120Sstevel@tonic-gate { 2130Sstevel@tonic-gate for (;;) { 2140Sstevel@tonic-gate switch (tdp->t_type) { 2150Sstevel@tonic-gate case INTRINSIC: 2160Sstevel@tonic-gate return (tdp->t_intr->intr_nbits); 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate case ARRAY: 2190Sstevel@tonic-gate case FUNCTION: 2200Sstevel@tonic-gate case STRUCT: 2210Sstevel@tonic-gate case UNION: 2220Sstevel@tonic-gate case ENUM: 2230Sstevel@tonic-gate case POINTER: 2240Sstevel@tonic-gate return (tdp->t_size); 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate case FORWARD: 2270Sstevel@tonic-gate return (0); 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate case TYPEDEF: 2300Sstevel@tonic-gate case VOLATILE: 2310Sstevel@tonic-gate case RESTRICT: 2320Sstevel@tonic-gate case CONST: 2330Sstevel@tonic-gate tdp = tdp->t_tdesc; 2340Sstevel@tonic-gate continue; 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate case 0: /* not yet defined */ 2370Sstevel@tonic-gate return (0); 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate default: 2400Sstevel@tonic-gate terminate("tdp %u: tdesc_bitsize on unknown type %d\n", 2410Sstevel@tonic-gate tdp->t_id, tdp->t_type); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate } 2440Sstevel@tonic-gate } 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate static tdesc_t * 2470Sstevel@tonic-gate tdesc_basetype(tdesc_t *tdp) 2480Sstevel@tonic-gate { 2490Sstevel@tonic-gate for (;;) { 2500Sstevel@tonic-gate switch (tdp->t_type) { 2510Sstevel@tonic-gate case TYPEDEF: 2520Sstevel@tonic-gate case VOLATILE: 2530Sstevel@tonic-gate case RESTRICT: 2540Sstevel@tonic-gate case CONST: 2550Sstevel@tonic-gate tdp = tdp->t_tdesc; 2560Sstevel@tonic-gate break; 2570Sstevel@tonic-gate case 0: /* not yet defined */ 2580Sstevel@tonic-gate return (NULL); 2590Sstevel@tonic-gate default: 2600Sstevel@tonic-gate return (tdp); 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate static Dwarf_Off 2660Sstevel@tonic-gate die_off(dwarf_t *dw, Dwarf_Die die) 2670Sstevel@tonic-gate { 2680Sstevel@tonic-gate Dwarf_Off off; 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate if (dwarf_dieoffset(die, &off, &dw->dw_err) == DW_DLV_OK) 2710Sstevel@tonic-gate return (off); 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate terminate("failed to get offset for die: %s\n", 2740Sstevel@tonic-gate dwarf_errmsg(dw->dw_err)); 2750Sstevel@tonic-gate /*NOTREACHED*/ 2760Sstevel@tonic-gate return (0); 2770Sstevel@tonic-gate } 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate static Dwarf_Die 2800Sstevel@tonic-gate die_sibling(dwarf_t *dw, Dwarf_Die die) 2810Sstevel@tonic-gate { 2820Sstevel@tonic-gate Dwarf_Die sib; 2830Sstevel@tonic-gate int rc; 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate if ((rc = dwarf_siblingof(dw->dw_dw, die, &sib, &dw->dw_err)) == 2860Sstevel@tonic-gate DW_DLV_OK) 2870Sstevel@tonic-gate return (sib); 2880Sstevel@tonic-gate else if (rc == DW_DLV_NO_ENTRY) 2890Sstevel@tonic-gate return (NULL); 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate terminate("die %llu: failed to find type sibling: %s\n", 2920Sstevel@tonic-gate die_off(dw, die), dwarf_errmsg(dw->dw_err)); 2930Sstevel@tonic-gate /*NOTREACHED*/ 2940Sstevel@tonic-gate return (NULL); 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate static Dwarf_Die 2980Sstevel@tonic-gate die_child(dwarf_t *dw, Dwarf_Die die) 2990Sstevel@tonic-gate { 3000Sstevel@tonic-gate Dwarf_Die child; 3010Sstevel@tonic-gate int rc; 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate if ((rc = dwarf_child(die, &child, &dw->dw_err)) == DW_DLV_OK) 3040Sstevel@tonic-gate return (child); 3050Sstevel@tonic-gate else if (rc == DW_DLV_NO_ENTRY) 3060Sstevel@tonic-gate return (NULL); 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate terminate("die %llu: failed to find type child: %s\n", 3090Sstevel@tonic-gate die_off(dw, die), dwarf_errmsg(dw->dw_err)); 3100Sstevel@tonic-gate /*NOTREACHED*/ 3110Sstevel@tonic-gate return (NULL); 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate static Dwarf_Half 3150Sstevel@tonic-gate die_tag(dwarf_t *dw, Dwarf_Die die) 3160Sstevel@tonic-gate { 3170Sstevel@tonic-gate Dwarf_Half tag; 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate if (dwarf_tag(die, &tag, &dw->dw_err) == DW_DLV_OK) 3200Sstevel@tonic-gate return (tag); 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate terminate("die %llu: failed to get tag for type: %s\n", 3230Sstevel@tonic-gate die_off(dw, die), dwarf_errmsg(dw->dw_err)); 3240Sstevel@tonic-gate /*NOTREACHED*/ 3250Sstevel@tonic-gate return (0); 3260Sstevel@tonic-gate } 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate static Dwarf_Attribute 3290Sstevel@tonic-gate die_attr(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, int req) 3300Sstevel@tonic-gate { 3310Sstevel@tonic-gate Dwarf_Attribute attr; 3320Sstevel@tonic-gate int rc; 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate if ((rc = dwarf_attr(die, name, &attr, &dw->dw_err)) == DW_DLV_OK) { 3350Sstevel@tonic-gate return (attr); 3360Sstevel@tonic-gate } else if (rc == DW_DLV_NO_ENTRY) { 3370Sstevel@tonic-gate if (req) { 3380Sstevel@tonic-gate terminate("die %llu: no attr 0x%x\n", die_off(dw, die), 3390Sstevel@tonic-gate name); 3400Sstevel@tonic-gate } else { 3410Sstevel@tonic-gate return (NULL); 3420Sstevel@tonic-gate } 3430Sstevel@tonic-gate } 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate terminate("die %llu: failed to get attribute for type: %s\n", 3460Sstevel@tonic-gate die_off(dw, die), dwarf_errmsg(dw->dw_err)); 3470Sstevel@tonic-gate /*NOTREACHED*/ 3480Sstevel@tonic-gate return (NULL); 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate static Dwarf_Half 3520Sstevel@tonic-gate die_attr_form(dwarf_t *dw, Dwarf_Attribute attr) 3530Sstevel@tonic-gate { 3540Sstevel@tonic-gate Dwarf_Half form; 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate if (dwarf_whatform(attr, &form, &dw->dw_err) == DW_DLV_OK) 3570Sstevel@tonic-gate return (form); 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate terminate("failed to get attribute form for type: %s\n", 3600Sstevel@tonic-gate dwarf_errmsg(dw->dw_err)); 3610Sstevel@tonic-gate /*NOTREACHED*/ 3620Sstevel@tonic-gate return (0); 3630Sstevel@tonic-gate } 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate static int 3660Sstevel@tonic-gate die_signed(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Signed *valp, 3670Sstevel@tonic-gate int req) 3680Sstevel@tonic-gate { 3690Sstevel@tonic-gate Dwarf_Attribute attr; 3700Sstevel@tonic-gate Dwarf_Signed val; 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 3730Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate if (dwarf_formsdata(attr, &val, &dw->dw_err) != DW_DLV_OK) { 3760Sstevel@tonic-gate terminate("die %llu: failed to get signed (form 0x%x)\n", 3770Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 3780Sstevel@tonic-gate } 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate *valp = val; 3830Sstevel@tonic-gate return (1); 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate static int 3870Sstevel@tonic-gate die_unsigned(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Unsigned *valp, 3880Sstevel@tonic-gate int req) 3890Sstevel@tonic-gate { 3900Sstevel@tonic-gate Dwarf_Attribute attr; 3910Sstevel@tonic-gate Dwarf_Unsigned val; 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 3940Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 3950Sstevel@tonic-gate 3960Sstevel@tonic-gate if (dwarf_formudata(attr, &val, &dw->dw_err) != DW_DLV_OK) { 3970Sstevel@tonic-gate terminate("die %llu: failed to get unsigned (form 0x%x)\n", 3980Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 3990Sstevel@tonic-gate } 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate *valp = val; 4040Sstevel@tonic-gate return (1); 4050Sstevel@tonic-gate } 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate static int 4080Sstevel@tonic-gate die_bool(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Bool *valp, int req) 4090Sstevel@tonic-gate { 4100Sstevel@tonic-gate Dwarf_Attribute attr; 4110Sstevel@tonic-gate Dwarf_Bool val; 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 4140Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate if (dwarf_formflag(attr, &val, &dw->dw_err) != DW_DLV_OK) { 4170Sstevel@tonic-gate terminate("die %llu: failed to get bool (form 0x%x)\n", 4180Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 4190Sstevel@tonic-gate } 4200Sstevel@tonic-gate 4210Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate *valp = val; 4240Sstevel@tonic-gate return (1); 4250Sstevel@tonic-gate } 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate static int 4280Sstevel@tonic-gate die_string(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, char **strp, int req) 4290Sstevel@tonic-gate { 4300Sstevel@tonic-gate Dwarf_Attribute attr; 4310Sstevel@tonic-gate char *str; 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 4340Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate if (dwarf_formstring(attr, &str, &dw->dw_err) != DW_DLV_OK) { 4370Sstevel@tonic-gate terminate("die %llu: failed to get string (form 0x%x)\n", 4380Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate *strp = xstrdup(str); 4420Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, str, DW_DLA_STRING); 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate return (1); 4450Sstevel@tonic-gate } 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate static Dwarf_Off 4480Sstevel@tonic-gate die_attr_ref(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name) 4490Sstevel@tonic-gate { 4500Sstevel@tonic-gate Dwarf_Attribute attr; 4510Sstevel@tonic-gate Dwarf_Off off; 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate attr = die_attr(dw, die, name, DW_ATTR_REQ); 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate if (dwarf_formref(attr, &off, &dw->dw_err) != DW_DLV_OK) { 4560Sstevel@tonic-gate terminate("die %llu: failed to get ref (form 0x%x)\n", 4570Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 4580Sstevel@tonic-gate } 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate return (off); 4630Sstevel@tonic-gate } 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate static char * 4660Sstevel@tonic-gate die_name(dwarf_t *dw, Dwarf_Die die) 4670Sstevel@tonic-gate { 4680Sstevel@tonic-gate char *str = NULL; 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate (void) die_string(dw, die, DW_AT_name, &str, 0); 4710Sstevel@tonic-gate 4720Sstevel@tonic-gate return (str); 4730Sstevel@tonic-gate } 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate static int 4760Sstevel@tonic-gate die_isdecl(dwarf_t *dw, Dwarf_Die die) 4770Sstevel@tonic-gate { 4780Sstevel@tonic-gate Dwarf_Bool val; 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate return (die_bool(dw, die, DW_AT_declaration, &val, 0) && val); 4810Sstevel@tonic-gate } 4820Sstevel@tonic-gate 4830Sstevel@tonic-gate static int 4840Sstevel@tonic-gate die_isglobal(dwarf_t *dw, Dwarf_Die die) 4850Sstevel@tonic-gate { 4860Sstevel@tonic-gate Dwarf_Signed vis; 4870Sstevel@tonic-gate Dwarf_Bool ext; 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate /* 4900Sstevel@tonic-gate * Some compilers (gcc) use DW_AT_external to indicate function 4910Sstevel@tonic-gate * visibility. Others (Sun) use DW_AT_visibility. 4920Sstevel@tonic-gate */ 4930Sstevel@tonic-gate if (die_signed(dw, die, DW_AT_visibility, &vis, 0)) 4940Sstevel@tonic-gate return (vis == DW_VIS_exported); 4950Sstevel@tonic-gate else 4960Sstevel@tonic-gate return (die_bool(dw, die, DW_AT_external, &ext, 0) && ext); 4970Sstevel@tonic-gate } 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate static tdesc_t * 5000Sstevel@tonic-gate die_add(dwarf_t *dw, Dwarf_Off off) 5010Sstevel@tonic-gate { 5020Sstevel@tonic-gate tdesc_t *tdp = xcalloc(sizeof (tdesc_t)); 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate tdp->t_id = off; 5050Sstevel@tonic-gate 5060Sstevel@tonic-gate tdesc_add(dw, tdp); 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate return (tdp); 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate static tdesc_t * 5120Sstevel@tonic-gate die_lookup_pass1(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name) 5130Sstevel@tonic-gate { 5140Sstevel@tonic-gate Dwarf_Off ref = die_attr_ref(dw, die, name); 5150Sstevel@tonic-gate tdesc_t *tdp; 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate if ((tdp = tdesc_lookup(dw, ref)) != NULL) 5180Sstevel@tonic-gate return (tdp); 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate return (die_add(dw, ref)); 5210Sstevel@tonic-gate } 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate static int 5240Sstevel@tonic-gate die_mem_offset(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, 5250Sstevel@tonic-gate Dwarf_Unsigned *valp, int req) 5260Sstevel@tonic-gate { 5270Sstevel@tonic-gate Dwarf_Attribute attr; 5280Sstevel@tonic-gate Dwarf_Locdesc *loc; 5290Sstevel@tonic-gate Dwarf_Signed locnum; 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 5320Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate if (dwarf_loclist(attr, &loc, &locnum, &dw->dw_err) != DW_DLV_OK) { 5350Sstevel@tonic-gate terminate("die %llu: failed to get mem offset location list\n", 5360Sstevel@tonic-gate die_off(dw, die)); 5370Sstevel@tonic-gate } 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) { 5420Sstevel@tonic-gate terminate("die %llu: cannot parse member offset\n", 5430Sstevel@tonic-gate die_off(dw, die)); 5440Sstevel@tonic-gate } 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate *valp = loc->ld_s->lr_number; 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, loc->ld_s, DW_DLA_LOC_BLOCK); 5490Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, loc, DW_DLA_LOCDESC); 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate return (1); 5520Sstevel@tonic-gate } 5530Sstevel@tonic-gate 5540Sstevel@tonic-gate static tdesc_t * 5550Sstevel@tonic-gate tdesc_intr_common(dwarf_t *dw, int tid, const char *name, size_t sz) 5560Sstevel@tonic-gate { 5570Sstevel@tonic-gate tdesc_t *tdp; 5580Sstevel@tonic-gate intr_t *intr; 5590Sstevel@tonic-gate 5600Sstevel@tonic-gate intr = xcalloc(sizeof (intr_t)); 5610Sstevel@tonic-gate intr->intr_type = INTR_INT; 5620Sstevel@tonic-gate intr->intr_signed = 1; 5630Sstevel@tonic-gate intr->intr_nbits = sz * NBBY; 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate tdp = xcalloc(sizeof (tdesc_t)); 5660Sstevel@tonic-gate tdp->t_name = xstrdup(name); 5670Sstevel@tonic-gate tdp->t_size = sz; 5680Sstevel@tonic-gate tdp->t_id = tid; 5690Sstevel@tonic-gate tdp->t_type = INTRINSIC; 5700Sstevel@tonic-gate tdp->t_intr = intr; 5710Sstevel@tonic-gate tdp->t_flags = TDESC_F_RESOLVED; 5720Sstevel@tonic-gate 5730Sstevel@tonic-gate tdesc_add(dw, tdp); 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate return (tdp); 5760Sstevel@tonic-gate } 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate /* 5790Sstevel@tonic-gate * Manufacture a void type. Used for gcc-emitted stabs, where the lack of a 5800Sstevel@tonic-gate * type reference implies a reference to a void type. A void *, for example 5810Sstevel@tonic-gate * will be represented by a pointer die without a DW_AT_type. CTF requires 5820Sstevel@tonic-gate * that pointer nodes point to something, so we'll create a void for use as 5830Sstevel@tonic-gate * the target. Note that the DWARF data may already create a void type. Ours 5840Sstevel@tonic-gate * would then be a duplicate, but it'll be removed in the self-uniquification 5850Sstevel@tonic-gate * merge performed at the completion of DWARF->tdesc conversion. 5860Sstevel@tonic-gate */ 5870Sstevel@tonic-gate static tdesc_t * 5880Sstevel@tonic-gate tdesc_intr_void(dwarf_t *dw) 5890Sstevel@tonic-gate { 5900Sstevel@tonic-gate if (dw->dw_void == NULL) 5910Sstevel@tonic-gate dw->dw_void = tdesc_intr_common(dw, TID_VOID, "void", 0); 5920Sstevel@tonic-gate 5930Sstevel@tonic-gate return (dw->dw_void); 5940Sstevel@tonic-gate } 5950Sstevel@tonic-gate 5960Sstevel@tonic-gate static tdesc_t * 5970Sstevel@tonic-gate tdesc_intr_long(dwarf_t *dw) 5980Sstevel@tonic-gate { 5990Sstevel@tonic-gate if (dw->dw_long == NULL) { 6000Sstevel@tonic-gate dw->dw_long = tdesc_intr_common(dw, TID_LONG, "long", 6010Sstevel@tonic-gate dw->dw_ptrsz); 6020Sstevel@tonic-gate } 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate return (dw->dw_long); 6050Sstevel@tonic-gate } 6060Sstevel@tonic-gate 6070Sstevel@tonic-gate /* 6080Sstevel@tonic-gate * Used for creating bitfield types. We create a copy of an existing intrinsic, 6090Sstevel@tonic-gate * adjusting the size of the copy to match what the caller requested. The 6100Sstevel@tonic-gate * caller can then use the copy as the type for a bitfield structure member. 6110Sstevel@tonic-gate */ 6120Sstevel@tonic-gate static tdesc_t * 6130Sstevel@tonic-gate tdesc_intr_clone(dwarf_t *dw, tdesc_t *old, size_t bitsz) 6140Sstevel@tonic-gate { 6150Sstevel@tonic-gate tdesc_t *new = xcalloc(sizeof (tdesc_t)); 6160Sstevel@tonic-gate 6170Sstevel@tonic-gate if (!(old->t_flags & TDESC_F_RESOLVED)) { 6180Sstevel@tonic-gate terminate("tdp %u: attempt to make a bit field from an " 6190Sstevel@tonic-gate "unresolved type\n", old->t_id); 6200Sstevel@tonic-gate } 6210Sstevel@tonic-gate 6220Sstevel@tonic-gate new->t_name = xstrdup(old->t_name); 6230Sstevel@tonic-gate new->t_size = old->t_size; 6240Sstevel@tonic-gate new->t_id = mfgtid_next(dw); 6250Sstevel@tonic-gate new->t_type = INTRINSIC; 6260Sstevel@tonic-gate new->t_flags = TDESC_F_RESOLVED; 6270Sstevel@tonic-gate 6280Sstevel@tonic-gate new->t_intr = xcalloc(sizeof (intr_t)); 6290Sstevel@tonic-gate bcopy(old->t_intr, new->t_intr, sizeof (intr_t)); 6300Sstevel@tonic-gate new->t_intr->intr_nbits = bitsz; 6310Sstevel@tonic-gate 6320Sstevel@tonic-gate tdesc_add(dw, new); 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate return (new); 6350Sstevel@tonic-gate } 6360Sstevel@tonic-gate 6370Sstevel@tonic-gate static void 6380Sstevel@tonic-gate tdesc_array_create(dwarf_t *dw, Dwarf_Die dim, tdesc_t *arrtdp, 6390Sstevel@tonic-gate tdesc_t *dimtdp) 6400Sstevel@tonic-gate { 6410Sstevel@tonic-gate Dwarf_Unsigned uval; 6420Sstevel@tonic-gate Dwarf_Signed sval; 6430Sstevel@tonic-gate tdesc_t *ctdp; 6440Sstevel@tonic-gate Dwarf_Die dim2; 6450Sstevel@tonic-gate ardef_t *ar; 6460Sstevel@tonic-gate 6470Sstevel@tonic-gate if ((dim2 = die_sibling(dw, dim)) == NULL) { 6480Sstevel@tonic-gate ctdp = arrtdp; 6490Sstevel@tonic-gate } else if (die_tag(dw, dim2) == DW_TAG_subrange_type) { 6500Sstevel@tonic-gate ctdp = xcalloc(sizeof (tdesc_t)); 6510Sstevel@tonic-gate ctdp->t_id = mfgtid_next(dw); 6520Sstevel@tonic-gate debug(3, "die %llu: creating new type %u for sub-dimension\n", 6530Sstevel@tonic-gate die_off(dw, dim2), ctdp->t_id); 6540Sstevel@tonic-gate tdesc_array_create(dw, dim2, arrtdp, ctdp); 6550Sstevel@tonic-gate } else { 6560Sstevel@tonic-gate terminate("die %llu: unexpected non-subrange node in array\n", 6570Sstevel@tonic-gate die_off(dw, dim2)); 6580Sstevel@tonic-gate } 6590Sstevel@tonic-gate 6600Sstevel@tonic-gate dimtdp->t_type = ARRAY; 6610Sstevel@tonic-gate dimtdp->t_ardef = ar = xcalloc(sizeof (ardef_t)); 6620Sstevel@tonic-gate 6630Sstevel@tonic-gate /* 6640Sstevel@tonic-gate * Array bounds can be signed or unsigned, but there are several kinds 6650Sstevel@tonic-gate * of signless forms (data1, data2, etc) that take their sign from the 6660Sstevel@tonic-gate * routine that is trying to interpret them. That is, data1 can be 6670Sstevel@tonic-gate * either signed or unsigned, depending on whether you use the signed or 6680Sstevel@tonic-gate * unsigned accessor function. GCC will use the signless forms to store 6690Sstevel@tonic-gate * unsigned values which have their high bit set, so we need to try to 6700Sstevel@tonic-gate * read them first as unsigned to get positive values. We could also 6710Sstevel@tonic-gate * try signed first, falling back to unsigned if we got a negative 6720Sstevel@tonic-gate * value. 6730Sstevel@tonic-gate */ 6740Sstevel@tonic-gate if (die_unsigned(dw, dim, DW_AT_upper_bound, &uval, 0)) 6750Sstevel@tonic-gate ar->ad_nelems = uval + 1; 6760Sstevel@tonic-gate else if (die_signed(dw, dim, DW_AT_upper_bound, &sval, 0)) 6770Sstevel@tonic-gate ar->ad_nelems = sval + 1; 6780Sstevel@tonic-gate else 6790Sstevel@tonic-gate ar->ad_nelems = 0; 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate /* 6820Sstevel@tonic-gate * Different compilers use different index types. Force the type to be 6830Sstevel@tonic-gate * a common, known value (long). 6840Sstevel@tonic-gate */ 6850Sstevel@tonic-gate ar->ad_idxtype = tdesc_intr_long(dw); 6860Sstevel@tonic-gate ar->ad_contents = ctdp; 6870Sstevel@tonic-gate 6880Sstevel@tonic-gate if (ar->ad_contents->t_size != 0) { 6890Sstevel@tonic-gate dimtdp->t_size = ar->ad_contents->t_size * ar->ad_nelems; 6900Sstevel@tonic-gate dimtdp->t_flags |= TDESC_F_RESOLVED; 6910Sstevel@tonic-gate } 6920Sstevel@tonic-gate } 6930Sstevel@tonic-gate 6940Sstevel@tonic-gate /* 6950Sstevel@tonic-gate * Create a tdesc from an array node. Some arrays will come with byte size 6960Sstevel@tonic-gate * attributes, and thus can be resolved immediately. Others don't, and will 6970Sstevel@tonic-gate * need to wait until the second pass for resolution. 6980Sstevel@tonic-gate */ 6990Sstevel@tonic-gate static void 7000Sstevel@tonic-gate die_array_create(dwarf_t *dw, Dwarf_Die arr, Dwarf_Off off, tdesc_t *tdp) 7010Sstevel@tonic-gate { 7020Sstevel@tonic-gate tdesc_t *arrtdp = die_lookup_pass1(dw, arr, DW_AT_type); 7030Sstevel@tonic-gate Dwarf_Unsigned uval; 7040Sstevel@tonic-gate Dwarf_Die dim; 7050Sstevel@tonic-gate 7060Sstevel@tonic-gate debug(3, "die %llu: creating array\n", off); 7070Sstevel@tonic-gate 7080Sstevel@tonic-gate if ((dim = die_child(dw, arr)) == NULL || 7090Sstevel@tonic-gate die_tag(dw, dim) != DW_TAG_subrange_type) 7100Sstevel@tonic-gate terminate("die %llu: failed to retrieve array bounds\n", off); 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate tdesc_array_create(dw, dim, arrtdp, tdp); 7130Sstevel@tonic-gate 7140Sstevel@tonic-gate if (die_unsigned(dw, arr, DW_AT_byte_size, &uval, 0)) { 7150Sstevel@tonic-gate tdesc_t *dimtdp; 7160Sstevel@tonic-gate int flags; 7170Sstevel@tonic-gate 7180Sstevel@tonic-gate tdp->t_size = uval; 7190Sstevel@tonic-gate 7200Sstevel@tonic-gate /* 7210Sstevel@tonic-gate * Ensure that sub-dimensions have sizes too before marking 7220Sstevel@tonic-gate * as resolved. 7230Sstevel@tonic-gate */ 7240Sstevel@tonic-gate flags = TDESC_F_RESOLVED; 7250Sstevel@tonic-gate for (dimtdp = tdp->t_ardef->ad_contents; 7260Sstevel@tonic-gate dimtdp->t_type == ARRAY; 7270Sstevel@tonic-gate dimtdp = dimtdp->t_ardef->ad_contents) { 7280Sstevel@tonic-gate if (!(dimtdp->t_flags & TDESC_F_RESOLVED)) { 7290Sstevel@tonic-gate flags = 0; 7300Sstevel@tonic-gate break; 7310Sstevel@tonic-gate } 7320Sstevel@tonic-gate } 7330Sstevel@tonic-gate 7340Sstevel@tonic-gate tdp->t_flags |= flags; 7350Sstevel@tonic-gate } 7360Sstevel@tonic-gate 7370Sstevel@tonic-gate debug(3, "die %llu: array nelems %u size %u\n", off, 7380Sstevel@tonic-gate tdp->t_ardef->ad_nelems, tdp->t_size); 7390Sstevel@tonic-gate } 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate /*ARGSUSED1*/ 7420Sstevel@tonic-gate static int 7430Sstevel@tonic-gate die_array_resolve(tdesc_t *tdp, tdesc_t **tdpp, void *private) 7440Sstevel@tonic-gate { 7450Sstevel@tonic-gate dwarf_t *dw = private; 7460Sstevel@tonic-gate size_t sz; 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 7490Sstevel@tonic-gate return (1); 7500Sstevel@tonic-gate 7510Sstevel@tonic-gate debug(3, "trying to resolve array %d (cont %d)\n", tdp->t_id, 7520Sstevel@tonic-gate tdp->t_ardef->ad_contents->t_id); 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate if ((sz = tdesc_size(tdp->t_ardef->ad_contents)) == 0) { 7550Sstevel@tonic-gate debug(3, "unable to resolve array %s (%d) contents %d\n", 7561882Sjohnlev tdesc_name(tdp), tdp->t_id, 7570Sstevel@tonic-gate tdp->t_ardef->ad_contents->t_id); 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate dw->dw_nunres++; 7600Sstevel@tonic-gate return (1); 7610Sstevel@tonic-gate } 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate tdp->t_size = sz * tdp->t_ardef->ad_nelems; 7640Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 7650Sstevel@tonic-gate 7660Sstevel@tonic-gate debug(3, "resolved array %d: %u bytes\n", tdp->t_id, tdp->t_size); 7670Sstevel@tonic-gate 7680Sstevel@tonic-gate return (1); 7690Sstevel@tonic-gate } 7700Sstevel@tonic-gate 7710Sstevel@tonic-gate /*ARGSUSED1*/ 7720Sstevel@tonic-gate static int 7730Sstevel@tonic-gate die_array_failed(tdesc_t *tdp, tdesc_t **tdpp, void *private) 7740Sstevel@tonic-gate { 7750Sstevel@tonic-gate tdesc_t *cont = tdp->t_ardef->ad_contents; 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 7780Sstevel@tonic-gate return (1); 7790Sstevel@tonic-gate 7800Sstevel@tonic-gate fprintf(stderr, "Array %d: failed to size contents type %s (%d)\n", 7811882Sjohnlev tdp->t_id, tdesc_name(cont), cont->t_id); 7820Sstevel@tonic-gate 7830Sstevel@tonic-gate return (1); 7840Sstevel@tonic-gate } 7850Sstevel@tonic-gate 7860Sstevel@tonic-gate /* 7870Sstevel@tonic-gate * Most enums (those with members) will be resolved during this first pass. 7880Sstevel@tonic-gate * Others - those without members (see the file comment) - won't be, and will 7890Sstevel@tonic-gate * need to wait until the second pass when they can be matched with their full 7900Sstevel@tonic-gate * definitions. 7910Sstevel@tonic-gate */ 7920Sstevel@tonic-gate static void 7930Sstevel@tonic-gate die_enum_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 7940Sstevel@tonic-gate { 7950Sstevel@tonic-gate Dwarf_Die mem; 7960Sstevel@tonic-gate Dwarf_Unsigned uval; 7970Sstevel@tonic-gate Dwarf_Signed sval; 7980Sstevel@tonic-gate 7990Sstevel@tonic-gate debug(3, "die %llu: creating enum\n", off); 8000Sstevel@tonic-gate 8010Sstevel@tonic-gate tdp->t_type = ENUM; 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate (void) die_unsigned(dw, die, DW_AT_byte_size, &uval, DW_ATTR_REQ); 8040Sstevel@tonic-gate tdp->t_size = uval; 8050Sstevel@tonic-gate 8060Sstevel@tonic-gate if ((mem = die_child(dw, die)) != NULL) { 8070Sstevel@tonic-gate elist_t **elastp = &tdp->t_emem; 8080Sstevel@tonic-gate 8090Sstevel@tonic-gate do { 8100Sstevel@tonic-gate elist_t *el; 8110Sstevel@tonic-gate 8120Sstevel@tonic-gate if (die_tag(dw, mem) != DW_TAG_enumerator) { 8130Sstevel@tonic-gate /* Nested type declaration */ 8140Sstevel@tonic-gate die_create_one(dw, mem); 8150Sstevel@tonic-gate continue; 8160Sstevel@tonic-gate } 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate el = xcalloc(sizeof (elist_t)); 8190Sstevel@tonic-gate el->el_name = die_name(dw, mem); 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate if (die_signed(dw, mem, DW_AT_const_value, &sval, 0)) { 8220Sstevel@tonic-gate el->el_number = sval; 8230Sstevel@tonic-gate } else if (die_unsigned(dw, mem, DW_AT_const_value, 8240Sstevel@tonic-gate &uval, 0)) { 8250Sstevel@tonic-gate el->el_number = uval; 8260Sstevel@tonic-gate } else { 8270Sstevel@tonic-gate terminate("die %llu: enum %llu: member without " 8280Sstevel@tonic-gate "value\n", off, die_off(dw, mem)); 8290Sstevel@tonic-gate } 8300Sstevel@tonic-gate 8310Sstevel@tonic-gate debug(3, "die %llu: enum %llu: created %s = %d\n", off, 8320Sstevel@tonic-gate die_off(dw, mem), el->el_name, el->el_number); 8330Sstevel@tonic-gate 8340Sstevel@tonic-gate *elastp = el; 8350Sstevel@tonic-gate elastp = &el->el_next; 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate } while ((mem = die_sibling(dw, mem)) != NULL); 8380Sstevel@tonic-gate 8390Sstevel@tonic-gate hash_add(dw->dw_enumhash, tdp); 8400Sstevel@tonic-gate 8410Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 8420Sstevel@tonic-gate 8430Sstevel@tonic-gate if (tdp->t_name != NULL) { 8440Sstevel@tonic-gate iidesc_t *ii = xcalloc(sizeof (iidesc_t)); 8450Sstevel@tonic-gate ii->ii_type = II_SOU; 8460Sstevel@tonic-gate ii->ii_name = xstrdup(tdp->t_name); 8470Sstevel@tonic-gate ii->ii_dtype = tdp; 8480Sstevel@tonic-gate 8490Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 8500Sstevel@tonic-gate } 8510Sstevel@tonic-gate } 8520Sstevel@tonic-gate } 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate static int 8550Sstevel@tonic-gate die_enum_match(void *arg1, void *arg2) 8560Sstevel@tonic-gate { 8570Sstevel@tonic-gate tdesc_t *tdp = arg1, **fullp = arg2; 8580Sstevel@tonic-gate 8590Sstevel@tonic-gate if (tdp->t_emem != NULL) { 8600Sstevel@tonic-gate *fullp = tdp; 8610Sstevel@tonic-gate return (-1); /* stop the iteration */ 8620Sstevel@tonic-gate } 8630Sstevel@tonic-gate 8640Sstevel@tonic-gate return (0); 8650Sstevel@tonic-gate } 8660Sstevel@tonic-gate 8670Sstevel@tonic-gate /*ARGSUSED1*/ 8680Sstevel@tonic-gate static int 8690Sstevel@tonic-gate die_enum_resolve(tdesc_t *tdp, tdesc_t **tdpp, void *private) 8700Sstevel@tonic-gate { 8710Sstevel@tonic-gate dwarf_t *dw = private; 8720Sstevel@tonic-gate tdesc_t *full = NULL; 8730Sstevel@tonic-gate 8740Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 8750Sstevel@tonic-gate return (1); 8760Sstevel@tonic-gate 8770Sstevel@tonic-gate (void) hash_find_iter(dw->dw_enumhash, tdp, die_enum_match, &full); 8780Sstevel@tonic-gate 8790Sstevel@tonic-gate /* 8800Sstevel@tonic-gate * The answer to this one won't change from iteration to iteration, 8810Sstevel@tonic-gate * so don't even try. 8820Sstevel@tonic-gate */ 8830Sstevel@tonic-gate if (full == NULL) { 8841882Sjohnlev terminate("tdp %u: enum %s has no members\n", tdp->t_id, 8851882Sjohnlev tdesc_name(tdp)); 8860Sstevel@tonic-gate } 8870Sstevel@tonic-gate 8880Sstevel@tonic-gate debug(3, "tdp %u: enum %s redirected to %u\n", tdp->t_id, 8891882Sjohnlev tdesc_name(tdp), full->t_id); 8900Sstevel@tonic-gate 8910Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 8920Sstevel@tonic-gate 8930Sstevel@tonic-gate return (1); 8940Sstevel@tonic-gate } 8950Sstevel@tonic-gate 8960Sstevel@tonic-gate static int 8970Sstevel@tonic-gate die_fwd_map(void *arg1, void *arg2) 8980Sstevel@tonic-gate { 8990Sstevel@tonic-gate tdesc_t *fwd = arg1, *sou = arg2; 9000Sstevel@tonic-gate 9010Sstevel@tonic-gate debug(3, "tdp %u: mapped forward %s to sou %u\n", fwd->t_id, 9021882Sjohnlev tdesc_name(fwd), sou->t_id); 9030Sstevel@tonic-gate fwd->t_tdesc = sou; 9040Sstevel@tonic-gate 9050Sstevel@tonic-gate return (0); 9060Sstevel@tonic-gate } 9070Sstevel@tonic-gate 9080Sstevel@tonic-gate /* 9090Sstevel@tonic-gate * Structures and unions will never be resolved during the first pass, as we 9100Sstevel@tonic-gate * won't be able to fully determine the member sizes. The second pass, which 9110Sstevel@tonic-gate * have access to sizing information, will be able to complete the resolution. 9120Sstevel@tonic-gate */ 9130Sstevel@tonic-gate static void 9140Sstevel@tonic-gate die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp, 9150Sstevel@tonic-gate int type, const char *typename) 9160Sstevel@tonic-gate { 9170Sstevel@tonic-gate Dwarf_Unsigned sz, bitsz, bitoff; 9180Sstevel@tonic-gate Dwarf_Die mem; 9190Sstevel@tonic-gate mlist_t *ml, **mlastp; 9200Sstevel@tonic-gate iidesc_t *ii; 9210Sstevel@tonic-gate 9220Sstevel@tonic-gate tdp->t_type = (die_isdecl(dw, str) ? FORWARD : type); 9230Sstevel@tonic-gate 9240Sstevel@tonic-gate debug(3, "die %llu: creating %s %s\n", off, 9250Sstevel@tonic-gate (tdp->t_type == FORWARD ? "forward decl" : typename), 9261882Sjohnlev tdesc_name(tdp)); 9270Sstevel@tonic-gate 9280Sstevel@tonic-gate if (tdp->t_type == FORWARD) { 9290Sstevel@tonic-gate hash_add(dw->dw_fwdhash, tdp); 9300Sstevel@tonic-gate return; 9310Sstevel@tonic-gate } 9320Sstevel@tonic-gate 9330Sstevel@tonic-gate (void) hash_find_iter(dw->dw_fwdhash, tdp, die_fwd_map, tdp); 9340Sstevel@tonic-gate 9350Sstevel@tonic-gate (void) die_unsigned(dw, str, DW_AT_byte_size, &sz, DW_ATTR_REQ); 9360Sstevel@tonic-gate tdp->t_size = sz; 9370Sstevel@tonic-gate 9380Sstevel@tonic-gate if ((mem = die_child(dw, str)) == NULL) 9390Sstevel@tonic-gate terminate("die %llu: %s has no members", off, typename); 9400Sstevel@tonic-gate 9410Sstevel@tonic-gate mlastp = &tdp->t_members; 9420Sstevel@tonic-gate 9430Sstevel@tonic-gate do { 9440Sstevel@tonic-gate Dwarf_Off memoff = die_off(dw, mem); 9450Sstevel@tonic-gate Dwarf_Half tag = die_tag(dw, mem); 9460Sstevel@tonic-gate Dwarf_Unsigned mloff; 9470Sstevel@tonic-gate 9480Sstevel@tonic-gate if (tag != DW_TAG_member) { 9490Sstevel@tonic-gate /* Nested type declaration */ 9500Sstevel@tonic-gate die_create_one(dw, mem); 9510Sstevel@tonic-gate continue; 9520Sstevel@tonic-gate } 9530Sstevel@tonic-gate 9540Sstevel@tonic-gate debug(3, "die %llu: mem %llu: creating member\n", off, memoff); 9550Sstevel@tonic-gate 9560Sstevel@tonic-gate ml = xcalloc(sizeof (mlist_t)); 9570Sstevel@tonic-gate 958*2722Sjohnlev /* 959*2722Sjohnlev * This could be a GCC anon struct/union member, so we'll allow 960*2722Sjohnlev * an empty name, even though nothing can really handle them 961*2722Sjohnlev * properly. Note that some versions of GCC miss out debug 962*2722Sjohnlev * info for anon structs, though recent versions are fixed (gcc 963*2722Sjohnlev * bug 11816). 964*2722Sjohnlev */ 965*2722Sjohnlev if ((ml->ml_name = die_name(dw, mem)) == NULL) 966*2722Sjohnlev ml->ml_name = ""; 9670Sstevel@tonic-gate 9680Sstevel@tonic-gate ml->ml_type = die_lookup_pass1(dw, mem, DW_AT_type); 9690Sstevel@tonic-gate 9700Sstevel@tonic-gate if (die_mem_offset(dw, mem, DW_AT_data_member_location, 9710Sstevel@tonic-gate &mloff, 0)) { 9720Sstevel@tonic-gate debug(3, "die %llu: got mloff %llx\n", off, 9730Sstevel@tonic-gate (u_longlong_t)mloff); 9740Sstevel@tonic-gate ml->ml_offset = mloff * 8; 9750Sstevel@tonic-gate } 9760Sstevel@tonic-gate 9770Sstevel@tonic-gate if (die_unsigned(dw, mem, DW_AT_bit_size, &bitsz, 0)) 9780Sstevel@tonic-gate ml->ml_size = bitsz; 9790Sstevel@tonic-gate else 9800Sstevel@tonic-gate ml->ml_size = tdesc_bitsize(ml->ml_type); 9810Sstevel@tonic-gate 9820Sstevel@tonic-gate if (die_unsigned(dw, mem, DW_AT_bit_offset, &bitoff, 0)) { 9830Sstevel@tonic-gate #ifdef _BIG_ENDIAN 9840Sstevel@tonic-gate ml->ml_offset += bitoff; 9850Sstevel@tonic-gate #else 9860Sstevel@tonic-gate ml->ml_offset += (dw->dw_ptrsz * NBBY - bitoff - 9870Sstevel@tonic-gate ml->ml_size); 9880Sstevel@tonic-gate #endif 9890Sstevel@tonic-gate } 9900Sstevel@tonic-gate 991*2722Sjohnlev debug(3, "die %llu: mem %llu: created \"%s\" (off %u sz %u)\n", 9920Sstevel@tonic-gate off, memoff, ml->ml_name, ml->ml_offset, ml->ml_size); 9930Sstevel@tonic-gate 9940Sstevel@tonic-gate *mlastp = ml; 9950Sstevel@tonic-gate mlastp = &ml->ml_next; 9960Sstevel@tonic-gate } while ((mem = die_sibling(dw, mem)) != NULL); 9970Sstevel@tonic-gate 9980Sstevel@tonic-gate /* 9990Sstevel@tonic-gate * GCC will attempt to eliminate unused types, thus decreasing the 10000Sstevel@tonic-gate * size of the emitted dwarf. That is, if you declare a foo_t in your 10010Sstevel@tonic-gate * header, include said header in your source file, and neglect to 10020Sstevel@tonic-gate * actually use (directly or indirectly) the foo_t in the source file, 10030Sstevel@tonic-gate * the foo_t won't make it into the emitted DWARF. So, at least, goes 10040Sstevel@tonic-gate * the theory. 10050Sstevel@tonic-gate * 10060Sstevel@tonic-gate * Occasionally, it'll emit the DW_TAG_structure_type for the foo_t, 10070Sstevel@tonic-gate * and then neglect to emit the members. Strangely, the loner struct 10080Sstevel@tonic-gate * tag will always be followed by a proper nested declaration of 10090Sstevel@tonic-gate * something else. This is clearly a bug, but we're not going to have 10100Sstevel@tonic-gate * time to get it fixed before this goo goes back, so we'll have to work 10110Sstevel@tonic-gate * around it. If we see a no-membered struct with a nested declaration 10120Sstevel@tonic-gate * (i.e. die_child of the struct tag won't be null), we'll ignore it. 10130Sstevel@tonic-gate * Being paranoid, we won't simply remove it from the hash. Instead, 10140Sstevel@tonic-gate * we'll decline to create an iidesc for it, thus ensuring that this 10150Sstevel@tonic-gate * type won't make it into the output file. To be safe, we'll also 10160Sstevel@tonic-gate * change the name. 10170Sstevel@tonic-gate */ 10180Sstevel@tonic-gate if (tdp->t_members == NULL) { 10191882Sjohnlev const char *old = tdesc_name(tdp); 10200Sstevel@tonic-gate size_t newsz = 7 + strlen(old) + 1; 10210Sstevel@tonic-gate char *new = xmalloc(newsz); 10220Sstevel@tonic-gate (void) snprintf(new, newsz, "orphan %s", old); 10230Sstevel@tonic-gate 10241882Sjohnlev debug(3, "die %llu: worked around %s %s\n", off, typename, old); 10250Sstevel@tonic-gate 10260Sstevel@tonic-gate if (tdp->t_name != NULL) 10270Sstevel@tonic-gate free(tdp->t_name); 10280Sstevel@tonic-gate tdp->t_name = new; 10290Sstevel@tonic-gate 10300Sstevel@tonic-gate } 10310Sstevel@tonic-gate 10320Sstevel@tonic-gate if (tdp->t_name != NULL && tdp->t_members != NULL) { 10330Sstevel@tonic-gate ii = xcalloc(sizeof (iidesc_t)); 10340Sstevel@tonic-gate ii->ii_type = II_SOU; 10350Sstevel@tonic-gate ii->ii_name = xstrdup(tdp->t_name); 10360Sstevel@tonic-gate ii->ii_dtype = tdp; 10370Sstevel@tonic-gate 10380Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 10390Sstevel@tonic-gate } 10400Sstevel@tonic-gate } 10410Sstevel@tonic-gate 10420Sstevel@tonic-gate static void 10430Sstevel@tonic-gate die_struct_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 10440Sstevel@tonic-gate { 10450Sstevel@tonic-gate die_sou_create(dw, die, off, tdp, STRUCT, "struct"); 10460Sstevel@tonic-gate } 10470Sstevel@tonic-gate 10480Sstevel@tonic-gate static void 10490Sstevel@tonic-gate die_union_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 10500Sstevel@tonic-gate { 10510Sstevel@tonic-gate die_sou_create(dw, die, off, tdp, UNION, "union"); 10520Sstevel@tonic-gate } 10530Sstevel@tonic-gate 10540Sstevel@tonic-gate /*ARGSUSED1*/ 10550Sstevel@tonic-gate static int 10560Sstevel@tonic-gate die_sou_resolve(tdesc_t *tdp, tdesc_t **tdpp, void *private) 10570Sstevel@tonic-gate { 10580Sstevel@tonic-gate dwarf_t *dw = private; 10590Sstevel@tonic-gate mlist_t *ml; 10600Sstevel@tonic-gate tdesc_t *mt; 10610Sstevel@tonic-gate 10620Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 10630Sstevel@tonic-gate return (1); 10640Sstevel@tonic-gate 10651882Sjohnlev debug(3, "resolving sou %s\n", tdesc_name(tdp)); 10660Sstevel@tonic-gate 10670Sstevel@tonic-gate for (ml = tdp->t_members; ml != NULL; ml = ml->ml_next) { 10680Sstevel@tonic-gate if (ml->ml_size == 0) { 10690Sstevel@tonic-gate if ((ml->ml_size = tdesc_bitsize(ml->ml_type)) == 0) { 10700Sstevel@tonic-gate dw->dw_nunres++; 10710Sstevel@tonic-gate return (1); 10720Sstevel@tonic-gate } 10730Sstevel@tonic-gate } 10740Sstevel@tonic-gate 10750Sstevel@tonic-gate if ((mt = tdesc_basetype(ml->ml_type)) == NULL) { 10760Sstevel@tonic-gate dw->dw_nunres++; 10770Sstevel@tonic-gate return (1); 10780Sstevel@tonic-gate } 10790Sstevel@tonic-gate 10800Sstevel@tonic-gate if (ml->ml_size != 0 && mt->t_type == INTRINSIC && 10810Sstevel@tonic-gate mt->t_intr->intr_nbits != ml->ml_size) { 10820Sstevel@tonic-gate /* 10830Sstevel@tonic-gate * This member is a bitfield, and needs to reference 10840Sstevel@tonic-gate * an intrinsic type with the same width. If the 10850Sstevel@tonic-gate * currently-referenced type isn't of the same width, 10860Sstevel@tonic-gate * we'll copy it, adjusting the width of the copy to 10870Sstevel@tonic-gate * the size we'd like. 10880Sstevel@tonic-gate */ 10890Sstevel@tonic-gate debug(3, "tdp %u: creating bitfield for %d bits\n", 10900Sstevel@tonic-gate tdp->t_id, ml->ml_size); 10910Sstevel@tonic-gate 10920Sstevel@tonic-gate ml->ml_type = tdesc_intr_clone(dw, mt, ml->ml_size); 10930Sstevel@tonic-gate } 10940Sstevel@tonic-gate } 10950Sstevel@tonic-gate 10960Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 10970Sstevel@tonic-gate 10980Sstevel@tonic-gate return (1); 10990Sstevel@tonic-gate } 11000Sstevel@tonic-gate 11010Sstevel@tonic-gate /*ARGSUSED1*/ 11020Sstevel@tonic-gate static int 11030Sstevel@tonic-gate die_sou_failed(tdesc_t *tdp, tdesc_t **tdpp, void *private) 11040Sstevel@tonic-gate { 11050Sstevel@tonic-gate const char *typename = (tdp->t_type == STRUCT ? "struct" : "union"); 11060Sstevel@tonic-gate mlist_t *ml; 11070Sstevel@tonic-gate 11080Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 11090Sstevel@tonic-gate return (1); 11100Sstevel@tonic-gate 11110Sstevel@tonic-gate for (ml = tdp->t_members; ml != NULL; ml = ml->ml_next) { 11120Sstevel@tonic-gate if (ml->ml_size == 0) { 1113*2722Sjohnlev fprintf(stderr, "%s %d: failed to size member \"%s\" " 1114*2722Sjohnlev "of type %s (%d)\n", typename, tdp->t_id, 1115*2722Sjohnlev ml->ml_name, tdesc_name(ml->ml_type), 1116*2722Sjohnlev ml->ml_type->t_id); 11170Sstevel@tonic-gate } 11180Sstevel@tonic-gate } 11190Sstevel@tonic-gate 11200Sstevel@tonic-gate return (1); 11210Sstevel@tonic-gate } 11220Sstevel@tonic-gate 11230Sstevel@tonic-gate static void 11240Sstevel@tonic-gate die_funcptr_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 11250Sstevel@tonic-gate { 11260Sstevel@tonic-gate Dwarf_Attribute attr; 11270Sstevel@tonic-gate Dwarf_Half tag; 11280Sstevel@tonic-gate Dwarf_Die arg; 11290Sstevel@tonic-gate fndef_t *fn; 11300Sstevel@tonic-gate int i; 11310Sstevel@tonic-gate 11320Sstevel@tonic-gate debug(3, "die %llu: creating function pointer\n", off); 11330Sstevel@tonic-gate 11340Sstevel@tonic-gate /* 11350Sstevel@tonic-gate * We'll begin by processing any type definition nodes that may be 11360Sstevel@tonic-gate * lurking underneath this one. 11370Sstevel@tonic-gate */ 11380Sstevel@tonic-gate for (arg = die_child(dw, die); arg != NULL; 11390Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 11400Sstevel@tonic-gate if ((tag = die_tag(dw, arg)) != DW_TAG_formal_parameter && 11410Sstevel@tonic-gate tag != DW_TAG_unspecified_parameters) { 11420Sstevel@tonic-gate /* Nested type declaration */ 11430Sstevel@tonic-gate die_create_one(dw, arg); 11440Sstevel@tonic-gate } 11450Sstevel@tonic-gate } 11460Sstevel@tonic-gate 11470Sstevel@tonic-gate if (die_isdecl(dw, die)) { 11480Sstevel@tonic-gate /* 11490Sstevel@tonic-gate * This is a prototype. We don't add prototypes to the 11500Sstevel@tonic-gate * tree, so we're going to drop the tdesc. Unfortunately, 11510Sstevel@tonic-gate * it has already been added to the tree. Nobody will reference 11520Sstevel@tonic-gate * it, though, and it will be leaked. 11530Sstevel@tonic-gate */ 11540Sstevel@tonic-gate return; 11550Sstevel@tonic-gate } 11560Sstevel@tonic-gate 11570Sstevel@tonic-gate fn = xcalloc(sizeof (fndef_t)); 11580Sstevel@tonic-gate 11590Sstevel@tonic-gate tdp->t_type = FUNCTION; 11600Sstevel@tonic-gate 11610Sstevel@tonic-gate if ((attr = die_attr(dw, die, DW_AT_type, 0)) != NULL) { 11620Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 11630Sstevel@tonic-gate fn->fn_ret = die_lookup_pass1(dw, die, DW_AT_type); 11640Sstevel@tonic-gate } else { 11650Sstevel@tonic-gate fn->fn_ret = tdesc_intr_void(dw); 11660Sstevel@tonic-gate } 11670Sstevel@tonic-gate 11680Sstevel@tonic-gate /* 11690Sstevel@tonic-gate * Count the arguments to the function, then read them in. 11700Sstevel@tonic-gate */ 11710Sstevel@tonic-gate for (fn->fn_nargs = 0, arg = die_child(dw, die); arg != NULL; 11720Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 11730Sstevel@tonic-gate if ((tag = die_tag(dw, arg)) == DW_TAG_formal_parameter) 11740Sstevel@tonic-gate fn->fn_nargs++; 11750Sstevel@tonic-gate else if (tag == DW_TAG_unspecified_parameters && 11760Sstevel@tonic-gate fn->fn_nargs > 0) 11770Sstevel@tonic-gate fn->fn_vargs = 1; 11780Sstevel@tonic-gate } 11790Sstevel@tonic-gate 11800Sstevel@tonic-gate if (fn->fn_nargs != 0) { 11810Sstevel@tonic-gate debug(3, "die %llu: adding %d argument%s\n", off, fn->fn_nargs, 11820Sstevel@tonic-gate (fn->fn_nargs > 1 ? "s" : "")); 11830Sstevel@tonic-gate 11840Sstevel@tonic-gate fn->fn_args = xcalloc(sizeof (tdesc_t *) * fn->fn_nargs); 11850Sstevel@tonic-gate for (i = 0, arg = die_child(dw, die); 11860Sstevel@tonic-gate arg != NULL && i < fn->fn_nargs; 11870Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 11880Sstevel@tonic-gate if (die_tag(dw, arg) != DW_TAG_formal_parameter) 11890Sstevel@tonic-gate continue; 11900Sstevel@tonic-gate 11910Sstevel@tonic-gate fn->fn_args[i++] = die_lookup_pass1(dw, arg, 11920Sstevel@tonic-gate DW_AT_type); 11930Sstevel@tonic-gate } 11940Sstevel@tonic-gate } 11950Sstevel@tonic-gate 11960Sstevel@tonic-gate tdp->t_fndef = fn; 11970Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 11980Sstevel@tonic-gate } 11990Sstevel@tonic-gate 12000Sstevel@tonic-gate /* 12010Sstevel@tonic-gate * GCC and DevPro use different names for the base types. While the terms are 12020Sstevel@tonic-gate * the same, they are arranged in a different order. Some terms, such as int, 12030Sstevel@tonic-gate * are implied in one, and explicitly named in the other. Given a base type 12040Sstevel@tonic-gate * as input, this routine will return a common name, along with an intr_t 12050Sstevel@tonic-gate * that reflects said name. 12060Sstevel@tonic-gate */ 12070Sstevel@tonic-gate static intr_t * 12080Sstevel@tonic-gate die_base_name_parse(const char *name, char **newp) 12090Sstevel@tonic-gate { 12100Sstevel@tonic-gate char buf[100]; 12110Sstevel@tonic-gate char *base, *c; 12120Sstevel@tonic-gate int nlong = 0, nshort = 0, nchar = 0, nint = 0; 12130Sstevel@tonic-gate int sign = 1; 12140Sstevel@tonic-gate char fmt = '\0'; 12150Sstevel@tonic-gate intr_t *intr; 12160Sstevel@tonic-gate 12170Sstevel@tonic-gate if (strlen(name) > sizeof (buf) - 1) 12180Sstevel@tonic-gate terminate("base type name \"%s\" is too long\n", name); 12190Sstevel@tonic-gate 12200Sstevel@tonic-gate strncpy(buf, name, sizeof (buf)); 12210Sstevel@tonic-gate 12220Sstevel@tonic-gate for (c = strtok(buf, " "); c != NULL; c = strtok(NULL, " ")) { 12230Sstevel@tonic-gate if (strcmp(c, "signed") == 0) 12240Sstevel@tonic-gate sign = 1; 12250Sstevel@tonic-gate else if (strcmp(c, "unsigned") == 0) 12260Sstevel@tonic-gate sign = 0; 12270Sstevel@tonic-gate else if (strcmp(c, "long") == 0) 12280Sstevel@tonic-gate nlong++; 12290Sstevel@tonic-gate else if (strcmp(c, "char") == 0) { 12300Sstevel@tonic-gate nchar++; 12310Sstevel@tonic-gate fmt = 'c'; 12320Sstevel@tonic-gate } else if (strcmp(c, "short") == 0) 12330Sstevel@tonic-gate nshort++; 12340Sstevel@tonic-gate else if (strcmp(c, "int") == 0) 12350Sstevel@tonic-gate nint++; 12360Sstevel@tonic-gate else { 12370Sstevel@tonic-gate /* 12380Sstevel@tonic-gate * If we don't recognize any of the tokens, we'll tell 12390Sstevel@tonic-gate * the caller to fall back to the dwarf-provided 12400Sstevel@tonic-gate * encoding information. 12410Sstevel@tonic-gate */ 12420Sstevel@tonic-gate return (NULL); 12430Sstevel@tonic-gate } 12440Sstevel@tonic-gate } 12450Sstevel@tonic-gate 12460Sstevel@tonic-gate if (nchar > 1 || nshort > 1 || nint > 1 || nlong > 2) 12470Sstevel@tonic-gate return (NULL); 12480Sstevel@tonic-gate 12490Sstevel@tonic-gate if (nchar > 0) { 12500Sstevel@tonic-gate if (nlong > 0 || nshort > 0 || nint > 0) 12510Sstevel@tonic-gate return (NULL); 12520Sstevel@tonic-gate 12530Sstevel@tonic-gate base = "char"; 12540Sstevel@tonic-gate 12550Sstevel@tonic-gate } else if (nshort > 0) { 12560Sstevel@tonic-gate if (nlong > 0) 12570Sstevel@tonic-gate return (NULL); 12580Sstevel@tonic-gate 12590Sstevel@tonic-gate base = "short"; 12600Sstevel@tonic-gate 12610Sstevel@tonic-gate } else if (nlong > 0) { 12620Sstevel@tonic-gate base = "long"; 12630Sstevel@tonic-gate 12640Sstevel@tonic-gate } else { 12650Sstevel@tonic-gate base = "int"; 12660Sstevel@tonic-gate } 12670Sstevel@tonic-gate 12680Sstevel@tonic-gate intr = xcalloc(sizeof (intr_t)); 12690Sstevel@tonic-gate intr->intr_type = INTR_INT; 12700Sstevel@tonic-gate intr->intr_signed = sign; 12710Sstevel@tonic-gate intr->intr_iformat = fmt; 12720Sstevel@tonic-gate 12730Sstevel@tonic-gate snprintf(buf, sizeof (buf), "%s%s%s", 12740Sstevel@tonic-gate (sign ? "" : "unsigned "), 12750Sstevel@tonic-gate (nlong > 1 ? "long " : ""), 12760Sstevel@tonic-gate base); 12770Sstevel@tonic-gate 12780Sstevel@tonic-gate *newp = xstrdup(buf); 12790Sstevel@tonic-gate return (intr); 12800Sstevel@tonic-gate } 12810Sstevel@tonic-gate 12820Sstevel@tonic-gate typedef struct fp_size_map { 12830Sstevel@tonic-gate size_t fsm_typesz[2]; /* size of {32,64} type */ 12840Sstevel@tonic-gate uint_t fsm_enc[3]; /* CTF_FP_* for {bare,cplx,imagry} type */ 12850Sstevel@tonic-gate } fp_size_map_t; 12860Sstevel@tonic-gate 12870Sstevel@tonic-gate static const fp_size_map_t fp_encodings[] = { 12880Sstevel@tonic-gate { { 4, 4 }, { CTF_FP_SINGLE, CTF_FP_CPLX, CTF_FP_IMAGRY } }, 12890Sstevel@tonic-gate { { 8, 8 }, { CTF_FP_DOUBLE, CTF_FP_DCPLX, CTF_FP_DIMAGRY } }, 1290436Sdmick #ifdef __sparc 1291436Sdmick { { 16, 16 }, { CTF_FP_LDOUBLE, CTF_FP_LDCPLX, CTF_FP_LDIMAGRY } }, 1292436Sdmick #else 12930Sstevel@tonic-gate { { 12, 16 }, { CTF_FP_LDOUBLE, CTF_FP_LDCPLX, CTF_FP_LDIMAGRY } }, 1294436Sdmick #endif 12950Sstevel@tonic-gate { { 0, 0 } } 12960Sstevel@tonic-gate }; 12970Sstevel@tonic-gate 12980Sstevel@tonic-gate static uint_t 12990Sstevel@tonic-gate die_base_type2enc(dwarf_t *dw, Dwarf_Off off, Dwarf_Signed enc, size_t sz) 13000Sstevel@tonic-gate { 13010Sstevel@tonic-gate const fp_size_map_t *map = fp_encodings; 13020Sstevel@tonic-gate uint_t szidx = dw->dw_ptrsz == sizeof (uint64_t); 13030Sstevel@tonic-gate uint_t mult = 1, col = 0; 13040Sstevel@tonic-gate 13050Sstevel@tonic-gate if (enc == DW_ATE_complex_float) { 13060Sstevel@tonic-gate mult = 2; 13070Sstevel@tonic-gate col = 1; 13080Sstevel@tonic-gate } else if (enc == DW_ATE_imaginary_float || 13090Sstevel@tonic-gate enc == DW_ATE_SUN_imaginary_float) 13100Sstevel@tonic-gate col = 2; 13110Sstevel@tonic-gate 13120Sstevel@tonic-gate while (map->fsm_typesz[szidx] != 0) { 13130Sstevel@tonic-gate if (map->fsm_typesz[szidx] * mult == sz) 13140Sstevel@tonic-gate return (map->fsm_enc[col]); 13150Sstevel@tonic-gate map++; 13160Sstevel@tonic-gate } 13170Sstevel@tonic-gate 13180Sstevel@tonic-gate terminate("die %llu: unrecognized real type size %u\n", off, sz); 13190Sstevel@tonic-gate /*NOTREACHED*/ 13200Sstevel@tonic-gate return (0); 13210Sstevel@tonic-gate } 13220Sstevel@tonic-gate 13230Sstevel@tonic-gate static intr_t * 13240Sstevel@tonic-gate die_base_from_dwarf(dwarf_t *dw, Dwarf_Die base, Dwarf_Off off, size_t sz) 13250Sstevel@tonic-gate { 13260Sstevel@tonic-gate intr_t *intr = xcalloc(sizeof (intr_t)); 13270Sstevel@tonic-gate Dwarf_Signed enc; 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate (void) die_signed(dw, base, DW_AT_encoding, &enc, DW_ATTR_REQ); 13300Sstevel@tonic-gate 13310Sstevel@tonic-gate switch (enc) { 13320Sstevel@tonic-gate case DW_ATE_unsigned: 13330Sstevel@tonic-gate case DW_ATE_address: 13340Sstevel@tonic-gate intr->intr_type = INTR_INT; 13350Sstevel@tonic-gate break; 13360Sstevel@tonic-gate case DW_ATE_unsigned_char: 13370Sstevel@tonic-gate intr->intr_type = INTR_INT; 13380Sstevel@tonic-gate intr->intr_iformat = 'c'; 13390Sstevel@tonic-gate break; 13400Sstevel@tonic-gate case DW_ATE_signed: 13410Sstevel@tonic-gate intr->intr_type = INTR_INT; 13420Sstevel@tonic-gate intr->intr_signed = 1; 13430Sstevel@tonic-gate break; 13440Sstevel@tonic-gate case DW_ATE_signed_char: 13450Sstevel@tonic-gate intr->intr_type = INTR_INT; 13460Sstevel@tonic-gate intr->intr_signed = 1; 13470Sstevel@tonic-gate intr->intr_iformat = 'c'; 13480Sstevel@tonic-gate break; 13490Sstevel@tonic-gate case DW_ATE_boolean: 13500Sstevel@tonic-gate intr->intr_type = INTR_INT; 13510Sstevel@tonic-gate intr->intr_signed = 1; 13520Sstevel@tonic-gate intr->intr_iformat = 'b'; 13530Sstevel@tonic-gate break; 13540Sstevel@tonic-gate case DW_ATE_float: 13550Sstevel@tonic-gate case DW_ATE_complex_float: 13560Sstevel@tonic-gate case DW_ATE_imaginary_float: 13570Sstevel@tonic-gate case DW_ATE_SUN_imaginary_float: 13580Sstevel@tonic-gate case DW_ATE_SUN_interval_float: 13590Sstevel@tonic-gate intr->intr_type = INTR_REAL; 13600Sstevel@tonic-gate intr->intr_signed = 1; 13610Sstevel@tonic-gate intr->intr_fformat = die_base_type2enc(dw, off, enc, sz); 13620Sstevel@tonic-gate break; 13630Sstevel@tonic-gate default: 13640Sstevel@tonic-gate terminate("die %llu: unknown base type encoding 0x%llx\n", 13650Sstevel@tonic-gate off, enc); 13660Sstevel@tonic-gate } 13670Sstevel@tonic-gate 13680Sstevel@tonic-gate return (intr); 13690Sstevel@tonic-gate } 13700Sstevel@tonic-gate 13710Sstevel@tonic-gate static void 13720Sstevel@tonic-gate die_base_create(dwarf_t *dw, Dwarf_Die base, Dwarf_Off off, tdesc_t *tdp) 13730Sstevel@tonic-gate { 13740Sstevel@tonic-gate Dwarf_Unsigned sz; 13750Sstevel@tonic-gate intr_t *intr; 13760Sstevel@tonic-gate char *new; 13770Sstevel@tonic-gate 13780Sstevel@tonic-gate debug(3, "die %llu: creating base type\n", off); 13790Sstevel@tonic-gate 13800Sstevel@tonic-gate /* 13810Sstevel@tonic-gate * The compilers have their own clever (internally inconsistent) ideas 13820Sstevel@tonic-gate * as to what base types should look like. Some times gcc will, for 13830Sstevel@tonic-gate * example, use DW_ATE_signed_char for char. Other times, however, it 13840Sstevel@tonic-gate * will use DW_ATE_signed. Needless to say, this causes some problems 13850Sstevel@tonic-gate * down the road, particularly with merging. We do, however, use the 13860Sstevel@tonic-gate * DWARF idea of type sizes, as this allows us to avoid caring about 13870Sstevel@tonic-gate * the data model. 13880Sstevel@tonic-gate */ 13890Sstevel@tonic-gate (void) die_unsigned(dw, base, DW_AT_byte_size, &sz, DW_ATTR_REQ); 13900Sstevel@tonic-gate 13910Sstevel@tonic-gate if (tdp->t_name == NULL) 13920Sstevel@tonic-gate terminate("die %llu: base type without name\n", off); 13930Sstevel@tonic-gate 13940Sstevel@tonic-gate /* XXX make a name parser for float too */ 13950Sstevel@tonic-gate if ((intr = die_base_name_parse(tdp->t_name, &new)) != NULL) { 13960Sstevel@tonic-gate /* Found it. We'll use the parsed version */ 13970Sstevel@tonic-gate debug(3, "die %llu: name \"%s\" remapped to \"%s\"\n", off, 13981882Sjohnlev tdesc_name(tdp), new); 13990Sstevel@tonic-gate 14000Sstevel@tonic-gate free(tdp->t_name); 14010Sstevel@tonic-gate tdp->t_name = new; 14020Sstevel@tonic-gate } else { 14030Sstevel@tonic-gate /* 14040Sstevel@tonic-gate * We didn't recognize the type, so we'll create an intr_t 14050Sstevel@tonic-gate * based on the DWARF data. 14060Sstevel@tonic-gate */ 14070Sstevel@tonic-gate debug(3, "die %llu: using dwarf data for base \"%s\"\n", off, 14081882Sjohnlev tdesc_name(tdp)); 14090Sstevel@tonic-gate 14100Sstevel@tonic-gate intr = die_base_from_dwarf(dw, base, off, sz); 14110Sstevel@tonic-gate } 14120Sstevel@tonic-gate 14130Sstevel@tonic-gate intr->intr_nbits = sz * 8; 14140Sstevel@tonic-gate 14150Sstevel@tonic-gate tdp->t_type = INTRINSIC; 14160Sstevel@tonic-gate tdp->t_intr = intr; 14170Sstevel@tonic-gate tdp->t_size = sz; 14180Sstevel@tonic-gate 14190Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 14200Sstevel@tonic-gate } 14210Sstevel@tonic-gate 14220Sstevel@tonic-gate static void 14230Sstevel@tonic-gate die_through_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp, 14240Sstevel@tonic-gate int type, const char *typename) 14250Sstevel@tonic-gate { 14260Sstevel@tonic-gate Dwarf_Attribute attr; 14270Sstevel@tonic-gate 14280Sstevel@tonic-gate debug(3, "die %llu: creating %s\n", off, typename); 14290Sstevel@tonic-gate 14300Sstevel@tonic-gate tdp->t_type = type; 14310Sstevel@tonic-gate 14320Sstevel@tonic-gate if ((attr = die_attr(dw, die, DW_AT_type, 0)) != NULL) { 14330Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 14340Sstevel@tonic-gate tdp->t_tdesc = die_lookup_pass1(dw, die, DW_AT_type); 14350Sstevel@tonic-gate } else { 14360Sstevel@tonic-gate tdp->t_tdesc = tdesc_intr_void(dw); 14370Sstevel@tonic-gate } 14380Sstevel@tonic-gate 14390Sstevel@tonic-gate if (type == POINTER) 14400Sstevel@tonic-gate tdp->t_size = dw->dw_ptrsz; 14410Sstevel@tonic-gate 14420Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 14430Sstevel@tonic-gate 14440Sstevel@tonic-gate if (type == TYPEDEF) { 14450Sstevel@tonic-gate iidesc_t *ii = xcalloc(sizeof (iidesc_t)); 14460Sstevel@tonic-gate ii->ii_type = II_TYPE; 14470Sstevel@tonic-gate ii->ii_name = xstrdup(tdp->t_name); 14480Sstevel@tonic-gate ii->ii_dtype = tdp; 14490Sstevel@tonic-gate 14500Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 14510Sstevel@tonic-gate } 14520Sstevel@tonic-gate } 14530Sstevel@tonic-gate 14540Sstevel@tonic-gate static void 14550Sstevel@tonic-gate die_typedef_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 14560Sstevel@tonic-gate { 14570Sstevel@tonic-gate die_through_create(dw, die, off, tdp, TYPEDEF, "typedef"); 14580Sstevel@tonic-gate } 14590Sstevel@tonic-gate 14600Sstevel@tonic-gate static void 14610Sstevel@tonic-gate die_const_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 14620Sstevel@tonic-gate { 14630Sstevel@tonic-gate die_through_create(dw, die, off, tdp, CONST, "const"); 14640Sstevel@tonic-gate } 14650Sstevel@tonic-gate 14660Sstevel@tonic-gate static void 14670Sstevel@tonic-gate die_pointer_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 14680Sstevel@tonic-gate { 14690Sstevel@tonic-gate die_through_create(dw, die, off, tdp, POINTER, "pointer"); 14700Sstevel@tonic-gate } 14710Sstevel@tonic-gate 14720Sstevel@tonic-gate static void 14730Sstevel@tonic-gate die_restrict_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 14740Sstevel@tonic-gate { 14750Sstevel@tonic-gate die_through_create(dw, die, off, tdp, RESTRICT, "restrict"); 14760Sstevel@tonic-gate } 14770Sstevel@tonic-gate 14780Sstevel@tonic-gate static void 14790Sstevel@tonic-gate die_volatile_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 14800Sstevel@tonic-gate { 14810Sstevel@tonic-gate die_through_create(dw, die, off, tdp, VOLATILE, "volatile"); 14820Sstevel@tonic-gate } 14830Sstevel@tonic-gate 14840Sstevel@tonic-gate /*ARGSUSED3*/ 14850Sstevel@tonic-gate static void 14860Sstevel@tonic-gate die_function_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 14870Sstevel@tonic-gate { 14880Sstevel@tonic-gate Dwarf_Die arg; 14890Sstevel@tonic-gate Dwarf_Half tag; 14900Sstevel@tonic-gate iidesc_t *ii; 14910Sstevel@tonic-gate char *name; 14920Sstevel@tonic-gate 14930Sstevel@tonic-gate debug(3, "die %llu: creating function definition\n", off); 14940Sstevel@tonic-gate 14950Sstevel@tonic-gate /* 14960Sstevel@tonic-gate * We'll begin by processing any type definition nodes that may be 14970Sstevel@tonic-gate * lurking underneath this one. 14980Sstevel@tonic-gate */ 14990Sstevel@tonic-gate for (arg = die_child(dw, die); arg != NULL; 15000Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 15010Sstevel@tonic-gate if ((tag = die_tag(dw, arg)) != DW_TAG_formal_parameter && 15020Sstevel@tonic-gate tag != DW_TAG_variable) { 15030Sstevel@tonic-gate /* Nested type declaration */ 15040Sstevel@tonic-gate die_create_one(dw, arg); 15050Sstevel@tonic-gate } 15060Sstevel@tonic-gate } 15070Sstevel@tonic-gate 15080Sstevel@tonic-gate if (die_isdecl(dw, die) || (name = die_name(dw, die)) == NULL) { 15090Sstevel@tonic-gate /* 15100Sstevel@tonic-gate * We process neither prototypes nor subprograms without 15110Sstevel@tonic-gate * names. 15120Sstevel@tonic-gate */ 15130Sstevel@tonic-gate return; 15140Sstevel@tonic-gate } 15150Sstevel@tonic-gate 15160Sstevel@tonic-gate ii = xcalloc(sizeof (iidesc_t)); 15170Sstevel@tonic-gate ii->ii_type = die_isglobal(dw, die) ? II_GFUN : II_SFUN; 15180Sstevel@tonic-gate ii->ii_name = name; 15190Sstevel@tonic-gate if (ii->ii_type == II_SFUN) 15200Sstevel@tonic-gate ii->ii_owner = xstrdup(dw->dw_cuname); 15210Sstevel@tonic-gate 15220Sstevel@tonic-gate debug(3, "die %llu: function %s is %s\n", off, ii->ii_name, 15230Sstevel@tonic-gate (ii->ii_type == II_GFUN ? "global" : "static")); 15240Sstevel@tonic-gate 15250Sstevel@tonic-gate if (die_attr(dw, die, DW_AT_type, 0) != NULL) 15260Sstevel@tonic-gate ii->ii_dtype = die_lookup_pass1(dw, die, DW_AT_type); 15270Sstevel@tonic-gate else 15280Sstevel@tonic-gate ii->ii_dtype = tdesc_intr_void(dw); 15290Sstevel@tonic-gate 15300Sstevel@tonic-gate for (arg = die_child(dw, die); arg != NULL; 15310Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 15320Sstevel@tonic-gate char *name; 15330Sstevel@tonic-gate 15340Sstevel@tonic-gate debug(3, "die %llu: looking at sub member at %llu\n", 15350Sstevel@tonic-gate off, die_off(dw, die)); 15360Sstevel@tonic-gate 15370Sstevel@tonic-gate if (die_tag(dw, arg) != DW_TAG_formal_parameter) 15380Sstevel@tonic-gate continue; 15390Sstevel@tonic-gate 15400Sstevel@tonic-gate if ((name = die_name(dw, arg)) == NULL) { 15410Sstevel@tonic-gate terminate("die %llu: func arg %d has no name\n", 15420Sstevel@tonic-gate off, ii->ii_nargs + 1); 15430Sstevel@tonic-gate } 15440Sstevel@tonic-gate 15450Sstevel@tonic-gate if (strcmp(name, "...") == 0) { 15460Sstevel@tonic-gate free(name); 15470Sstevel@tonic-gate ii->ii_vargs = 1; 15480Sstevel@tonic-gate continue; 15490Sstevel@tonic-gate } 15500Sstevel@tonic-gate 15510Sstevel@tonic-gate ii->ii_nargs++; 15520Sstevel@tonic-gate } 15530Sstevel@tonic-gate 15540Sstevel@tonic-gate if (ii->ii_nargs > 0) { 15550Sstevel@tonic-gate int i; 15560Sstevel@tonic-gate 15570Sstevel@tonic-gate debug(3, "die %llu: function has %d argument%s\n", off, 15580Sstevel@tonic-gate ii->ii_nargs, (ii->ii_nargs == 1 ? "" : "s")); 15590Sstevel@tonic-gate 15600Sstevel@tonic-gate ii->ii_args = xcalloc(sizeof (tdesc_t) * ii->ii_nargs); 15610Sstevel@tonic-gate 15620Sstevel@tonic-gate for (arg = die_child(dw, die), i = 0; 15630Sstevel@tonic-gate arg != NULL && i < ii->ii_nargs; 15640Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 15650Sstevel@tonic-gate if (die_tag(dw, arg) != DW_TAG_formal_parameter) 15660Sstevel@tonic-gate continue; 15670Sstevel@tonic-gate 15680Sstevel@tonic-gate ii->ii_args[i++] = die_lookup_pass1(dw, arg, 15690Sstevel@tonic-gate DW_AT_type); 15700Sstevel@tonic-gate } 15710Sstevel@tonic-gate } 15720Sstevel@tonic-gate 15730Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 15740Sstevel@tonic-gate } 15750Sstevel@tonic-gate 15760Sstevel@tonic-gate /*ARGSUSED3*/ 15770Sstevel@tonic-gate static void 15780Sstevel@tonic-gate die_variable_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 15790Sstevel@tonic-gate { 15800Sstevel@tonic-gate iidesc_t *ii; 15810Sstevel@tonic-gate char *name; 15820Sstevel@tonic-gate 15830Sstevel@tonic-gate debug(3, "die %llu: creating object definition\n", off); 15840Sstevel@tonic-gate 15850Sstevel@tonic-gate if (die_isdecl(dw, die) || (name = die_name(dw, die)) == NULL) 15860Sstevel@tonic-gate return; /* skip prototypes and nameless objects */ 15870Sstevel@tonic-gate 15880Sstevel@tonic-gate ii = xcalloc(sizeof (iidesc_t)); 15890Sstevel@tonic-gate ii->ii_type = die_isglobal(dw, die) ? II_GVAR : II_SVAR; 15900Sstevel@tonic-gate ii->ii_name = name; 15910Sstevel@tonic-gate ii->ii_dtype = die_lookup_pass1(dw, die, DW_AT_type); 15920Sstevel@tonic-gate if (ii->ii_type == II_SVAR) 15930Sstevel@tonic-gate ii->ii_owner = xstrdup(dw->dw_cuname); 15940Sstevel@tonic-gate 15950Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 15960Sstevel@tonic-gate } 15970Sstevel@tonic-gate 15980Sstevel@tonic-gate /*ARGSUSED2*/ 15990Sstevel@tonic-gate static int 16000Sstevel@tonic-gate die_fwd_resolve(tdesc_t *fwd, tdesc_t **fwdp, void *private) 16010Sstevel@tonic-gate { 16020Sstevel@tonic-gate if (fwd->t_flags & TDESC_F_RESOLVED) 16030Sstevel@tonic-gate return (1); 16040Sstevel@tonic-gate 16050Sstevel@tonic-gate if (fwd->t_tdesc != NULL) { 16061882Sjohnlev debug(3, "tdp %u: unforwarded %s\n", fwd->t_id, 16071882Sjohnlev tdesc_name(fwd)); 16080Sstevel@tonic-gate *fwdp = fwd->t_tdesc; 16090Sstevel@tonic-gate } 16100Sstevel@tonic-gate 16110Sstevel@tonic-gate fwd->t_flags |= TDESC_F_RESOLVED; 16120Sstevel@tonic-gate 16130Sstevel@tonic-gate return (1); 16140Sstevel@tonic-gate } 16150Sstevel@tonic-gate 16160Sstevel@tonic-gate /*ARGSUSED*/ 16170Sstevel@tonic-gate static void 16180Sstevel@tonic-gate die_lexblk_descend(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 16190Sstevel@tonic-gate { 16200Sstevel@tonic-gate Dwarf_Die child = die_child(dw, die); 16210Sstevel@tonic-gate 16220Sstevel@tonic-gate if (child != NULL) 16230Sstevel@tonic-gate die_create(dw, child); 16240Sstevel@tonic-gate } 16250Sstevel@tonic-gate 16260Sstevel@tonic-gate /* 16270Sstevel@tonic-gate * Used to map the die to a routine which can parse it, using the tag to do the 16280Sstevel@tonic-gate * mapping. While the processing of most tags entails the creation of a tdesc, 16290Sstevel@tonic-gate * there are a few which don't - primarily those which result in the creation of 16300Sstevel@tonic-gate * iidescs which refer to existing tdescs. 16310Sstevel@tonic-gate */ 16320Sstevel@tonic-gate 16330Sstevel@tonic-gate #define DW_F_NOTDP 0x1 /* Don't create a tdesc for the creator */ 16340Sstevel@tonic-gate 16350Sstevel@tonic-gate typedef struct die_creator { 16360Sstevel@tonic-gate Dwarf_Half dc_tag; 16370Sstevel@tonic-gate uint16_t dc_flags; 16380Sstevel@tonic-gate void (*dc_create)(dwarf_t *, Dwarf_Die, Dwarf_Off, tdesc_t *); 16390Sstevel@tonic-gate } die_creator_t; 16400Sstevel@tonic-gate 16410Sstevel@tonic-gate static const die_creator_t die_creators[] = { 16420Sstevel@tonic-gate { DW_TAG_array_type, 0, die_array_create }, 16430Sstevel@tonic-gate { DW_TAG_enumeration_type, 0, die_enum_create }, 16440Sstevel@tonic-gate { DW_TAG_lexical_block, DW_F_NOTDP, die_lexblk_descend }, 16450Sstevel@tonic-gate { DW_TAG_pointer_type, 0, die_pointer_create }, 16460Sstevel@tonic-gate { DW_TAG_structure_type, 0, die_struct_create }, 16470Sstevel@tonic-gate { DW_TAG_subroutine_type, 0, die_funcptr_create }, 16480Sstevel@tonic-gate { DW_TAG_typedef, 0, die_typedef_create }, 16490Sstevel@tonic-gate { DW_TAG_union_type, 0, die_union_create }, 16500Sstevel@tonic-gate { DW_TAG_base_type, 0, die_base_create }, 16510Sstevel@tonic-gate { DW_TAG_const_type, 0, die_const_create }, 16520Sstevel@tonic-gate { DW_TAG_subprogram, DW_F_NOTDP, die_function_create }, 16530Sstevel@tonic-gate { DW_TAG_variable, DW_F_NOTDP, die_variable_create }, 16540Sstevel@tonic-gate { DW_TAG_volatile_type, 0, die_volatile_create }, 16550Sstevel@tonic-gate { DW_TAG_restrict_type, 0, die_restrict_create }, 16560Sstevel@tonic-gate { 0, NULL } 16570Sstevel@tonic-gate }; 16580Sstevel@tonic-gate 16590Sstevel@tonic-gate static const die_creator_t * 16600Sstevel@tonic-gate die_tag2ctor(Dwarf_Half tag) 16610Sstevel@tonic-gate { 16620Sstevel@tonic-gate const die_creator_t *dc; 16630Sstevel@tonic-gate 16640Sstevel@tonic-gate for (dc = die_creators; dc->dc_create != NULL; dc++) { 16650Sstevel@tonic-gate if (dc->dc_tag == tag) 16660Sstevel@tonic-gate return (dc); 16670Sstevel@tonic-gate } 16680Sstevel@tonic-gate 16690Sstevel@tonic-gate return (NULL); 16700Sstevel@tonic-gate } 16710Sstevel@tonic-gate 16720Sstevel@tonic-gate static void 16730Sstevel@tonic-gate die_create_one(dwarf_t *dw, Dwarf_Die die) 16740Sstevel@tonic-gate { 16750Sstevel@tonic-gate Dwarf_Off off = die_off(dw, die); 16760Sstevel@tonic-gate const die_creator_t *dc; 16770Sstevel@tonic-gate Dwarf_Half tag; 16780Sstevel@tonic-gate tdesc_t *tdp; 16790Sstevel@tonic-gate 16800Sstevel@tonic-gate debug(3, "die %llu: create_one\n", off); 16810Sstevel@tonic-gate 16820Sstevel@tonic-gate if (off > dw->dw_maxoff) { 16830Sstevel@tonic-gate terminate("illegal die offset %llu (max %llu)\n", off, 16840Sstevel@tonic-gate dw->dw_maxoff); 16850Sstevel@tonic-gate } 16860Sstevel@tonic-gate 16870Sstevel@tonic-gate tag = die_tag(dw, die); 16880Sstevel@tonic-gate 16890Sstevel@tonic-gate if ((dc = die_tag2ctor(tag)) == NULL) { 16900Sstevel@tonic-gate debug(2, "die %llu: ignoring tag type %x\n", off, tag); 16910Sstevel@tonic-gate return; 16920Sstevel@tonic-gate } 16930Sstevel@tonic-gate 16940Sstevel@tonic-gate if ((tdp = tdesc_lookup(dw, off)) == NULL && 16950Sstevel@tonic-gate !(dc->dc_flags & DW_F_NOTDP)) { 16960Sstevel@tonic-gate tdp = xcalloc(sizeof (tdesc_t)); 16970Sstevel@tonic-gate tdp->t_id = off; 16980Sstevel@tonic-gate tdesc_add(dw, tdp); 16990Sstevel@tonic-gate } 17000Sstevel@tonic-gate 17010Sstevel@tonic-gate if (tdp != NULL) 17020Sstevel@tonic-gate tdp->t_name = die_name(dw, die); 17030Sstevel@tonic-gate 17040Sstevel@tonic-gate dc->dc_create(dw, die, off, tdp); 17050Sstevel@tonic-gate } 17060Sstevel@tonic-gate 17070Sstevel@tonic-gate static void 17080Sstevel@tonic-gate die_create(dwarf_t *dw, Dwarf_Die die) 17090Sstevel@tonic-gate { 17100Sstevel@tonic-gate do { 17110Sstevel@tonic-gate die_create_one(dw, die); 17120Sstevel@tonic-gate } while ((die = die_sibling(dw, die)) != NULL); 17130Sstevel@tonic-gate } 17140Sstevel@tonic-gate 17150Sstevel@tonic-gate static tdtrav_cb_f die_resolvers[] = { 17160Sstevel@tonic-gate NULL, 17170Sstevel@tonic-gate NULL, /* intrinsic */ 17180Sstevel@tonic-gate NULL, /* pointer */ 17190Sstevel@tonic-gate die_array_resolve, /* array */ 17200Sstevel@tonic-gate NULL, /* function */ 17210Sstevel@tonic-gate die_sou_resolve, /* struct */ 17220Sstevel@tonic-gate die_sou_resolve, /* union */ 17230Sstevel@tonic-gate die_enum_resolve, /* enum */ 17240Sstevel@tonic-gate die_fwd_resolve, /* forward */ 17250Sstevel@tonic-gate NULL, /* typedef */ 17260Sstevel@tonic-gate NULL, /* typedef unres */ 17270Sstevel@tonic-gate NULL, /* volatile */ 17280Sstevel@tonic-gate NULL, /* const */ 17290Sstevel@tonic-gate NULL, /* restrict */ 17300Sstevel@tonic-gate }; 17310Sstevel@tonic-gate 17320Sstevel@tonic-gate static tdtrav_cb_f die_fail_reporters[] = { 17330Sstevel@tonic-gate NULL, 17340Sstevel@tonic-gate NULL, /* intrinsic */ 17350Sstevel@tonic-gate NULL, /* pointer */ 17360Sstevel@tonic-gate die_array_failed, /* array */ 17370Sstevel@tonic-gate NULL, /* function */ 17380Sstevel@tonic-gate die_sou_failed, /* struct */ 17390Sstevel@tonic-gate die_sou_failed, /* union */ 17400Sstevel@tonic-gate NULL, /* enum */ 17410Sstevel@tonic-gate NULL, /* forward */ 17420Sstevel@tonic-gate NULL, /* typedef */ 17430Sstevel@tonic-gate NULL, /* typedef unres */ 17440Sstevel@tonic-gate NULL, /* volatile */ 17450Sstevel@tonic-gate NULL, /* const */ 17460Sstevel@tonic-gate NULL, /* restrict */ 17470Sstevel@tonic-gate }; 17480Sstevel@tonic-gate 17490Sstevel@tonic-gate static void 17500Sstevel@tonic-gate die_resolve(dwarf_t *dw) 17510Sstevel@tonic-gate { 17520Sstevel@tonic-gate int last = -1; 17530Sstevel@tonic-gate int pass = 0; 17540Sstevel@tonic-gate 17550Sstevel@tonic-gate do { 17560Sstevel@tonic-gate pass++; 17570Sstevel@tonic-gate dw->dw_nunres = 0; 17580Sstevel@tonic-gate 17590Sstevel@tonic-gate (void) iitraverse_hash(dw->dw_td->td_iihash, 17600Sstevel@tonic-gate &dw->dw_td->td_curvgen, NULL, NULL, die_resolvers, dw); 17610Sstevel@tonic-gate 17620Sstevel@tonic-gate debug(3, "resolve: pass %d, %u left\n", pass, dw->dw_nunres); 17630Sstevel@tonic-gate 17640Sstevel@tonic-gate if (dw->dw_nunres == last) { 17650Sstevel@tonic-gate fprintf(stderr, "%s: failed to resolve the following " 17660Sstevel@tonic-gate "types:\n", progname); 17670Sstevel@tonic-gate 17680Sstevel@tonic-gate (void) iitraverse_hash(dw->dw_td->td_iihash, 17690Sstevel@tonic-gate &dw->dw_td->td_curvgen, NULL, NULL, 17700Sstevel@tonic-gate die_fail_reporters, dw); 17710Sstevel@tonic-gate 17720Sstevel@tonic-gate terminate("failed to resolve types\n"); 17730Sstevel@tonic-gate } 17740Sstevel@tonic-gate 17750Sstevel@tonic-gate last = dw->dw_nunres; 17760Sstevel@tonic-gate 17770Sstevel@tonic-gate } while (dw->dw_nunres != 0); 17780Sstevel@tonic-gate } 17790Sstevel@tonic-gate 17800Sstevel@tonic-gate /*ARGSUSED*/ 17810Sstevel@tonic-gate int 17820Sstevel@tonic-gate dw_read(tdata_t *td, Elf *elf, const char *filename) 17830Sstevel@tonic-gate { 17840Sstevel@tonic-gate Dwarf_Unsigned abboff, hdrlen, nxthdr; 17850Sstevel@tonic-gate Dwarf_Half vers, addrsz; 17860Sstevel@tonic-gate Dwarf_Die cu, child; 17870Sstevel@tonic-gate dwarf_t dw; 17880Sstevel@tonic-gate char *prod = NULL; 17890Sstevel@tonic-gate int rc; 17900Sstevel@tonic-gate 17910Sstevel@tonic-gate bzero(&dw, sizeof (dwarf_t)); 17920Sstevel@tonic-gate dw.dw_td = td; 17930Sstevel@tonic-gate dw.dw_ptrsz = elf_ptrsz(elf); 17940Sstevel@tonic-gate dw.dw_mfgtid_last = TID_MFGTID_BASE; 17950Sstevel@tonic-gate dw.dw_tidhash = hash_new(TDESC_HASH_BUCKETS, tdesc_idhash, tdesc_idcmp); 17960Sstevel@tonic-gate dw.dw_fwdhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash, 17970Sstevel@tonic-gate tdesc_namecmp); 17980Sstevel@tonic-gate dw.dw_enumhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash, 17990Sstevel@tonic-gate tdesc_namecmp); 18000Sstevel@tonic-gate 18010Sstevel@tonic-gate if ((rc = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dw.dw_dw, 18020Sstevel@tonic-gate &dw.dw_err)) == DW_DLV_NO_ENTRY) { 18030Sstevel@tonic-gate errno = ENOENT; 18040Sstevel@tonic-gate return (-1); 18050Sstevel@tonic-gate } else if (rc != DW_DLV_OK) { 18060Sstevel@tonic-gate if (dwarf_errno(dw.dw_err) == DW_DLE_DEBUG_INFO_NULL) { 18070Sstevel@tonic-gate /* 18080Sstevel@tonic-gate * There's no type data in the DWARF section, but 18090Sstevel@tonic-gate * libdwarf is too clever to handle that properly. 18100Sstevel@tonic-gate */ 18110Sstevel@tonic-gate return (0); 18120Sstevel@tonic-gate } 18130Sstevel@tonic-gate 18140Sstevel@tonic-gate terminate("failed to initialize DWARF: %s\n", 18150Sstevel@tonic-gate dwarf_errmsg(dw.dw_err)); 18160Sstevel@tonic-gate } 18170Sstevel@tonic-gate 18180Sstevel@tonic-gate if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff, 18190Sstevel@tonic-gate &addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_OK || 18200Sstevel@tonic-gate (cu = die_sibling(&dw, NULL)) == NULL || 18210Sstevel@tonic-gate (child = die_child(&dw, cu)) == NULL) 18220Sstevel@tonic-gate terminate("file does not contain dwarf type data " 18230Sstevel@tonic-gate "(try compiling with -g)\n"); 18240Sstevel@tonic-gate 18250Sstevel@tonic-gate dw.dw_maxoff = nxthdr - 1; 18260Sstevel@tonic-gate 18270Sstevel@tonic-gate if (dw.dw_maxoff > TID_FILEMAX) 18280Sstevel@tonic-gate terminate("file contains too many types\n"); 18290Sstevel@tonic-gate 18300Sstevel@tonic-gate debug(1, "DWARF version: %d\n", vers); 18310Sstevel@tonic-gate if (vers != DWARF_VERSION) { 18320Sstevel@tonic-gate terminate("file contains incompatible version %d DWARF code " 18330Sstevel@tonic-gate "(version 2 required)\n", vers); 18340Sstevel@tonic-gate } 18350Sstevel@tonic-gate 18360Sstevel@tonic-gate if (die_string(&dw, cu, DW_AT_producer, &prod, 0)) { 18370Sstevel@tonic-gate debug(1, "DWARF emitter: %s\n", prod); 18380Sstevel@tonic-gate free(prod); 18390Sstevel@tonic-gate } 18400Sstevel@tonic-gate 18410Sstevel@tonic-gate if ((dw.dw_cuname = die_name(&dw, cu)) != NULL) { 18420Sstevel@tonic-gate char *base = xstrdup(basename(dw.dw_cuname)); 18430Sstevel@tonic-gate free(dw.dw_cuname); 18440Sstevel@tonic-gate dw.dw_cuname = base; 18450Sstevel@tonic-gate 18460Sstevel@tonic-gate debug(1, "CU name: %s\n", dw.dw_cuname); 18470Sstevel@tonic-gate } 18480Sstevel@tonic-gate 18490Sstevel@tonic-gate die_create(&dw, child); 18500Sstevel@tonic-gate 18510Sstevel@tonic-gate if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff, 18520Sstevel@tonic-gate &addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_NO_ENTRY) 18530Sstevel@tonic-gate terminate("multiple compilation units not supported\n"); 18540Sstevel@tonic-gate 18550Sstevel@tonic-gate (void) dwarf_finish(dw.dw_dw, &dw.dw_err); 18560Sstevel@tonic-gate 18570Sstevel@tonic-gate die_resolve(&dw); 18580Sstevel@tonic-gate 1859*2722Sjohnlev cvt_fixups(td, dw.dw_ptrsz); 1860*2722Sjohnlev 18610Sstevel@tonic-gate /* leak the dwarf_t */ 18620Sstevel@tonic-gate 18630Sstevel@tonic-gate return (0); 18640Sstevel@tonic-gate } 1865