1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * DWARF to tdata conversion 31*7c478bd9Sstevel@tonic-gate * 32*7c478bd9Sstevel@tonic-gate * For the most part, conversion is straightforward, proceeding in two passes. 33*7c478bd9Sstevel@tonic-gate * On the first pass, we iterate through every die, creating new type nodes as 34*7c478bd9Sstevel@tonic-gate * necessary. Referenced tdesc_t's are created in an uninitialized state, thus 35*7c478bd9Sstevel@tonic-gate * allowing type reference pointers to be filled in. If the tdesc_t 36*7c478bd9Sstevel@tonic-gate * corresponding to a given die can be completely filled out (sizes and offsets 37*7c478bd9Sstevel@tonic-gate * calculated, and so forth) without using any referenced types, the tdesc_t is 38*7c478bd9Sstevel@tonic-gate * marked as resolved. Consider an array type. If the type corresponding to 39*7c478bd9Sstevel@tonic-gate * the array contents has not yet been processed, we will create a blank tdesc 40*7c478bd9Sstevel@tonic-gate * for the contents type (only the type ID will be filled in, relying upon the 41*7c478bd9Sstevel@tonic-gate * later portion of the first pass to encounter and complete the referenced 42*7c478bd9Sstevel@tonic-gate * type). We will then attempt to determine the size of the array. If the 43*7c478bd9Sstevel@tonic-gate * array has a byte size attribute, we will have completely characterized the 44*7c478bd9Sstevel@tonic-gate * array type, and will be able to mark it as resolved. The lack of a byte 45*7c478bd9Sstevel@tonic-gate * size attribute, on the other hand, will prevent us from fully resolving the 46*7c478bd9Sstevel@tonic-gate * type, as the size will only be calculable with reference to the contents 47*7c478bd9Sstevel@tonic-gate * type, which has not, as yet, been encountered. The array type will thus be 48*7c478bd9Sstevel@tonic-gate * left without the resolved flag, and the first pass will continue. 49*7c478bd9Sstevel@tonic-gate * 50*7c478bd9Sstevel@tonic-gate * When we begin the second pass, we will have created tdesc_t nodes for every 51*7c478bd9Sstevel@tonic-gate * type in the section. We will traverse the tree, from the iidescs down, 52*7c478bd9Sstevel@tonic-gate * processing each unresolved node. As the referenced nodes will have been 53*7c478bd9Sstevel@tonic-gate * populated, the array type used in our example above will be able to use the 54*7c478bd9Sstevel@tonic-gate * size of the referenced types (if available) to determine its own type. The 55*7c478bd9Sstevel@tonic-gate * traversal will be repeated until all types have been resolved or we have 56*7c478bd9Sstevel@tonic-gate * failed to make progress. When all tdescs have been resolved, the conversion 57*7c478bd9Sstevel@tonic-gate * is complete. 58*7c478bd9Sstevel@tonic-gate * 59*7c478bd9Sstevel@tonic-gate * There are, as always, a few special cases that are handled during the first 60*7c478bd9Sstevel@tonic-gate * and second passes: 61*7c478bd9Sstevel@tonic-gate * 62*7c478bd9Sstevel@tonic-gate * 1. Empty enums - GCC will occasionally emit an enum without any members. 63*7c478bd9Sstevel@tonic-gate * Later on in the file, it will emit the same enum type, though this time 64*7c478bd9Sstevel@tonic-gate * with the full complement of members. All references to the memberless 65*7c478bd9Sstevel@tonic-gate * enum need to be redirected to the full definition. During the first 66*7c478bd9Sstevel@tonic-gate * pass, each enum is entered in dm_enumhash, along with a pointer to its 67*7c478bd9Sstevel@tonic-gate * corresponding tdesc_t. If, during the second pass, we encounter a 68*7c478bd9Sstevel@tonic-gate * memberless enum, we use the hash to locate the full definition. All 69*7c478bd9Sstevel@tonic-gate * tdescs referencing the empty enum are then redirected. 70*7c478bd9Sstevel@tonic-gate * 71*7c478bd9Sstevel@tonic-gate * 2. Forward declarations - If the compiler sees a forward declaration for 72*7c478bd9Sstevel@tonic-gate * a structure, followed by the definition of that structure, it will emit 73*7c478bd9Sstevel@tonic-gate * DWARF data for both the forward declaration and the definition. We need 74*7c478bd9Sstevel@tonic-gate * to resolve the forward declarations when possible, by redirecting 75*7c478bd9Sstevel@tonic-gate * forward-referencing tdescs to the actual struct/union definitions. This 76*7c478bd9Sstevel@tonic-gate * redirection is done completely within the first pass. We begin by 77*7c478bd9Sstevel@tonic-gate * recording all forward declarations in dw_fwdhash. When we define a 78*7c478bd9Sstevel@tonic-gate * structure, we check to see if there have been any corresponding forward 79*7c478bd9Sstevel@tonic-gate * declarations. If so, we redirect the tdescs which referenced the forward 80*7c478bd9Sstevel@tonic-gate * declarations to the structure or union definition. 81*7c478bd9Sstevel@tonic-gate * 82*7c478bd9Sstevel@tonic-gate * XXX see if a post traverser will allow the elimination of repeated pass 2 83*7c478bd9Sstevel@tonic-gate * traversals. 84*7c478bd9Sstevel@tonic-gate */ 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate #include <stdio.h> 87*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 88*7c478bd9Sstevel@tonic-gate #include <strings.h> 89*7c478bd9Sstevel@tonic-gate #include <errno.h> 90*7c478bd9Sstevel@tonic-gate #include <libelf.h> 91*7c478bd9Sstevel@tonic-gate #include <libdwarf.h> 92*7c478bd9Sstevel@tonic-gate #include <libgen.h> 93*7c478bd9Sstevel@tonic-gate #include <dwarf.h> 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate #include "ctf_headers.h" 96*7c478bd9Sstevel@tonic-gate #include "ctftools.h" 97*7c478bd9Sstevel@tonic-gate #include "memory.h" 98*7c478bd9Sstevel@tonic-gate #include "list.h" 99*7c478bd9Sstevel@tonic-gate #include "traverse.h" 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate /* The version of DWARF which we support. */ 102*7c478bd9Sstevel@tonic-gate #define DWARF_VERSION 2 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate /* 105*7c478bd9Sstevel@tonic-gate * We need to define a couple of our own intrinsics, to smooth out some of the 106*7c478bd9Sstevel@tonic-gate * differences between the GCC and DevPro DWARF emitters. See the referenced 107*7c478bd9Sstevel@tonic-gate * routines and the special cases in the file comment for more details. 108*7c478bd9Sstevel@tonic-gate * 109*7c478bd9Sstevel@tonic-gate * Type IDs are 32 bits wide. We're going to use the top of that field to 110*7c478bd9Sstevel@tonic-gate * indicate types that we've created ourselves. 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate #define TID_FILEMAX 0x3fffffff /* highest tid from file */ 113*7c478bd9Sstevel@tonic-gate #define TID_VOID 0x40000001 /* see die_void() */ 114*7c478bd9Sstevel@tonic-gate #define TID_LONG 0x40000002 /* see die_array() */ 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate #define TID_MFGTID_BASE 0x40000003 /* first mfg'd tid */ 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate /* 119*7c478bd9Sstevel@tonic-gate * To reduce the staggering amount of error-handling code that would otherwise 120*7c478bd9Sstevel@tonic-gate * be required, the attribute-retrieval routines handle most of their own 121*7c478bd9Sstevel@tonic-gate * errors. If the following flag is supplied as the value of the `req' 122*7c478bd9Sstevel@tonic-gate * argument, they will also handle the absence of a requested attribute by 123*7c478bd9Sstevel@tonic-gate * terminating the program. 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate #define DW_ATTR_REQ 1 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate #define TDESC_HASH_BUCKETS 511 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate typedef struct dwarf { 130*7c478bd9Sstevel@tonic-gate Dwarf_Debug dw_dw; /* for libdwarf */ 131*7c478bd9Sstevel@tonic-gate Dwarf_Error dw_err; /* for libdwarf */ 132*7c478bd9Sstevel@tonic-gate Dwarf_Unsigned dw_maxoff; /* highest legal offset in this cu */ 133*7c478bd9Sstevel@tonic-gate tdata_t *dw_td; /* root of the tdesc/iidesc tree */ 134*7c478bd9Sstevel@tonic-gate hash_t *dw_tidhash; /* hash of tdescs by t_id */ 135*7c478bd9Sstevel@tonic-gate hash_t *dw_fwdhash; /* hash of fwd decls by name */ 136*7c478bd9Sstevel@tonic-gate hash_t *dw_enumhash; /* hash of memberless enums by name */ 137*7c478bd9Sstevel@tonic-gate tdesc_t *dw_void; /* manufactured void type */ 138*7c478bd9Sstevel@tonic-gate tdesc_t *dw_long; /* manufactured long type for arrays */ 139*7c478bd9Sstevel@tonic-gate size_t dw_ptrsz; /* size of a pointer in this file */ 140*7c478bd9Sstevel@tonic-gate tid_t dw_mfgtid_last; /* last mfg'd type ID used */ 141*7c478bd9Sstevel@tonic-gate uint_t dw_nunres; /* count of unresolved types */ 142*7c478bd9Sstevel@tonic-gate char *dw_cuname; /* name of compilation unit */ 143*7c478bd9Sstevel@tonic-gate } dwarf_t; 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate static void die_create_one(dwarf_t *, Dwarf_Die); 146*7c478bd9Sstevel@tonic-gate static void die_create(dwarf_t *, Dwarf_Die); 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate static tid_t 149*7c478bd9Sstevel@tonic-gate mfgtid_next(dwarf_t *dw) 150*7c478bd9Sstevel@tonic-gate { 151*7c478bd9Sstevel@tonic-gate return (++dw->dw_mfgtid_last); 152*7c478bd9Sstevel@tonic-gate } 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate static void 155*7c478bd9Sstevel@tonic-gate tdesc_add(dwarf_t *dw, tdesc_t *tdp) 156*7c478bd9Sstevel@tonic-gate { 157*7c478bd9Sstevel@tonic-gate hash_add(dw->dw_tidhash, tdp); 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate static tdesc_t * 161*7c478bd9Sstevel@tonic-gate tdesc_lookup(dwarf_t *dw, int tid) 162*7c478bd9Sstevel@tonic-gate { 163*7c478bd9Sstevel@tonic-gate tdesc_t tmpl, *tdp; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate tmpl.t_id = tid; 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate if (hash_find(dw->dw_tidhash, &tmpl, (void **)&tdp)) 168*7c478bd9Sstevel@tonic-gate return (tdp); 169*7c478bd9Sstevel@tonic-gate else 170*7c478bd9Sstevel@tonic-gate return (NULL); 171*7c478bd9Sstevel@tonic-gate } 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate /* 174*7c478bd9Sstevel@tonic-gate * Resolve a tdesc down to a node which should have a size. Returns the size, 175*7c478bd9Sstevel@tonic-gate * zero if the size hasn't yet been determined. 176*7c478bd9Sstevel@tonic-gate */ 177*7c478bd9Sstevel@tonic-gate static size_t 178*7c478bd9Sstevel@tonic-gate tdesc_size(tdesc_t *tdp) 179*7c478bd9Sstevel@tonic-gate { 180*7c478bd9Sstevel@tonic-gate for (;;) { 181*7c478bd9Sstevel@tonic-gate switch (tdp->t_type) { 182*7c478bd9Sstevel@tonic-gate case INTRINSIC: 183*7c478bd9Sstevel@tonic-gate case POINTER: 184*7c478bd9Sstevel@tonic-gate case ARRAY: 185*7c478bd9Sstevel@tonic-gate case FUNCTION: 186*7c478bd9Sstevel@tonic-gate case STRUCT: 187*7c478bd9Sstevel@tonic-gate case UNION: 188*7c478bd9Sstevel@tonic-gate case ENUM: 189*7c478bd9Sstevel@tonic-gate return (tdp->t_size); 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate case FORWARD: 192*7c478bd9Sstevel@tonic-gate return (0); 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate case TYPEDEF: 195*7c478bd9Sstevel@tonic-gate case VOLATILE: 196*7c478bd9Sstevel@tonic-gate case CONST: 197*7c478bd9Sstevel@tonic-gate case RESTRICT: 198*7c478bd9Sstevel@tonic-gate tdp = tdp->t_tdesc; 199*7c478bd9Sstevel@tonic-gate continue; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate case 0: /* not yet defined */ 202*7c478bd9Sstevel@tonic-gate return (0); 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate default: 205*7c478bd9Sstevel@tonic-gate terminate("tdp %u: tdesc_size on unknown type %d\n", 206*7c478bd9Sstevel@tonic-gate tdp->t_id, tdp->t_type); 207*7c478bd9Sstevel@tonic-gate } 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate static size_t 212*7c478bd9Sstevel@tonic-gate tdesc_bitsize(tdesc_t *tdp) 213*7c478bd9Sstevel@tonic-gate { 214*7c478bd9Sstevel@tonic-gate for (;;) { 215*7c478bd9Sstevel@tonic-gate switch (tdp->t_type) { 216*7c478bd9Sstevel@tonic-gate case INTRINSIC: 217*7c478bd9Sstevel@tonic-gate return (tdp->t_intr->intr_nbits); 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate case ARRAY: 220*7c478bd9Sstevel@tonic-gate case FUNCTION: 221*7c478bd9Sstevel@tonic-gate case STRUCT: 222*7c478bd9Sstevel@tonic-gate case UNION: 223*7c478bd9Sstevel@tonic-gate case ENUM: 224*7c478bd9Sstevel@tonic-gate case POINTER: 225*7c478bd9Sstevel@tonic-gate return (tdp->t_size); 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate case FORWARD: 228*7c478bd9Sstevel@tonic-gate return (0); 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate case TYPEDEF: 231*7c478bd9Sstevel@tonic-gate case VOLATILE: 232*7c478bd9Sstevel@tonic-gate case RESTRICT: 233*7c478bd9Sstevel@tonic-gate case CONST: 234*7c478bd9Sstevel@tonic-gate tdp = tdp->t_tdesc; 235*7c478bd9Sstevel@tonic-gate continue; 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate case 0: /* not yet defined */ 238*7c478bd9Sstevel@tonic-gate return (0); 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate default: 241*7c478bd9Sstevel@tonic-gate terminate("tdp %u: tdesc_bitsize on unknown type %d\n", 242*7c478bd9Sstevel@tonic-gate tdp->t_id, tdp->t_type); 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate static tdesc_t * 248*7c478bd9Sstevel@tonic-gate tdesc_basetype(tdesc_t *tdp) 249*7c478bd9Sstevel@tonic-gate { 250*7c478bd9Sstevel@tonic-gate for (;;) { 251*7c478bd9Sstevel@tonic-gate switch (tdp->t_type) { 252*7c478bd9Sstevel@tonic-gate case TYPEDEF: 253*7c478bd9Sstevel@tonic-gate case VOLATILE: 254*7c478bd9Sstevel@tonic-gate case RESTRICT: 255*7c478bd9Sstevel@tonic-gate case CONST: 256*7c478bd9Sstevel@tonic-gate tdp = tdp->t_tdesc; 257*7c478bd9Sstevel@tonic-gate break; 258*7c478bd9Sstevel@tonic-gate case 0: /* not yet defined */ 259*7c478bd9Sstevel@tonic-gate return (NULL); 260*7c478bd9Sstevel@tonic-gate default: 261*7c478bd9Sstevel@tonic-gate return (tdp); 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate static Dwarf_Off 267*7c478bd9Sstevel@tonic-gate die_off(dwarf_t *dw, Dwarf_Die die) 268*7c478bd9Sstevel@tonic-gate { 269*7c478bd9Sstevel@tonic-gate Dwarf_Off off; 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate if (dwarf_dieoffset(die, &off, &dw->dw_err) == DW_DLV_OK) 272*7c478bd9Sstevel@tonic-gate return (off); 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate terminate("failed to get offset for die: %s\n", 275*7c478bd9Sstevel@tonic-gate dwarf_errmsg(dw->dw_err)); 276*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 277*7c478bd9Sstevel@tonic-gate return (0); 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate static Dwarf_Die 281*7c478bd9Sstevel@tonic-gate die_sibling(dwarf_t *dw, Dwarf_Die die) 282*7c478bd9Sstevel@tonic-gate { 283*7c478bd9Sstevel@tonic-gate Dwarf_Die sib; 284*7c478bd9Sstevel@tonic-gate int rc; 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate if ((rc = dwarf_siblingof(dw->dw_dw, die, &sib, &dw->dw_err)) == 287*7c478bd9Sstevel@tonic-gate DW_DLV_OK) 288*7c478bd9Sstevel@tonic-gate return (sib); 289*7c478bd9Sstevel@tonic-gate else if (rc == DW_DLV_NO_ENTRY) 290*7c478bd9Sstevel@tonic-gate return (NULL); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate terminate("die %llu: failed to find type sibling: %s\n", 293*7c478bd9Sstevel@tonic-gate die_off(dw, die), dwarf_errmsg(dw->dw_err)); 294*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 295*7c478bd9Sstevel@tonic-gate return (NULL); 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate static Dwarf_Die 299*7c478bd9Sstevel@tonic-gate die_child(dwarf_t *dw, Dwarf_Die die) 300*7c478bd9Sstevel@tonic-gate { 301*7c478bd9Sstevel@tonic-gate Dwarf_Die child; 302*7c478bd9Sstevel@tonic-gate int rc; 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate if ((rc = dwarf_child(die, &child, &dw->dw_err)) == DW_DLV_OK) 305*7c478bd9Sstevel@tonic-gate return (child); 306*7c478bd9Sstevel@tonic-gate else if (rc == DW_DLV_NO_ENTRY) 307*7c478bd9Sstevel@tonic-gate return (NULL); 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate terminate("die %llu: failed to find type child: %s\n", 310*7c478bd9Sstevel@tonic-gate die_off(dw, die), dwarf_errmsg(dw->dw_err)); 311*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 312*7c478bd9Sstevel@tonic-gate return (NULL); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate static Dwarf_Half 316*7c478bd9Sstevel@tonic-gate die_tag(dwarf_t *dw, Dwarf_Die die) 317*7c478bd9Sstevel@tonic-gate { 318*7c478bd9Sstevel@tonic-gate Dwarf_Half tag; 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate if (dwarf_tag(die, &tag, &dw->dw_err) == DW_DLV_OK) 321*7c478bd9Sstevel@tonic-gate return (tag); 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get tag for type: %s\n", 324*7c478bd9Sstevel@tonic-gate die_off(dw, die), dwarf_errmsg(dw->dw_err)); 325*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 326*7c478bd9Sstevel@tonic-gate return (0); 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate static Dwarf_Attribute 330*7c478bd9Sstevel@tonic-gate die_attr(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, int req) 331*7c478bd9Sstevel@tonic-gate { 332*7c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 333*7c478bd9Sstevel@tonic-gate int rc; 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate if ((rc = dwarf_attr(die, name, &attr, &dw->dw_err)) == DW_DLV_OK) { 336*7c478bd9Sstevel@tonic-gate return (attr); 337*7c478bd9Sstevel@tonic-gate } else if (rc == DW_DLV_NO_ENTRY) { 338*7c478bd9Sstevel@tonic-gate if (req) { 339*7c478bd9Sstevel@tonic-gate terminate("die %llu: no attr 0x%x\n", die_off(dw, die), 340*7c478bd9Sstevel@tonic-gate name); 341*7c478bd9Sstevel@tonic-gate } else { 342*7c478bd9Sstevel@tonic-gate return (NULL); 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get attribute for type: %s\n", 347*7c478bd9Sstevel@tonic-gate die_off(dw, die), dwarf_errmsg(dw->dw_err)); 348*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 349*7c478bd9Sstevel@tonic-gate return (NULL); 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate static Dwarf_Half 353*7c478bd9Sstevel@tonic-gate die_attr_form(dwarf_t *dw, Dwarf_Attribute attr) 354*7c478bd9Sstevel@tonic-gate { 355*7c478bd9Sstevel@tonic-gate Dwarf_Half form; 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate if (dwarf_whatform(attr, &form, &dw->dw_err) == DW_DLV_OK) 358*7c478bd9Sstevel@tonic-gate return (form); 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate terminate("failed to get attribute form for type: %s\n", 361*7c478bd9Sstevel@tonic-gate dwarf_errmsg(dw->dw_err)); 362*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 363*7c478bd9Sstevel@tonic-gate return (0); 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate static int 367*7c478bd9Sstevel@tonic-gate die_signed(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Signed *valp, 368*7c478bd9Sstevel@tonic-gate int req) 369*7c478bd9Sstevel@tonic-gate { 370*7c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 371*7c478bd9Sstevel@tonic-gate Dwarf_Signed val; 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 374*7c478bd9Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate if (dwarf_formsdata(attr, &val, &dw->dw_err) != DW_DLV_OK) { 377*7c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get signed (form 0x%x)\n", 378*7c478bd9Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate *valp = val; 384*7c478bd9Sstevel@tonic-gate return (1); 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate static int 388*7c478bd9Sstevel@tonic-gate die_unsigned(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Unsigned *valp, 389*7c478bd9Sstevel@tonic-gate int req) 390*7c478bd9Sstevel@tonic-gate { 391*7c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 392*7c478bd9Sstevel@tonic-gate Dwarf_Unsigned val; 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 395*7c478bd9Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate if (dwarf_formudata(attr, &val, &dw->dw_err) != DW_DLV_OK) { 398*7c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get unsigned (form 0x%x)\n", 399*7c478bd9Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate *valp = val; 405*7c478bd9Sstevel@tonic-gate return (1); 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate static int 409*7c478bd9Sstevel@tonic-gate die_bool(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Bool *valp, int req) 410*7c478bd9Sstevel@tonic-gate { 411*7c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 412*7c478bd9Sstevel@tonic-gate Dwarf_Bool val; 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 415*7c478bd9Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate if (dwarf_formflag(attr, &val, &dw->dw_err) != DW_DLV_OK) { 418*7c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get bool (form 0x%x)\n", 419*7c478bd9Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate *valp = val; 425*7c478bd9Sstevel@tonic-gate return (1); 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate static int 429*7c478bd9Sstevel@tonic-gate die_string(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, char **strp, int req) 430*7c478bd9Sstevel@tonic-gate { 431*7c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 432*7c478bd9Sstevel@tonic-gate char *str; 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 435*7c478bd9Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate if (dwarf_formstring(attr, &str, &dw->dw_err) != DW_DLV_OK) { 438*7c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get string (form 0x%x)\n", 439*7c478bd9Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 440*7c478bd9Sstevel@tonic-gate } 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate *strp = xstrdup(str); 443*7c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, str, DW_DLA_STRING); 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate return (1); 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate static Dwarf_Off 449*7c478bd9Sstevel@tonic-gate die_attr_ref(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name) 450*7c478bd9Sstevel@tonic-gate { 451*7c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 452*7c478bd9Sstevel@tonic-gate Dwarf_Off off; 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate attr = die_attr(dw, die, name, DW_ATTR_REQ); 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate if (dwarf_formref(attr, &off, &dw->dw_err) != DW_DLV_OK) { 457*7c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get ref (form 0x%x)\n", 458*7c478bd9Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate return (off); 464*7c478bd9Sstevel@tonic-gate } 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate static char * 467*7c478bd9Sstevel@tonic-gate die_name(dwarf_t *dw, Dwarf_Die die) 468*7c478bd9Sstevel@tonic-gate { 469*7c478bd9Sstevel@tonic-gate char *str = NULL; 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate (void) die_string(dw, die, DW_AT_name, &str, 0); 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate return (str); 474*7c478bd9Sstevel@tonic-gate } 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate static int 477*7c478bd9Sstevel@tonic-gate die_isdecl(dwarf_t *dw, Dwarf_Die die) 478*7c478bd9Sstevel@tonic-gate { 479*7c478bd9Sstevel@tonic-gate Dwarf_Bool val; 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate return (die_bool(dw, die, DW_AT_declaration, &val, 0) && val); 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate static int 485*7c478bd9Sstevel@tonic-gate die_isglobal(dwarf_t *dw, Dwarf_Die die) 486*7c478bd9Sstevel@tonic-gate { 487*7c478bd9Sstevel@tonic-gate Dwarf_Signed vis; 488*7c478bd9Sstevel@tonic-gate Dwarf_Bool ext; 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate /* 491*7c478bd9Sstevel@tonic-gate * Some compilers (gcc) use DW_AT_external to indicate function 492*7c478bd9Sstevel@tonic-gate * visibility. Others (Sun) use DW_AT_visibility. 493*7c478bd9Sstevel@tonic-gate */ 494*7c478bd9Sstevel@tonic-gate if (die_signed(dw, die, DW_AT_visibility, &vis, 0)) 495*7c478bd9Sstevel@tonic-gate return (vis == DW_VIS_exported); 496*7c478bd9Sstevel@tonic-gate else 497*7c478bd9Sstevel@tonic-gate return (die_bool(dw, die, DW_AT_external, &ext, 0) && ext); 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate static tdesc_t * 501*7c478bd9Sstevel@tonic-gate die_add(dwarf_t *dw, Dwarf_Off off) 502*7c478bd9Sstevel@tonic-gate { 503*7c478bd9Sstevel@tonic-gate tdesc_t *tdp = xcalloc(sizeof (tdesc_t)); 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate tdp->t_id = off; 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate tdesc_add(dw, tdp); 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate return (tdp); 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate static tdesc_t * 513*7c478bd9Sstevel@tonic-gate die_lookup_pass1(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name) 514*7c478bd9Sstevel@tonic-gate { 515*7c478bd9Sstevel@tonic-gate Dwarf_Off ref = die_attr_ref(dw, die, name); 516*7c478bd9Sstevel@tonic-gate tdesc_t *tdp; 517*7c478bd9Sstevel@tonic-gate 518*7c478bd9Sstevel@tonic-gate if ((tdp = tdesc_lookup(dw, ref)) != NULL) 519*7c478bd9Sstevel@tonic-gate return (tdp); 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate return (die_add(dw, ref)); 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate static int 525*7c478bd9Sstevel@tonic-gate die_mem_offset(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, 526*7c478bd9Sstevel@tonic-gate Dwarf_Unsigned *valp, int req) 527*7c478bd9Sstevel@tonic-gate { 528*7c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 529*7c478bd9Sstevel@tonic-gate Dwarf_Locdesc *loc; 530*7c478bd9Sstevel@tonic-gate Dwarf_Signed locnum; 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 533*7c478bd9Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate if (dwarf_loclist(attr, &loc, &locnum, &dw->dw_err) != DW_DLV_OK) { 536*7c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get mem offset location list\n", 537*7c478bd9Sstevel@tonic-gate die_off(dw, die)); 538*7c478bd9Sstevel@tonic-gate } 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) { 543*7c478bd9Sstevel@tonic-gate terminate("die %llu: cannot parse member offset\n", 544*7c478bd9Sstevel@tonic-gate die_off(dw, die)); 545*7c478bd9Sstevel@tonic-gate } 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate *valp = loc->ld_s->lr_number; 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, loc->ld_s, DW_DLA_LOC_BLOCK); 550*7c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, loc, DW_DLA_LOCDESC); 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate return (1); 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate static tdesc_t * 556*7c478bd9Sstevel@tonic-gate tdesc_intr_common(dwarf_t *dw, int tid, const char *name, size_t sz) 557*7c478bd9Sstevel@tonic-gate { 558*7c478bd9Sstevel@tonic-gate tdesc_t *tdp; 559*7c478bd9Sstevel@tonic-gate intr_t *intr; 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate intr = xcalloc(sizeof (intr_t)); 562*7c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 563*7c478bd9Sstevel@tonic-gate intr->intr_signed = 1; 564*7c478bd9Sstevel@tonic-gate intr->intr_nbits = sz * NBBY; 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate tdp = xcalloc(sizeof (tdesc_t)); 567*7c478bd9Sstevel@tonic-gate tdp->t_name = xstrdup(name); 568*7c478bd9Sstevel@tonic-gate tdp->t_size = sz; 569*7c478bd9Sstevel@tonic-gate tdp->t_id = tid; 570*7c478bd9Sstevel@tonic-gate tdp->t_type = INTRINSIC; 571*7c478bd9Sstevel@tonic-gate tdp->t_intr = intr; 572*7c478bd9Sstevel@tonic-gate tdp->t_flags = TDESC_F_RESOLVED; 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate tdesc_add(dw, tdp); 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate return (tdp); 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate /* 580*7c478bd9Sstevel@tonic-gate * Manufacture a void type. Used for gcc-emitted stabs, where the lack of a 581*7c478bd9Sstevel@tonic-gate * type reference implies a reference to a void type. A void *, for example 582*7c478bd9Sstevel@tonic-gate * will be represented by a pointer die without a DW_AT_type. CTF requires 583*7c478bd9Sstevel@tonic-gate * that pointer nodes point to something, so we'll create a void for use as 584*7c478bd9Sstevel@tonic-gate * the target. Note that the DWARF data may already create a void type. Ours 585*7c478bd9Sstevel@tonic-gate * would then be a duplicate, but it'll be removed in the self-uniquification 586*7c478bd9Sstevel@tonic-gate * merge performed at the completion of DWARF->tdesc conversion. 587*7c478bd9Sstevel@tonic-gate */ 588*7c478bd9Sstevel@tonic-gate static tdesc_t * 589*7c478bd9Sstevel@tonic-gate tdesc_intr_void(dwarf_t *dw) 590*7c478bd9Sstevel@tonic-gate { 591*7c478bd9Sstevel@tonic-gate if (dw->dw_void == NULL) 592*7c478bd9Sstevel@tonic-gate dw->dw_void = tdesc_intr_common(dw, TID_VOID, "void", 0); 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate return (dw->dw_void); 595*7c478bd9Sstevel@tonic-gate } 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate static tdesc_t * 598*7c478bd9Sstevel@tonic-gate tdesc_intr_long(dwarf_t *dw) 599*7c478bd9Sstevel@tonic-gate { 600*7c478bd9Sstevel@tonic-gate if (dw->dw_long == NULL) { 601*7c478bd9Sstevel@tonic-gate dw->dw_long = tdesc_intr_common(dw, TID_LONG, "long", 602*7c478bd9Sstevel@tonic-gate dw->dw_ptrsz); 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate return (dw->dw_long); 606*7c478bd9Sstevel@tonic-gate } 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate /* 609*7c478bd9Sstevel@tonic-gate * Used for creating bitfield types. We create a copy of an existing intrinsic, 610*7c478bd9Sstevel@tonic-gate * adjusting the size of the copy to match what the caller requested. The 611*7c478bd9Sstevel@tonic-gate * caller can then use the copy as the type for a bitfield structure member. 612*7c478bd9Sstevel@tonic-gate */ 613*7c478bd9Sstevel@tonic-gate static tdesc_t * 614*7c478bd9Sstevel@tonic-gate tdesc_intr_clone(dwarf_t *dw, tdesc_t *old, size_t bitsz) 615*7c478bd9Sstevel@tonic-gate { 616*7c478bd9Sstevel@tonic-gate tdesc_t *new = xcalloc(sizeof (tdesc_t)); 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate if (!(old->t_flags & TDESC_F_RESOLVED)) { 619*7c478bd9Sstevel@tonic-gate terminate("tdp %u: attempt to make a bit field from an " 620*7c478bd9Sstevel@tonic-gate "unresolved type\n", old->t_id); 621*7c478bd9Sstevel@tonic-gate } 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate new->t_name = xstrdup(old->t_name); 624*7c478bd9Sstevel@tonic-gate new->t_size = old->t_size; 625*7c478bd9Sstevel@tonic-gate new->t_id = mfgtid_next(dw); 626*7c478bd9Sstevel@tonic-gate new->t_type = INTRINSIC; 627*7c478bd9Sstevel@tonic-gate new->t_flags = TDESC_F_RESOLVED; 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate new->t_intr = xcalloc(sizeof (intr_t)); 630*7c478bd9Sstevel@tonic-gate bcopy(old->t_intr, new->t_intr, sizeof (intr_t)); 631*7c478bd9Sstevel@tonic-gate new->t_intr->intr_nbits = bitsz; 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate tdesc_add(dw, new); 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate return (new); 636*7c478bd9Sstevel@tonic-gate } 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate static void 639*7c478bd9Sstevel@tonic-gate tdesc_array_create(dwarf_t *dw, Dwarf_Die dim, tdesc_t *arrtdp, 640*7c478bd9Sstevel@tonic-gate tdesc_t *dimtdp) 641*7c478bd9Sstevel@tonic-gate { 642*7c478bd9Sstevel@tonic-gate Dwarf_Unsigned uval; 643*7c478bd9Sstevel@tonic-gate Dwarf_Signed sval; 644*7c478bd9Sstevel@tonic-gate tdesc_t *ctdp; 645*7c478bd9Sstevel@tonic-gate Dwarf_Die dim2; 646*7c478bd9Sstevel@tonic-gate ardef_t *ar; 647*7c478bd9Sstevel@tonic-gate 648*7c478bd9Sstevel@tonic-gate if ((dim2 = die_sibling(dw, dim)) == NULL) { 649*7c478bd9Sstevel@tonic-gate ctdp = arrtdp; 650*7c478bd9Sstevel@tonic-gate } else if (die_tag(dw, dim2) == DW_TAG_subrange_type) { 651*7c478bd9Sstevel@tonic-gate ctdp = xcalloc(sizeof (tdesc_t)); 652*7c478bd9Sstevel@tonic-gate ctdp->t_id = mfgtid_next(dw); 653*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating new type %u for sub-dimension\n", 654*7c478bd9Sstevel@tonic-gate die_off(dw, dim2), ctdp->t_id); 655*7c478bd9Sstevel@tonic-gate tdesc_array_create(dw, dim2, arrtdp, ctdp); 656*7c478bd9Sstevel@tonic-gate } else { 657*7c478bd9Sstevel@tonic-gate terminate("die %llu: unexpected non-subrange node in array\n", 658*7c478bd9Sstevel@tonic-gate die_off(dw, dim2)); 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate dimtdp->t_type = ARRAY; 662*7c478bd9Sstevel@tonic-gate dimtdp->t_ardef = ar = xcalloc(sizeof (ardef_t)); 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate /* 665*7c478bd9Sstevel@tonic-gate * Array bounds can be signed or unsigned, but there are several kinds 666*7c478bd9Sstevel@tonic-gate * of signless forms (data1, data2, etc) that take their sign from the 667*7c478bd9Sstevel@tonic-gate * routine that is trying to interpret them. That is, data1 can be 668*7c478bd9Sstevel@tonic-gate * either signed or unsigned, depending on whether you use the signed or 669*7c478bd9Sstevel@tonic-gate * unsigned accessor function. GCC will use the signless forms to store 670*7c478bd9Sstevel@tonic-gate * unsigned values which have their high bit set, so we need to try to 671*7c478bd9Sstevel@tonic-gate * read them first as unsigned to get positive values. We could also 672*7c478bd9Sstevel@tonic-gate * try signed first, falling back to unsigned if we got a negative 673*7c478bd9Sstevel@tonic-gate * value. 674*7c478bd9Sstevel@tonic-gate */ 675*7c478bd9Sstevel@tonic-gate if (die_unsigned(dw, dim, DW_AT_upper_bound, &uval, 0)) 676*7c478bd9Sstevel@tonic-gate ar->ad_nelems = uval + 1; 677*7c478bd9Sstevel@tonic-gate else if (die_signed(dw, dim, DW_AT_upper_bound, &sval, 0)) 678*7c478bd9Sstevel@tonic-gate ar->ad_nelems = sval + 1; 679*7c478bd9Sstevel@tonic-gate else 680*7c478bd9Sstevel@tonic-gate ar->ad_nelems = 0; 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate /* 683*7c478bd9Sstevel@tonic-gate * Different compilers use different index types. Force the type to be 684*7c478bd9Sstevel@tonic-gate * a common, known value (long). 685*7c478bd9Sstevel@tonic-gate */ 686*7c478bd9Sstevel@tonic-gate ar->ad_idxtype = tdesc_intr_long(dw); 687*7c478bd9Sstevel@tonic-gate ar->ad_contents = ctdp; 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate if (ar->ad_contents->t_size != 0) { 690*7c478bd9Sstevel@tonic-gate dimtdp->t_size = ar->ad_contents->t_size * ar->ad_nelems; 691*7c478bd9Sstevel@tonic-gate dimtdp->t_flags |= TDESC_F_RESOLVED; 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate 695*7c478bd9Sstevel@tonic-gate /* 696*7c478bd9Sstevel@tonic-gate * Create a tdesc from an array node. Some arrays will come with byte size 697*7c478bd9Sstevel@tonic-gate * attributes, and thus can be resolved immediately. Others don't, and will 698*7c478bd9Sstevel@tonic-gate * need to wait until the second pass for resolution. 699*7c478bd9Sstevel@tonic-gate */ 700*7c478bd9Sstevel@tonic-gate static void 701*7c478bd9Sstevel@tonic-gate die_array_create(dwarf_t *dw, Dwarf_Die arr, Dwarf_Off off, tdesc_t *tdp) 702*7c478bd9Sstevel@tonic-gate { 703*7c478bd9Sstevel@tonic-gate tdesc_t *arrtdp = die_lookup_pass1(dw, arr, DW_AT_type); 704*7c478bd9Sstevel@tonic-gate Dwarf_Unsigned uval; 705*7c478bd9Sstevel@tonic-gate Dwarf_Die dim; 706*7c478bd9Sstevel@tonic-gate 707*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating array\n", off); 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate if ((dim = die_child(dw, arr)) == NULL || 710*7c478bd9Sstevel@tonic-gate die_tag(dw, dim) != DW_TAG_subrange_type) 711*7c478bd9Sstevel@tonic-gate terminate("die %llu: failed to retrieve array bounds\n", off); 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate tdesc_array_create(dw, dim, arrtdp, tdp); 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate if (die_unsigned(dw, arr, DW_AT_byte_size, &uval, 0)) { 716*7c478bd9Sstevel@tonic-gate tdesc_t *dimtdp; 717*7c478bd9Sstevel@tonic-gate int flags; 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate tdp->t_size = uval; 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate /* 722*7c478bd9Sstevel@tonic-gate * Ensure that sub-dimensions have sizes too before marking 723*7c478bd9Sstevel@tonic-gate * as resolved. 724*7c478bd9Sstevel@tonic-gate */ 725*7c478bd9Sstevel@tonic-gate flags = TDESC_F_RESOLVED; 726*7c478bd9Sstevel@tonic-gate for (dimtdp = tdp->t_ardef->ad_contents; 727*7c478bd9Sstevel@tonic-gate dimtdp->t_type == ARRAY; 728*7c478bd9Sstevel@tonic-gate dimtdp = dimtdp->t_ardef->ad_contents) { 729*7c478bd9Sstevel@tonic-gate if (!(dimtdp->t_flags & TDESC_F_RESOLVED)) { 730*7c478bd9Sstevel@tonic-gate flags = 0; 731*7c478bd9Sstevel@tonic-gate break; 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate tdp->t_flags |= flags; 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: array nelems %u size %u\n", off, 739*7c478bd9Sstevel@tonic-gate tdp->t_ardef->ad_nelems, tdp->t_size); 740*7c478bd9Sstevel@tonic-gate } 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 743*7c478bd9Sstevel@tonic-gate static int 744*7c478bd9Sstevel@tonic-gate die_array_resolve(tdesc_t *tdp, tdesc_t **tdpp, void *private) 745*7c478bd9Sstevel@tonic-gate { 746*7c478bd9Sstevel@tonic-gate dwarf_t *dw = private; 747*7c478bd9Sstevel@tonic-gate size_t sz; 748*7c478bd9Sstevel@tonic-gate 749*7c478bd9Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 750*7c478bd9Sstevel@tonic-gate return (1); 751*7c478bd9Sstevel@tonic-gate 752*7c478bd9Sstevel@tonic-gate debug(3, "trying to resolve array %d (cont %d)\n", tdp->t_id, 753*7c478bd9Sstevel@tonic-gate tdp->t_ardef->ad_contents->t_id); 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate if ((sz = tdesc_size(tdp->t_ardef->ad_contents)) == 0) { 756*7c478bd9Sstevel@tonic-gate debug(3, "unable to resolve array %s (%d) contents %d\n", 757*7c478bd9Sstevel@tonic-gate (tdp->t_name == NULL ? "(anon)" : tdp->t_name), tdp->t_id, 758*7c478bd9Sstevel@tonic-gate tdp->t_ardef->ad_contents->t_id); 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate dw->dw_nunres++; 761*7c478bd9Sstevel@tonic-gate return (1); 762*7c478bd9Sstevel@tonic-gate } 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate tdp->t_size = sz * tdp->t_ardef->ad_nelems; 765*7c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate debug(3, "resolved array %d: %u bytes\n", tdp->t_id, tdp->t_size); 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate return (1); 770*7c478bd9Sstevel@tonic-gate } 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 773*7c478bd9Sstevel@tonic-gate static int 774*7c478bd9Sstevel@tonic-gate die_array_failed(tdesc_t *tdp, tdesc_t **tdpp, void *private) 775*7c478bd9Sstevel@tonic-gate { 776*7c478bd9Sstevel@tonic-gate tdesc_t *cont = tdp->t_ardef->ad_contents; 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 779*7c478bd9Sstevel@tonic-gate return (1); 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Array %d: failed to size contents type %s (%d)\n", 782*7c478bd9Sstevel@tonic-gate tdp->t_id, (cont->t_name == NULL ? "(anon)" : cont->t_name), 783*7c478bd9Sstevel@tonic-gate cont->t_id); 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate return (1); 786*7c478bd9Sstevel@tonic-gate } 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate /* 789*7c478bd9Sstevel@tonic-gate * Most enums (those with members) will be resolved during this first pass. 790*7c478bd9Sstevel@tonic-gate * Others - those without members (see the file comment) - won't be, and will 791*7c478bd9Sstevel@tonic-gate * need to wait until the second pass when they can be matched with their full 792*7c478bd9Sstevel@tonic-gate * definitions. 793*7c478bd9Sstevel@tonic-gate */ 794*7c478bd9Sstevel@tonic-gate static void 795*7c478bd9Sstevel@tonic-gate die_enum_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 796*7c478bd9Sstevel@tonic-gate { 797*7c478bd9Sstevel@tonic-gate Dwarf_Die mem; 798*7c478bd9Sstevel@tonic-gate Dwarf_Unsigned uval; 799*7c478bd9Sstevel@tonic-gate Dwarf_Signed sval; 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating enum\n", off); 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate tdp->t_type = ENUM; 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate (void) die_unsigned(dw, die, DW_AT_byte_size, &uval, DW_ATTR_REQ); 806*7c478bd9Sstevel@tonic-gate tdp->t_size = uval; 807*7c478bd9Sstevel@tonic-gate 808*7c478bd9Sstevel@tonic-gate if ((mem = die_child(dw, die)) != NULL) { 809*7c478bd9Sstevel@tonic-gate elist_t **elastp = &tdp->t_emem; 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate do { 812*7c478bd9Sstevel@tonic-gate elist_t *el; 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate if (die_tag(dw, mem) != DW_TAG_enumerator) { 815*7c478bd9Sstevel@tonic-gate /* Nested type declaration */ 816*7c478bd9Sstevel@tonic-gate die_create_one(dw, mem); 817*7c478bd9Sstevel@tonic-gate continue; 818*7c478bd9Sstevel@tonic-gate } 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate el = xcalloc(sizeof (elist_t)); 821*7c478bd9Sstevel@tonic-gate el->el_name = die_name(dw, mem); 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate if (die_signed(dw, mem, DW_AT_const_value, &sval, 0)) { 824*7c478bd9Sstevel@tonic-gate el->el_number = sval; 825*7c478bd9Sstevel@tonic-gate } else if (die_unsigned(dw, mem, DW_AT_const_value, 826*7c478bd9Sstevel@tonic-gate &uval, 0)) { 827*7c478bd9Sstevel@tonic-gate el->el_number = uval; 828*7c478bd9Sstevel@tonic-gate } else { 829*7c478bd9Sstevel@tonic-gate terminate("die %llu: enum %llu: member without " 830*7c478bd9Sstevel@tonic-gate "value\n", off, die_off(dw, mem)); 831*7c478bd9Sstevel@tonic-gate } 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: enum %llu: created %s = %d\n", off, 834*7c478bd9Sstevel@tonic-gate die_off(dw, mem), el->el_name, el->el_number); 835*7c478bd9Sstevel@tonic-gate 836*7c478bd9Sstevel@tonic-gate *elastp = el; 837*7c478bd9Sstevel@tonic-gate elastp = &el->el_next; 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate } while ((mem = die_sibling(dw, mem)) != NULL); 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate hash_add(dw->dw_enumhash, tdp); 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate if (tdp->t_name != NULL) { 846*7c478bd9Sstevel@tonic-gate iidesc_t *ii = xcalloc(sizeof (iidesc_t)); 847*7c478bd9Sstevel@tonic-gate ii->ii_type = II_SOU; 848*7c478bd9Sstevel@tonic-gate ii->ii_name = xstrdup(tdp->t_name); 849*7c478bd9Sstevel@tonic-gate ii->ii_dtype = tdp; 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 852*7c478bd9Sstevel@tonic-gate } 853*7c478bd9Sstevel@tonic-gate } 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate static int 857*7c478bd9Sstevel@tonic-gate die_enum_match(void *arg1, void *arg2) 858*7c478bd9Sstevel@tonic-gate { 859*7c478bd9Sstevel@tonic-gate tdesc_t *tdp = arg1, **fullp = arg2; 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate if (tdp->t_emem != NULL) { 862*7c478bd9Sstevel@tonic-gate *fullp = tdp; 863*7c478bd9Sstevel@tonic-gate return (-1); /* stop the iteration */ 864*7c478bd9Sstevel@tonic-gate } 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate return (0); 867*7c478bd9Sstevel@tonic-gate } 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 870*7c478bd9Sstevel@tonic-gate static int 871*7c478bd9Sstevel@tonic-gate die_enum_resolve(tdesc_t *tdp, tdesc_t **tdpp, void *private) 872*7c478bd9Sstevel@tonic-gate { 873*7c478bd9Sstevel@tonic-gate dwarf_t *dw = private; 874*7c478bd9Sstevel@tonic-gate tdesc_t *full = NULL; 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 877*7c478bd9Sstevel@tonic-gate return (1); 878*7c478bd9Sstevel@tonic-gate 879*7c478bd9Sstevel@tonic-gate (void) hash_find_iter(dw->dw_enumhash, tdp, die_enum_match, &full); 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate /* 882*7c478bd9Sstevel@tonic-gate * The answer to this one won't change from iteration to iteration, 883*7c478bd9Sstevel@tonic-gate * so don't even try. 884*7c478bd9Sstevel@tonic-gate */ 885*7c478bd9Sstevel@tonic-gate if (full == NULL) { 886*7c478bd9Sstevel@tonic-gate terminate("tdp %u: enum %s has no members\n", 887*7c478bd9Sstevel@tonic-gate tdp->t_id, (tdp->t_name == NULL ? "(anon)" : tdp->t_name)); 888*7c478bd9Sstevel@tonic-gate } 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate debug(3, "tdp %u: enum %s redirected to %u\n", tdp->t_id, 891*7c478bd9Sstevel@tonic-gate (tdp->t_name == NULL ? "(anon)" : tdp->t_name), full->t_id); 892*7c478bd9Sstevel@tonic-gate 893*7c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate return (1); 896*7c478bd9Sstevel@tonic-gate } 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate static int 899*7c478bd9Sstevel@tonic-gate die_fwd_map(void *arg1, void *arg2) 900*7c478bd9Sstevel@tonic-gate { 901*7c478bd9Sstevel@tonic-gate tdesc_t *fwd = arg1, *sou = arg2; 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate debug(3, "tdp %u: mapped forward %s to sou %u\n", fwd->t_id, 904*7c478bd9Sstevel@tonic-gate fwd->t_name, sou->t_id); 905*7c478bd9Sstevel@tonic-gate fwd->t_tdesc = sou; 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate return (0); 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate 910*7c478bd9Sstevel@tonic-gate /* 911*7c478bd9Sstevel@tonic-gate * Structures and unions will never be resolved during the first pass, as we 912*7c478bd9Sstevel@tonic-gate * won't be able to fully determine the member sizes. The second pass, which 913*7c478bd9Sstevel@tonic-gate * have access to sizing information, will be able to complete the resolution. 914*7c478bd9Sstevel@tonic-gate */ 915*7c478bd9Sstevel@tonic-gate static void 916*7c478bd9Sstevel@tonic-gate die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp, 917*7c478bd9Sstevel@tonic-gate int type, const char *typename) 918*7c478bd9Sstevel@tonic-gate { 919*7c478bd9Sstevel@tonic-gate Dwarf_Unsigned sz, bitsz, bitoff; 920*7c478bd9Sstevel@tonic-gate Dwarf_Die mem; 921*7c478bd9Sstevel@tonic-gate mlist_t *ml, **mlastp; 922*7c478bd9Sstevel@tonic-gate iidesc_t *ii; 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate tdp->t_type = (die_isdecl(dw, str) ? FORWARD : type); 925*7c478bd9Sstevel@tonic-gate 926*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating %s %s\n", off, 927*7c478bd9Sstevel@tonic-gate (tdp->t_type == FORWARD ? "forward decl" : typename), 928*7c478bd9Sstevel@tonic-gate (tdp->t_name == NULL ? "(anon)" : tdp->t_name)); 929*7c478bd9Sstevel@tonic-gate 930*7c478bd9Sstevel@tonic-gate if (tdp->t_type == FORWARD) { 931*7c478bd9Sstevel@tonic-gate hash_add(dw->dw_fwdhash, tdp); 932*7c478bd9Sstevel@tonic-gate return; 933*7c478bd9Sstevel@tonic-gate } 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate (void) hash_find_iter(dw->dw_fwdhash, tdp, die_fwd_map, tdp); 936*7c478bd9Sstevel@tonic-gate 937*7c478bd9Sstevel@tonic-gate (void) die_unsigned(dw, str, DW_AT_byte_size, &sz, DW_ATTR_REQ); 938*7c478bd9Sstevel@tonic-gate tdp->t_size = sz; 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate if ((mem = die_child(dw, str)) == NULL) 941*7c478bd9Sstevel@tonic-gate terminate("die %llu: %s has no members", off, typename); 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate mlastp = &tdp->t_members; 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate do { 946*7c478bd9Sstevel@tonic-gate Dwarf_Off memoff = die_off(dw, mem); 947*7c478bd9Sstevel@tonic-gate Dwarf_Half tag = die_tag(dw, mem); 948*7c478bd9Sstevel@tonic-gate Dwarf_Unsigned mloff; 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate if (tag != DW_TAG_member) { 951*7c478bd9Sstevel@tonic-gate /* Nested type declaration */ 952*7c478bd9Sstevel@tonic-gate die_create_one(dw, mem); 953*7c478bd9Sstevel@tonic-gate continue; 954*7c478bd9Sstevel@tonic-gate } 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: mem %llu: creating member\n", off, memoff); 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate ml = xcalloc(sizeof (mlist_t)); 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate if ((ml->ml_name = die_name(dw, mem)) == NULL) { 961*7c478bd9Sstevel@tonic-gate terminate("die %llu: mem %llu: member has no name\n", 962*7c478bd9Sstevel@tonic-gate off, memoff); 963*7c478bd9Sstevel@tonic-gate } 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate ml->ml_type = die_lookup_pass1(dw, mem, DW_AT_type); 966*7c478bd9Sstevel@tonic-gate 967*7c478bd9Sstevel@tonic-gate if (die_mem_offset(dw, mem, DW_AT_data_member_location, 968*7c478bd9Sstevel@tonic-gate &mloff, 0)) { 969*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: got mloff %llx\n", off, 970*7c478bd9Sstevel@tonic-gate (u_longlong_t)mloff); 971*7c478bd9Sstevel@tonic-gate ml->ml_offset = mloff * 8; 972*7c478bd9Sstevel@tonic-gate } 973*7c478bd9Sstevel@tonic-gate 974*7c478bd9Sstevel@tonic-gate if (die_unsigned(dw, mem, DW_AT_bit_size, &bitsz, 0)) 975*7c478bd9Sstevel@tonic-gate ml->ml_size = bitsz; 976*7c478bd9Sstevel@tonic-gate else 977*7c478bd9Sstevel@tonic-gate ml->ml_size = tdesc_bitsize(ml->ml_type); 978*7c478bd9Sstevel@tonic-gate 979*7c478bd9Sstevel@tonic-gate if (die_unsigned(dw, mem, DW_AT_bit_offset, &bitoff, 0)) { 980*7c478bd9Sstevel@tonic-gate #ifdef _BIG_ENDIAN 981*7c478bd9Sstevel@tonic-gate ml->ml_offset += bitoff; 982*7c478bd9Sstevel@tonic-gate #else 983*7c478bd9Sstevel@tonic-gate ml->ml_offset += (dw->dw_ptrsz * NBBY - bitoff - 984*7c478bd9Sstevel@tonic-gate ml->ml_size); 985*7c478bd9Sstevel@tonic-gate #endif 986*7c478bd9Sstevel@tonic-gate } 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: mem %llu: created %s (off %u sz %u)\n", 989*7c478bd9Sstevel@tonic-gate off, memoff, ml->ml_name, ml->ml_offset, ml->ml_size); 990*7c478bd9Sstevel@tonic-gate 991*7c478bd9Sstevel@tonic-gate *mlastp = ml; 992*7c478bd9Sstevel@tonic-gate mlastp = &ml->ml_next; 993*7c478bd9Sstevel@tonic-gate } while ((mem = die_sibling(dw, mem)) != NULL); 994*7c478bd9Sstevel@tonic-gate 995*7c478bd9Sstevel@tonic-gate /* 996*7c478bd9Sstevel@tonic-gate * GCC will attempt to eliminate unused types, thus decreasing the 997*7c478bd9Sstevel@tonic-gate * size of the emitted dwarf. That is, if you declare a foo_t in your 998*7c478bd9Sstevel@tonic-gate * header, include said header in your source file, and neglect to 999*7c478bd9Sstevel@tonic-gate * actually use (directly or indirectly) the foo_t in the source file, 1000*7c478bd9Sstevel@tonic-gate * the foo_t won't make it into the emitted DWARF. So, at least, goes 1001*7c478bd9Sstevel@tonic-gate * the theory. 1002*7c478bd9Sstevel@tonic-gate * 1003*7c478bd9Sstevel@tonic-gate * Occasionally, it'll emit the DW_TAG_structure_type for the foo_t, 1004*7c478bd9Sstevel@tonic-gate * and then neglect to emit the members. Strangely, the loner struct 1005*7c478bd9Sstevel@tonic-gate * tag will always be followed by a proper nested declaration of 1006*7c478bd9Sstevel@tonic-gate * something else. This is clearly a bug, but we're not going to have 1007*7c478bd9Sstevel@tonic-gate * time to get it fixed before this goo goes back, so we'll have to work 1008*7c478bd9Sstevel@tonic-gate * around it. If we see a no-membered struct with a nested declaration 1009*7c478bd9Sstevel@tonic-gate * (i.e. die_child of the struct tag won't be null), we'll ignore it. 1010*7c478bd9Sstevel@tonic-gate * Being paranoid, we won't simply remove it from the hash. Instead, 1011*7c478bd9Sstevel@tonic-gate * we'll decline to create an iidesc for it, thus ensuring that this 1012*7c478bd9Sstevel@tonic-gate * type won't make it into the output file. To be safe, we'll also 1013*7c478bd9Sstevel@tonic-gate * change the name. 1014*7c478bd9Sstevel@tonic-gate */ 1015*7c478bd9Sstevel@tonic-gate if (tdp->t_members == NULL) { 1016*7c478bd9Sstevel@tonic-gate char *old = (tdp->t_name == NULL ? "" : tdp->t_name); 1017*7c478bd9Sstevel@tonic-gate size_t newsz = 7 + strlen(old) + 1; 1018*7c478bd9Sstevel@tonic-gate char *new = xmalloc(newsz); 1019*7c478bd9Sstevel@tonic-gate (void) snprintf(new, newsz, "orphan %s", old); 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: worked around %s %s\n", off, typename, 1022*7c478bd9Sstevel@tonic-gate (tdp->t_name == NULL ? "<anon>" : tdp->t_name)); 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate if (tdp->t_name != NULL) 1025*7c478bd9Sstevel@tonic-gate free(tdp->t_name); 1026*7c478bd9Sstevel@tonic-gate tdp->t_name = new; 1027*7c478bd9Sstevel@tonic-gate 1028*7c478bd9Sstevel@tonic-gate } 1029*7c478bd9Sstevel@tonic-gate 1030*7c478bd9Sstevel@tonic-gate if (tdp->t_name != NULL && tdp->t_members != NULL) { 1031*7c478bd9Sstevel@tonic-gate ii = xcalloc(sizeof (iidesc_t)); 1032*7c478bd9Sstevel@tonic-gate ii->ii_type = II_SOU; 1033*7c478bd9Sstevel@tonic-gate ii->ii_name = xstrdup(tdp->t_name); 1034*7c478bd9Sstevel@tonic-gate ii->ii_dtype = tdp; 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 1037*7c478bd9Sstevel@tonic-gate } 1038*7c478bd9Sstevel@tonic-gate } 1039*7c478bd9Sstevel@tonic-gate 1040*7c478bd9Sstevel@tonic-gate static void 1041*7c478bd9Sstevel@tonic-gate die_struct_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 1042*7c478bd9Sstevel@tonic-gate { 1043*7c478bd9Sstevel@tonic-gate die_sou_create(dw, die, off, tdp, STRUCT, "struct"); 1044*7c478bd9Sstevel@tonic-gate } 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate static void 1047*7c478bd9Sstevel@tonic-gate die_union_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 1048*7c478bd9Sstevel@tonic-gate { 1049*7c478bd9Sstevel@tonic-gate die_sou_create(dw, die, off, tdp, UNION, "union"); 1050*7c478bd9Sstevel@tonic-gate } 1051*7c478bd9Sstevel@tonic-gate 1052*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 1053*7c478bd9Sstevel@tonic-gate static int 1054*7c478bd9Sstevel@tonic-gate die_sou_resolve(tdesc_t *tdp, tdesc_t **tdpp, void *private) 1055*7c478bd9Sstevel@tonic-gate { 1056*7c478bd9Sstevel@tonic-gate dwarf_t *dw = private; 1057*7c478bd9Sstevel@tonic-gate mlist_t *ml; 1058*7c478bd9Sstevel@tonic-gate tdesc_t *mt; 1059*7c478bd9Sstevel@tonic-gate 1060*7c478bd9Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 1061*7c478bd9Sstevel@tonic-gate return (1); 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate debug(3, "resolving sou %s\n", tdp->t_name); 1064*7c478bd9Sstevel@tonic-gate 1065*7c478bd9Sstevel@tonic-gate for (ml = tdp->t_members; ml != NULL; ml = ml->ml_next) { 1066*7c478bd9Sstevel@tonic-gate if (ml->ml_size == 0) { 1067*7c478bd9Sstevel@tonic-gate if ((ml->ml_size = tdesc_bitsize(ml->ml_type)) == 0) { 1068*7c478bd9Sstevel@tonic-gate dw->dw_nunres++; 1069*7c478bd9Sstevel@tonic-gate return (1); 1070*7c478bd9Sstevel@tonic-gate } 1071*7c478bd9Sstevel@tonic-gate } 1072*7c478bd9Sstevel@tonic-gate 1073*7c478bd9Sstevel@tonic-gate if ((mt = tdesc_basetype(ml->ml_type)) == NULL) { 1074*7c478bd9Sstevel@tonic-gate dw->dw_nunres++; 1075*7c478bd9Sstevel@tonic-gate return (1); 1076*7c478bd9Sstevel@tonic-gate } 1077*7c478bd9Sstevel@tonic-gate 1078*7c478bd9Sstevel@tonic-gate if (ml->ml_size != 0 && mt->t_type == INTRINSIC && 1079*7c478bd9Sstevel@tonic-gate mt->t_intr->intr_nbits != ml->ml_size) { 1080*7c478bd9Sstevel@tonic-gate /* 1081*7c478bd9Sstevel@tonic-gate * This member is a bitfield, and needs to reference 1082*7c478bd9Sstevel@tonic-gate * an intrinsic type with the same width. If the 1083*7c478bd9Sstevel@tonic-gate * currently-referenced type isn't of the same width, 1084*7c478bd9Sstevel@tonic-gate * we'll copy it, adjusting the width of the copy to 1085*7c478bd9Sstevel@tonic-gate * the size we'd like. 1086*7c478bd9Sstevel@tonic-gate */ 1087*7c478bd9Sstevel@tonic-gate debug(3, "tdp %u: creating bitfield for %d bits\n", 1088*7c478bd9Sstevel@tonic-gate tdp->t_id, ml->ml_size); 1089*7c478bd9Sstevel@tonic-gate 1090*7c478bd9Sstevel@tonic-gate ml->ml_type = tdesc_intr_clone(dw, mt, ml->ml_size); 1091*7c478bd9Sstevel@tonic-gate } 1092*7c478bd9Sstevel@tonic-gate } 1093*7c478bd9Sstevel@tonic-gate 1094*7c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 1095*7c478bd9Sstevel@tonic-gate 1096*7c478bd9Sstevel@tonic-gate return (1); 1097*7c478bd9Sstevel@tonic-gate } 1098*7c478bd9Sstevel@tonic-gate 1099*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 1100*7c478bd9Sstevel@tonic-gate static int 1101*7c478bd9Sstevel@tonic-gate die_sou_failed(tdesc_t *tdp, tdesc_t **tdpp, void *private) 1102*7c478bd9Sstevel@tonic-gate { 1103*7c478bd9Sstevel@tonic-gate const char *typename = (tdp->t_type == STRUCT ? "struct" : "union"); 1104*7c478bd9Sstevel@tonic-gate mlist_t *ml; 1105*7c478bd9Sstevel@tonic-gate 1106*7c478bd9Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 1107*7c478bd9Sstevel@tonic-gate return (1); 1108*7c478bd9Sstevel@tonic-gate 1109*7c478bd9Sstevel@tonic-gate for (ml = tdp->t_members; ml != NULL; ml = ml->ml_next) { 1110*7c478bd9Sstevel@tonic-gate if (ml->ml_size == 0) { 1111*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%s %d: failed to size member %s of " 1112*7c478bd9Sstevel@tonic-gate "type %s (%d)\n", typename, tdp->t_id, ml->ml_name, 1113*7c478bd9Sstevel@tonic-gate (ml->ml_type->t_name == NULL ? "(anon)" : 1114*7c478bd9Sstevel@tonic-gate ml->ml_type->t_name), ml->ml_type->t_id); 1115*7c478bd9Sstevel@tonic-gate } 1116*7c478bd9Sstevel@tonic-gate } 1117*7c478bd9Sstevel@tonic-gate 1118*7c478bd9Sstevel@tonic-gate return (1); 1119*7c478bd9Sstevel@tonic-gate } 1120*7c478bd9Sstevel@tonic-gate 1121*7c478bd9Sstevel@tonic-gate static void 1122*7c478bd9Sstevel@tonic-gate die_funcptr_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 1123*7c478bd9Sstevel@tonic-gate { 1124*7c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 1125*7c478bd9Sstevel@tonic-gate Dwarf_Half tag; 1126*7c478bd9Sstevel@tonic-gate Dwarf_Die arg; 1127*7c478bd9Sstevel@tonic-gate fndef_t *fn; 1128*7c478bd9Sstevel@tonic-gate int i; 1129*7c478bd9Sstevel@tonic-gate 1130*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating function pointer\n", off); 1131*7c478bd9Sstevel@tonic-gate 1132*7c478bd9Sstevel@tonic-gate /* 1133*7c478bd9Sstevel@tonic-gate * We'll begin by processing any type definition nodes that may be 1134*7c478bd9Sstevel@tonic-gate * lurking underneath this one. 1135*7c478bd9Sstevel@tonic-gate */ 1136*7c478bd9Sstevel@tonic-gate for (arg = die_child(dw, die); arg != NULL; 1137*7c478bd9Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 1138*7c478bd9Sstevel@tonic-gate if ((tag = die_tag(dw, arg)) != DW_TAG_formal_parameter && 1139*7c478bd9Sstevel@tonic-gate tag != DW_TAG_unspecified_parameters) { 1140*7c478bd9Sstevel@tonic-gate /* Nested type declaration */ 1141*7c478bd9Sstevel@tonic-gate die_create_one(dw, arg); 1142*7c478bd9Sstevel@tonic-gate } 1143*7c478bd9Sstevel@tonic-gate } 1144*7c478bd9Sstevel@tonic-gate 1145*7c478bd9Sstevel@tonic-gate if (die_isdecl(dw, die)) { 1146*7c478bd9Sstevel@tonic-gate /* 1147*7c478bd9Sstevel@tonic-gate * This is a prototype. We don't add prototypes to the 1148*7c478bd9Sstevel@tonic-gate * tree, so we're going to drop the tdesc. Unfortunately, 1149*7c478bd9Sstevel@tonic-gate * it has already been added to the tree. Nobody will reference 1150*7c478bd9Sstevel@tonic-gate * it, though, and it will be leaked. 1151*7c478bd9Sstevel@tonic-gate */ 1152*7c478bd9Sstevel@tonic-gate return; 1153*7c478bd9Sstevel@tonic-gate } 1154*7c478bd9Sstevel@tonic-gate 1155*7c478bd9Sstevel@tonic-gate fn = xcalloc(sizeof (fndef_t)); 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate tdp->t_type = FUNCTION; 1158*7c478bd9Sstevel@tonic-gate 1159*7c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, DW_AT_type, 0)) != NULL) { 1160*7c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 1161*7c478bd9Sstevel@tonic-gate fn->fn_ret = die_lookup_pass1(dw, die, DW_AT_type); 1162*7c478bd9Sstevel@tonic-gate } else { 1163*7c478bd9Sstevel@tonic-gate fn->fn_ret = tdesc_intr_void(dw); 1164*7c478bd9Sstevel@tonic-gate } 1165*7c478bd9Sstevel@tonic-gate 1166*7c478bd9Sstevel@tonic-gate /* 1167*7c478bd9Sstevel@tonic-gate * Count the arguments to the function, then read them in. 1168*7c478bd9Sstevel@tonic-gate */ 1169*7c478bd9Sstevel@tonic-gate for (fn->fn_nargs = 0, arg = die_child(dw, die); arg != NULL; 1170*7c478bd9Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 1171*7c478bd9Sstevel@tonic-gate if ((tag = die_tag(dw, arg)) == DW_TAG_formal_parameter) 1172*7c478bd9Sstevel@tonic-gate fn->fn_nargs++; 1173*7c478bd9Sstevel@tonic-gate else if (tag == DW_TAG_unspecified_parameters && 1174*7c478bd9Sstevel@tonic-gate fn->fn_nargs > 0) 1175*7c478bd9Sstevel@tonic-gate fn->fn_vargs = 1; 1176*7c478bd9Sstevel@tonic-gate } 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate if (fn->fn_nargs != 0) { 1179*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: adding %d argument%s\n", off, fn->fn_nargs, 1180*7c478bd9Sstevel@tonic-gate (fn->fn_nargs > 1 ? "s" : "")); 1181*7c478bd9Sstevel@tonic-gate 1182*7c478bd9Sstevel@tonic-gate fn->fn_args = xcalloc(sizeof (tdesc_t *) * fn->fn_nargs); 1183*7c478bd9Sstevel@tonic-gate for (i = 0, arg = die_child(dw, die); 1184*7c478bd9Sstevel@tonic-gate arg != NULL && i < fn->fn_nargs; 1185*7c478bd9Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 1186*7c478bd9Sstevel@tonic-gate if (die_tag(dw, arg) != DW_TAG_formal_parameter) 1187*7c478bd9Sstevel@tonic-gate continue; 1188*7c478bd9Sstevel@tonic-gate 1189*7c478bd9Sstevel@tonic-gate fn->fn_args[i++] = die_lookup_pass1(dw, arg, 1190*7c478bd9Sstevel@tonic-gate DW_AT_type); 1191*7c478bd9Sstevel@tonic-gate } 1192*7c478bd9Sstevel@tonic-gate } 1193*7c478bd9Sstevel@tonic-gate 1194*7c478bd9Sstevel@tonic-gate tdp->t_fndef = fn; 1195*7c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 1196*7c478bd9Sstevel@tonic-gate } 1197*7c478bd9Sstevel@tonic-gate 1198*7c478bd9Sstevel@tonic-gate /* 1199*7c478bd9Sstevel@tonic-gate * GCC and DevPro use different names for the base types. While the terms are 1200*7c478bd9Sstevel@tonic-gate * the same, they are arranged in a different order. Some terms, such as int, 1201*7c478bd9Sstevel@tonic-gate * are implied in one, and explicitly named in the other. Given a base type 1202*7c478bd9Sstevel@tonic-gate * as input, this routine will return a common name, along with an intr_t 1203*7c478bd9Sstevel@tonic-gate * that reflects said name. 1204*7c478bd9Sstevel@tonic-gate */ 1205*7c478bd9Sstevel@tonic-gate static intr_t * 1206*7c478bd9Sstevel@tonic-gate die_base_name_parse(const char *name, char **newp) 1207*7c478bd9Sstevel@tonic-gate { 1208*7c478bd9Sstevel@tonic-gate char buf[100]; 1209*7c478bd9Sstevel@tonic-gate char *base, *c; 1210*7c478bd9Sstevel@tonic-gate int nlong = 0, nshort = 0, nchar = 0, nint = 0; 1211*7c478bd9Sstevel@tonic-gate int sign = 1; 1212*7c478bd9Sstevel@tonic-gate char fmt = '\0'; 1213*7c478bd9Sstevel@tonic-gate intr_t *intr; 1214*7c478bd9Sstevel@tonic-gate 1215*7c478bd9Sstevel@tonic-gate if (strlen(name) > sizeof (buf) - 1) 1216*7c478bd9Sstevel@tonic-gate terminate("base type name \"%s\" is too long\n", name); 1217*7c478bd9Sstevel@tonic-gate 1218*7c478bd9Sstevel@tonic-gate strncpy(buf, name, sizeof (buf)); 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate for (c = strtok(buf, " "); c != NULL; c = strtok(NULL, " ")) { 1221*7c478bd9Sstevel@tonic-gate if (strcmp(c, "signed") == 0) 1222*7c478bd9Sstevel@tonic-gate sign = 1; 1223*7c478bd9Sstevel@tonic-gate else if (strcmp(c, "unsigned") == 0) 1224*7c478bd9Sstevel@tonic-gate sign = 0; 1225*7c478bd9Sstevel@tonic-gate else if (strcmp(c, "long") == 0) 1226*7c478bd9Sstevel@tonic-gate nlong++; 1227*7c478bd9Sstevel@tonic-gate else if (strcmp(c, "char") == 0) { 1228*7c478bd9Sstevel@tonic-gate nchar++; 1229*7c478bd9Sstevel@tonic-gate fmt = 'c'; 1230*7c478bd9Sstevel@tonic-gate } else if (strcmp(c, "short") == 0) 1231*7c478bd9Sstevel@tonic-gate nshort++; 1232*7c478bd9Sstevel@tonic-gate else if (strcmp(c, "int") == 0) 1233*7c478bd9Sstevel@tonic-gate nint++; 1234*7c478bd9Sstevel@tonic-gate else { 1235*7c478bd9Sstevel@tonic-gate /* 1236*7c478bd9Sstevel@tonic-gate * If we don't recognize any of the tokens, we'll tell 1237*7c478bd9Sstevel@tonic-gate * the caller to fall back to the dwarf-provided 1238*7c478bd9Sstevel@tonic-gate * encoding information. 1239*7c478bd9Sstevel@tonic-gate */ 1240*7c478bd9Sstevel@tonic-gate return (NULL); 1241*7c478bd9Sstevel@tonic-gate } 1242*7c478bd9Sstevel@tonic-gate } 1243*7c478bd9Sstevel@tonic-gate 1244*7c478bd9Sstevel@tonic-gate if (nchar > 1 || nshort > 1 || nint > 1 || nlong > 2) 1245*7c478bd9Sstevel@tonic-gate return (NULL); 1246*7c478bd9Sstevel@tonic-gate 1247*7c478bd9Sstevel@tonic-gate if (nchar > 0) { 1248*7c478bd9Sstevel@tonic-gate if (nlong > 0 || nshort > 0 || nint > 0) 1249*7c478bd9Sstevel@tonic-gate return (NULL); 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate base = "char"; 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate } else if (nshort > 0) { 1254*7c478bd9Sstevel@tonic-gate if (nlong > 0) 1255*7c478bd9Sstevel@tonic-gate return (NULL); 1256*7c478bd9Sstevel@tonic-gate 1257*7c478bd9Sstevel@tonic-gate base = "short"; 1258*7c478bd9Sstevel@tonic-gate 1259*7c478bd9Sstevel@tonic-gate } else if (nlong > 0) { 1260*7c478bd9Sstevel@tonic-gate base = "long"; 1261*7c478bd9Sstevel@tonic-gate 1262*7c478bd9Sstevel@tonic-gate } else { 1263*7c478bd9Sstevel@tonic-gate base = "int"; 1264*7c478bd9Sstevel@tonic-gate } 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate intr = xcalloc(sizeof (intr_t)); 1267*7c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 1268*7c478bd9Sstevel@tonic-gate intr->intr_signed = sign; 1269*7c478bd9Sstevel@tonic-gate intr->intr_iformat = fmt; 1270*7c478bd9Sstevel@tonic-gate 1271*7c478bd9Sstevel@tonic-gate snprintf(buf, sizeof (buf), "%s%s%s", 1272*7c478bd9Sstevel@tonic-gate (sign ? "" : "unsigned "), 1273*7c478bd9Sstevel@tonic-gate (nlong > 1 ? "long " : ""), 1274*7c478bd9Sstevel@tonic-gate base); 1275*7c478bd9Sstevel@tonic-gate 1276*7c478bd9Sstevel@tonic-gate *newp = xstrdup(buf); 1277*7c478bd9Sstevel@tonic-gate return (intr); 1278*7c478bd9Sstevel@tonic-gate } 1279*7c478bd9Sstevel@tonic-gate 1280*7c478bd9Sstevel@tonic-gate typedef struct fp_size_map { 1281*7c478bd9Sstevel@tonic-gate size_t fsm_typesz[2]; /* size of {32,64} type */ 1282*7c478bd9Sstevel@tonic-gate uint_t fsm_enc[3]; /* CTF_FP_* for {bare,cplx,imagry} type */ 1283*7c478bd9Sstevel@tonic-gate } fp_size_map_t; 1284*7c478bd9Sstevel@tonic-gate 1285*7c478bd9Sstevel@tonic-gate static const fp_size_map_t fp_encodings[] = { 1286*7c478bd9Sstevel@tonic-gate { { 4, 4 }, { CTF_FP_SINGLE, CTF_FP_CPLX, CTF_FP_IMAGRY } }, 1287*7c478bd9Sstevel@tonic-gate { { 8, 8 }, { CTF_FP_DOUBLE, CTF_FP_DCPLX, CTF_FP_DIMAGRY } }, 1288*7c478bd9Sstevel@tonic-gate { { 12, 16 }, { CTF_FP_LDOUBLE, CTF_FP_LDCPLX, CTF_FP_LDIMAGRY } }, 1289*7c478bd9Sstevel@tonic-gate { { 0, 0 } } 1290*7c478bd9Sstevel@tonic-gate }; 1291*7c478bd9Sstevel@tonic-gate 1292*7c478bd9Sstevel@tonic-gate static uint_t 1293*7c478bd9Sstevel@tonic-gate die_base_type2enc(dwarf_t *dw, Dwarf_Off off, Dwarf_Signed enc, size_t sz) 1294*7c478bd9Sstevel@tonic-gate { 1295*7c478bd9Sstevel@tonic-gate const fp_size_map_t *map = fp_encodings; 1296*7c478bd9Sstevel@tonic-gate uint_t szidx = dw->dw_ptrsz == sizeof (uint64_t); 1297*7c478bd9Sstevel@tonic-gate uint_t mult = 1, col = 0; 1298*7c478bd9Sstevel@tonic-gate 1299*7c478bd9Sstevel@tonic-gate if (enc == DW_ATE_complex_float) { 1300*7c478bd9Sstevel@tonic-gate mult = 2; 1301*7c478bd9Sstevel@tonic-gate col = 1; 1302*7c478bd9Sstevel@tonic-gate } else if (enc == DW_ATE_imaginary_float || 1303*7c478bd9Sstevel@tonic-gate enc == DW_ATE_SUN_imaginary_float) 1304*7c478bd9Sstevel@tonic-gate col = 2; 1305*7c478bd9Sstevel@tonic-gate 1306*7c478bd9Sstevel@tonic-gate while (map->fsm_typesz[szidx] != 0) { 1307*7c478bd9Sstevel@tonic-gate if (map->fsm_typesz[szidx] * mult == sz) 1308*7c478bd9Sstevel@tonic-gate return (map->fsm_enc[col]); 1309*7c478bd9Sstevel@tonic-gate map++; 1310*7c478bd9Sstevel@tonic-gate } 1311*7c478bd9Sstevel@tonic-gate 1312*7c478bd9Sstevel@tonic-gate terminate("die %llu: unrecognized real type size %u\n", off, sz); 1313*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1314*7c478bd9Sstevel@tonic-gate return (0); 1315*7c478bd9Sstevel@tonic-gate } 1316*7c478bd9Sstevel@tonic-gate 1317*7c478bd9Sstevel@tonic-gate static intr_t * 1318*7c478bd9Sstevel@tonic-gate die_base_from_dwarf(dwarf_t *dw, Dwarf_Die base, Dwarf_Off off, size_t sz) 1319*7c478bd9Sstevel@tonic-gate { 1320*7c478bd9Sstevel@tonic-gate intr_t *intr = xcalloc(sizeof (intr_t)); 1321*7c478bd9Sstevel@tonic-gate Dwarf_Signed enc; 1322*7c478bd9Sstevel@tonic-gate 1323*7c478bd9Sstevel@tonic-gate (void) die_signed(dw, base, DW_AT_encoding, &enc, DW_ATTR_REQ); 1324*7c478bd9Sstevel@tonic-gate 1325*7c478bd9Sstevel@tonic-gate switch (enc) { 1326*7c478bd9Sstevel@tonic-gate case DW_ATE_unsigned: 1327*7c478bd9Sstevel@tonic-gate case DW_ATE_address: 1328*7c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 1329*7c478bd9Sstevel@tonic-gate break; 1330*7c478bd9Sstevel@tonic-gate case DW_ATE_unsigned_char: 1331*7c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 1332*7c478bd9Sstevel@tonic-gate intr->intr_iformat = 'c'; 1333*7c478bd9Sstevel@tonic-gate break; 1334*7c478bd9Sstevel@tonic-gate case DW_ATE_signed: 1335*7c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 1336*7c478bd9Sstevel@tonic-gate intr->intr_signed = 1; 1337*7c478bd9Sstevel@tonic-gate break; 1338*7c478bd9Sstevel@tonic-gate case DW_ATE_signed_char: 1339*7c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 1340*7c478bd9Sstevel@tonic-gate intr->intr_signed = 1; 1341*7c478bd9Sstevel@tonic-gate intr->intr_iformat = 'c'; 1342*7c478bd9Sstevel@tonic-gate break; 1343*7c478bd9Sstevel@tonic-gate case DW_ATE_boolean: 1344*7c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 1345*7c478bd9Sstevel@tonic-gate intr->intr_signed = 1; 1346*7c478bd9Sstevel@tonic-gate intr->intr_iformat = 'b'; 1347*7c478bd9Sstevel@tonic-gate break; 1348*7c478bd9Sstevel@tonic-gate case DW_ATE_float: 1349*7c478bd9Sstevel@tonic-gate case DW_ATE_complex_float: 1350*7c478bd9Sstevel@tonic-gate case DW_ATE_imaginary_float: 1351*7c478bd9Sstevel@tonic-gate case DW_ATE_SUN_imaginary_float: 1352*7c478bd9Sstevel@tonic-gate case DW_ATE_SUN_interval_float: 1353*7c478bd9Sstevel@tonic-gate intr->intr_type = INTR_REAL; 1354*7c478bd9Sstevel@tonic-gate intr->intr_signed = 1; 1355*7c478bd9Sstevel@tonic-gate intr->intr_fformat = die_base_type2enc(dw, off, enc, sz); 1356*7c478bd9Sstevel@tonic-gate break; 1357*7c478bd9Sstevel@tonic-gate default: 1358*7c478bd9Sstevel@tonic-gate terminate("die %llu: unknown base type encoding 0x%llx\n", 1359*7c478bd9Sstevel@tonic-gate off, enc); 1360*7c478bd9Sstevel@tonic-gate } 1361*7c478bd9Sstevel@tonic-gate 1362*7c478bd9Sstevel@tonic-gate return (intr); 1363*7c478bd9Sstevel@tonic-gate } 1364*7c478bd9Sstevel@tonic-gate 1365*7c478bd9Sstevel@tonic-gate static void 1366*7c478bd9Sstevel@tonic-gate die_base_create(dwarf_t *dw, Dwarf_Die base, Dwarf_Off off, tdesc_t *tdp) 1367*7c478bd9Sstevel@tonic-gate { 1368*7c478bd9Sstevel@tonic-gate Dwarf_Unsigned sz; 1369*7c478bd9Sstevel@tonic-gate intr_t *intr; 1370*7c478bd9Sstevel@tonic-gate char *new; 1371*7c478bd9Sstevel@tonic-gate 1372*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating base type\n", off); 1373*7c478bd9Sstevel@tonic-gate 1374*7c478bd9Sstevel@tonic-gate /* 1375*7c478bd9Sstevel@tonic-gate * The compilers have their own clever (internally inconsistent) ideas 1376*7c478bd9Sstevel@tonic-gate * as to what base types should look like. Some times gcc will, for 1377*7c478bd9Sstevel@tonic-gate * example, use DW_ATE_signed_char for char. Other times, however, it 1378*7c478bd9Sstevel@tonic-gate * will use DW_ATE_signed. Needless to say, this causes some problems 1379*7c478bd9Sstevel@tonic-gate * down the road, particularly with merging. We do, however, use the 1380*7c478bd9Sstevel@tonic-gate * DWARF idea of type sizes, as this allows us to avoid caring about 1381*7c478bd9Sstevel@tonic-gate * the data model. 1382*7c478bd9Sstevel@tonic-gate */ 1383*7c478bd9Sstevel@tonic-gate (void) die_unsigned(dw, base, DW_AT_byte_size, &sz, DW_ATTR_REQ); 1384*7c478bd9Sstevel@tonic-gate 1385*7c478bd9Sstevel@tonic-gate if (tdp->t_name == NULL) 1386*7c478bd9Sstevel@tonic-gate terminate("die %llu: base type without name\n", off); 1387*7c478bd9Sstevel@tonic-gate 1388*7c478bd9Sstevel@tonic-gate /* XXX make a name parser for float too */ 1389*7c478bd9Sstevel@tonic-gate if ((intr = die_base_name_parse(tdp->t_name, &new)) != NULL) { 1390*7c478bd9Sstevel@tonic-gate /* Found it. We'll use the parsed version */ 1391*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: name \"%s\" remapped to \"%s\"\n", off, 1392*7c478bd9Sstevel@tonic-gate tdp->t_name, new); 1393*7c478bd9Sstevel@tonic-gate 1394*7c478bd9Sstevel@tonic-gate free(tdp->t_name); 1395*7c478bd9Sstevel@tonic-gate tdp->t_name = new; 1396*7c478bd9Sstevel@tonic-gate } else { 1397*7c478bd9Sstevel@tonic-gate /* 1398*7c478bd9Sstevel@tonic-gate * We didn't recognize the type, so we'll create an intr_t 1399*7c478bd9Sstevel@tonic-gate * based on the DWARF data. 1400*7c478bd9Sstevel@tonic-gate */ 1401*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: using dwarf data for base \"%s\"\n", off, 1402*7c478bd9Sstevel@tonic-gate tdp->t_name); 1403*7c478bd9Sstevel@tonic-gate 1404*7c478bd9Sstevel@tonic-gate intr = die_base_from_dwarf(dw, base, off, sz); 1405*7c478bd9Sstevel@tonic-gate } 1406*7c478bd9Sstevel@tonic-gate 1407*7c478bd9Sstevel@tonic-gate intr->intr_nbits = sz * 8; 1408*7c478bd9Sstevel@tonic-gate 1409*7c478bd9Sstevel@tonic-gate tdp->t_type = INTRINSIC; 1410*7c478bd9Sstevel@tonic-gate tdp->t_intr = intr; 1411*7c478bd9Sstevel@tonic-gate tdp->t_size = sz; 1412*7c478bd9Sstevel@tonic-gate 1413*7c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 1414*7c478bd9Sstevel@tonic-gate } 1415*7c478bd9Sstevel@tonic-gate 1416*7c478bd9Sstevel@tonic-gate static void 1417*7c478bd9Sstevel@tonic-gate die_through_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp, 1418*7c478bd9Sstevel@tonic-gate int type, const char *typename) 1419*7c478bd9Sstevel@tonic-gate { 1420*7c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 1421*7c478bd9Sstevel@tonic-gate 1422*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating %s\n", off, typename); 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate tdp->t_type = type; 1425*7c478bd9Sstevel@tonic-gate 1426*7c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, DW_AT_type, 0)) != NULL) { 1427*7c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 1428*7c478bd9Sstevel@tonic-gate tdp->t_tdesc = die_lookup_pass1(dw, die, DW_AT_type); 1429*7c478bd9Sstevel@tonic-gate } else { 1430*7c478bd9Sstevel@tonic-gate tdp->t_tdesc = tdesc_intr_void(dw); 1431*7c478bd9Sstevel@tonic-gate } 1432*7c478bd9Sstevel@tonic-gate 1433*7c478bd9Sstevel@tonic-gate if (type == POINTER) 1434*7c478bd9Sstevel@tonic-gate tdp->t_size = dw->dw_ptrsz; 1435*7c478bd9Sstevel@tonic-gate 1436*7c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 1437*7c478bd9Sstevel@tonic-gate 1438*7c478bd9Sstevel@tonic-gate if (type == TYPEDEF) { 1439*7c478bd9Sstevel@tonic-gate iidesc_t *ii = xcalloc(sizeof (iidesc_t)); 1440*7c478bd9Sstevel@tonic-gate ii->ii_type = II_TYPE; 1441*7c478bd9Sstevel@tonic-gate ii->ii_name = xstrdup(tdp->t_name); 1442*7c478bd9Sstevel@tonic-gate ii->ii_dtype = tdp; 1443*7c478bd9Sstevel@tonic-gate 1444*7c478bd9Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 1445*7c478bd9Sstevel@tonic-gate } 1446*7c478bd9Sstevel@tonic-gate } 1447*7c478bd9Sstevel@tonic-gate 1448*7c478bd9Sstevel@tonic-gate static void 1449*7c478bd9Sstevel@tonic-gate die_typedef_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 1450*7c478bd9Sstevel@tonic-gate { 1451*7c478bd9Sstevel@tonic-gate die_through_create(dw, die, off, tdp, TYPEDEF, "typedef"); 1452*7c478bd9Sstevel@tonic-gate } 1453*7c478bd9Sstevel@tonic-gate 1454*7c478bd9Sstevel@tonic-gate static void 1455*7c478bd9Sstevel@tonic-gate die_const_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 1456*7c478bd9Sstevel@tonic-gate { 1457*7c478bd9Sstevel@tonic-gate die_through_create(dw, die, off, tdp, CONST, "const"); 1458*7c478bd9Sstevel@tonic-gate } 1459*7c478bd9Sstevel@tonic-gate 1460*7c478bd9Sstevel@tonic-gate static void 1461*7c478bd9Sstevel@tonic-gate die_pointer_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 1462*7c478bd9Sstevel@tonic-gate { 1463*7c478bd9Sstevel@tonic-gate die_through_create(dw, die, off, tdp, POINTER, "pointer"); 1464*7c478bd9Sstevel@tonic-gate } 1465*7c478bd9Sstevel@tonic-gate 1466*7c478bd9Sstevel@tonic-gate static void 1467*7c478bd9Sstevel@tonic-gate die_restrict_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 1468*7c478bd9Sstevel@tonic-gate { 1469*7c478bd9Sstevel@tonic-gate die_through_create(dw, die, off, tdp, RESTRICT, "restrict"); 1470*7c478bd9Sstevel@tonic-gate } 1471*7c478bd9Sstevel@tonic-gate 1472*7c478bd9Sstevel@tonic-gate static void 1473*7c478bd9Sstevel@tonic-gate die_volatile_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 1474*7c478bd9Sstevel@tonic-gate { 1475*7c478bd9Sstevel@tonic-gate die_through_create(dw, die, off, tdp, VOLATILE, "volatile"); 1476*7c478bd9Sstevel@tonic-gate } 1477*7c478bd9Sstevel@tonic-gate 1478*7c478bd9Sstevel@tonic-gate /*ARGSUSED3*/ 1479*7c478bd9Sstevel@tonic-gate static void 1480*7c478bd9Sstevel@tonic-gate die_function_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 1481*7c478bd9Sstevel@tonic-gate { 1482*7c478bd9Sstevel@tonic-gate Dwarf_Die arg; 1483*7c478bd9Sstevel@tonic-gate Dwarf_Half tag; 1484*7c478bd9Sstevel@tonic-gate iidesc_t *ii; 1485*7c478bd9Sstevel@tonic-gate char *name; 1486*7c478bd9Sstevel@tonic-gate 1487*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating function definition\n", off); 1488*7c478bd9Sstevel@tonic-gate 1489*7c478bd9Sstevel@tonic-gate /* 1490*7c478bd9Sstevel@tonic-gate * We'll begin by processing any type definition nodes that may be 1491*7c478bd9Sstevel@tonic-gate * lurking underneath this one. 1492*7c478bd9Sstevel@tonic-gate */ 1493*7c478bd9Sstevel@tonic-gate for (arg = die_child(dw, die); arg != NULL; 1494*7c478bd9Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 1495*7c478bd9Sstevel@tonic-gate if ((tag = die_tag(dw, arg)) != DW_TAG_formal_parameter && 1496*7c478bd9Sstevel@tonic-gate tag != DW_TAG_variable) { 1497*7c478bd9Sstevel@tonic-gate /* Nested type declaration */ 1498*7c478bd9Sstevel@tonic-gate die_create_one(dw, arg); 1499*7c478bd9Sstevel@tonic-gate } 1500*7c478bd9Sstevel@tonic-gate } 1501*7c478bd9Sstevel@tonic-gate 1502*7c478bd9Sstevel@tonic-gate if (die_isdecl(dw, die) || (name = die_name(dw, die)) == NULL) { 1503*7c478bd9Sstevel@tonic-gate /* 1504*7c478bd9Sstevel@tonic-gate * We process neither prototypes nor subprograms without 1505*7c478bd9Sstevel@tonic-gate * names. 1506*7c478bd9Sstevel@tonic-gate */ 1507*7c478bd9Sstevel@tonic-gate return; 1508*7c478bd9Sstevel@tonic-gate } 1509*7c478bd9Sstevel@tonic-gate 1510*7c478bd9Sstevel@tonic-gate ii = xcalloc(sizeof (iidesc_t)); 1511*7c478bd9Sstevel@tonic-gate ii->ii_type = die_isglobal(dw, die) ? II_GFUN : II_SFUN; 1512*7c478bd9Sstevel@tonic-gate ii->ii_name = name; 1513*7c478bd9Sstevel@tonic-gate if (ii->ii_type == II_SFUN) 1514*7c478bd9Sstevel@tonic-gate ii->ii_owner = xstrdup(dw->dw_cuname); 1515*7c478bd9Sstevel@tonic-gate 1516*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: function %s is %s\n", off, ii->ii_name, 1517*7c478bd9Sstevel@tonic-gate (ii->ii_type == II_GFUN ? "global" : "static")); 1518*7c478bd9Sstevel@tonic-gate 1519*7c478bd9Sstevel@tonic-gate if (die_attr(dw, die, DW_AT_type, 0) != NULL) 1520*7c478bd9Sstevel@tonic-gate ii->ii_dtype = die_lookup_pass1(dw, die, DW_AT_type); 1521*7c478bd9Sstevel@tonic-gate else 1522*7c478bd9Sstevel@tonic-gate ii->ii_dtype = tdesc_intr_void(dw); 1523*7c478bd9Sstevel@tonic-gate 1524*7c478bd9Sstevel@tonic-gate for (arg = die_child(dw, die); arg != NULL; 1525*7c478bd9Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 1526*7c478bd9Sstevel@tonic-gate char *name; 1527*7c478bd9Sstevel@tonic-gate 1528*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: looking at sub member at %llu\n", 1529*7c478bd9Sstevel@tonic-gate off, die_off(dw, die)); 1530*7c478bd9Sstevel@tonic-gate 1531*7c478bd9Sstevel@tonic-gate if (die_tag(dw, arg) != DW_TAG_formal_parameter) 1532*7c478bd9Sstevel@tonic-gate continue; 1533*7c478bd9Sstevel@tonic-gate 1534*7c478bd9Sstevel@tonic-gate if ((name = die_name(dw, arg)) == NULL) { 1535*7c478bd9Sstevel@tonic-gate terminate("die %llu: func arg %d has no name\n", 1536*7c478bd9Sstevel@tonic-gate off, ii->ii_nargs + 1); 1537*7c478bd9Sstevel@tonic-gate } 1538*7c478bd9Sstevel@tonic-gate 1539*7c478bd9Sstevel@tonic-gate if (strcmp(name, "...") == 0) { 1540*7c478bd9Sstevel@tonic-gate free(name); 1541*7c478bd9Sstevel@tonic-gate ii->ii_vargs = 1; 1542*7c478bd9Sstevel@tonic-gate continue; 1543*7c478bd9Sstevel@tonic-gate } 1544*7c478bd9Sstevel@tonic-gate 1545*7c478bd9Sstevel@tonic-gate ii->ii_nargs++; 1546*7c478bd9Sstevel@tonic-gate } 1547*7c478bd9Sstevel@tonic-gate 1548*7c478bd9Sstevel@tonic-gate if (ii->ii_nargs > 0) { 1549*7c478bd9Sstevel@tonic-gate int i; 1550*7c478bd9Sstevel@tonic-gate 1551*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: function has %d argument%s\n", off, 1552*7c478bd9Sstevel@tonic-gate ii->ii_nargs, (ii->ii_nargs == 1 ? "" : "s")); 1553*7c478bd9Sstevel@tonic-gate 1554*7c478bd9Sstevel@tonic-gate ii->ii_args = xcalloc(sizeof (tdesc_t) * ii->ii_nargs); 1555*7c478bd9Sstevel@tonic-gate 1556*7c478bd9Sstevel@tonic-gate for (arg = die_child(dw, die), i = 0; 1557*7c478bd9Sstevel@tonic-gate arg != NULL && i < ii->ii_nargs; 1558*7c478bd9Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 1559*7c478bd9Sstevel@tonic-gate if (die_tag(dw, arg) != DW_TAG_formal_parameter) 1560*7c478bd9Sstevel@tonic-gate continue; 1561*7c478bd9Sstevel@tonic-gate 1562*7c478bd9Sstevel@tonic-gate ii->ii_args[i++] = die_lookup_pass1(dw, arg, 1563*7c478bd9Sstevel@tonic-gate DW_AT_type); 1564*7c478bd9Sstevel@tonic-gate } 1565*7c478bd9Sstevel@tonic-gate } 1566*7c478bd9Sstevel@tonic-gate 1567*7c478bd9Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 1568*7c478bd9Sstevel@tonic-gate } 1569*7c478bd9Sstevel@tonic-gate 1570*7c478bd9Sstevel@tonic-gate /*ARGSUSED3*/ 1571*7c478bd9Sstevel@tonic-gate static void 1572*7c478bd9Sstevel@tonic-gate die_variable_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 1573*7c478bd9Sstevel@tonic-gate { 1574*7c478bd9Sstevel@tonic-gate iidesc_t *ii; 1575*7c478bd9Sstevel@tonic-gate char *name; 1576*7c478bd9Sstevel@tonic-gate 1577*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating object definition\n", off); 1578*7c478bd9Sstevel@tonic-gate 1579*7c478bd9Sstevel@tonic-gate if (die_isdecl(dw, die) || (name = die_name(dw, die)) == NULL) 1580*7c478bd9Sstevel@tonic-gate return; /* skip prototypes and nameless objects */ 1581*7c478bd9Sstevel@tonic-gate 1582*7c478bd9Sstevel@tonic-gate ii = xcalloc(sizeof (iidesc_t)); 1583*7c478bd9Sstevel@tonic-gate ii->ii_type = die_isglobal(dw, die) ? II_GVAR : II_SVAR; 1584*7c478bd9Sstevel@tonic-gate ii->ii_name = name; 1585*7c478bd9Sstevel@tonic-gate ii->ii_dtype = die_lookup_pass1(dw, die, DW_AT_type); 1586*7c478bd9Sstevel@tonic-gate if (ii->ii_type == II_SVAR) 1587*7c478bd9Sstevel@tonic-gate ii->ii_owner = xstrdup(dw->dw_cuname); 1588*7c478bd9Sstevel@tonic-gate 1589*7c478bd9Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 1590*7c478bd9Sstevel@tonic-gate } 1591*7c478bd9Sstevel@tonic-gate 1592*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 1593*7c478bd9Sstevel@tonic-gate static int 1594*7c478bd9Sstevel@tonic-gate die_fwd_resolve(tdesc_t *fwd, tdesc_t **fwdp, void *private) 1595*7c478bd9Sstevel@tonic-gate { 1596*7c478bd9Sstevel@tonic-gate if (fwd->t_flags & TDESC_F_RESOLVED) 1597*7c478bd9Sstevel@tonic-gate return (1); 1598*7c478bd9Sstevel@tonic-gate 1599*7c478bd9Sstevel@tonic-gate if (fwd->t_tdesc != NULL) { 1600*7c478bd9Sstevel@tonic-gate debug(3, "tdp %u: unforwarded %s\n", fwd->t_id, fwd->t_name); 1601*7c478bd9Sstevel@tonic-gate *fwdp = fwd->t_tdesc; 1602*7c478bd9Sstevel@tonic-gate } 1603*7c478bd9Sstevel@tonic-gate 1604*7c478bd9Sstevel@tonic-gate fwd->t_flags |= TDESC_F_RESOLVED; 1605*7c478bd9Sstevel@tonic-gate 1606*7c478bd9Sstevel@tonic-gate return (1); 1607*7c478bd9Sstevel@tonic-gate } 1608*7c478bd9Sstevel@tonic-gate 1609*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1610*7c478bd9Sstevel@tonic-gate static void 1611*7c478bd9Sstevel@tonic-gate die_lexblk_descend(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 1612*7c478bd9Sstevel@tonic-gate { 1613*7c478bd9Sstevel@tonic-gate Dwarf_Die child = die_child(dw, die); 1614*7c478bd9Sstevel@tonic-gate 1615*7c478bd9Sstevel@tonic-gate if (child != NULL) 1616*7c478bd9Sstevel@tonic-gate die_create(dw, child); 1617*7c478bd9Sstevel@tonic-gate } 1618*7c478bd9Sstevel@tonic-gate 1619*7c478bd9Sstevel@tonic-gate /* 1620*7c478bd9Sstevel@tonic-gate * Used to map the die to a routine which can parse it, using the tag to do the 1621*7c478bd9Sstevel@tonic-gate * mapping. While the processing of most tags entails the creation of a tdesc, 1622*7c478bd9Sstevel@tonic-gate * there are a few which don't - primarily those which result in the creation of 1623*7c478bd9Sstevel@tonic-gate * iidescs which refer to existing tdescs. 1624*7c478bd9Sstevel@tonic-gate */ 1625*7c478bd9Sstevel@tonic-gate 1626*7c478bd9Sstevel@tonic-gate #define DW_F_NOTDP 0x1 /* Don't create a tdesc for the creator */ 1627*7c478bd9Sstevel@tonic-gate 1628*7c478bd9Sstevel@tonic-gate typedef struct die_creator { 1629*7c478bd9Sstevel@tonic-gate Dwarf_Half dc_tag; 1630*7c478bd9Sstevel@tonic-gate uint16_t dc_flags; 1631*7c478bd9Sstevel@tonic-gate void (*dc_create)(dwarf_t *, Dwarf_Die, Dwarf_Off, tdesc_t *); 1632*7c478bd9Sstevel@tonic-gate } die_creator_t; 1633*7c478bd9Sstevel@tonic-gate 1634*7c478bd9Sstevel@tonic-gate static const die_creator_t die_creators[] = { 1635*7c478bd9Sstevel@tonic-gate { DW_TAG_array_type, 0, die_array_create }, 1636*7c478bd9Sstevel@tonic-gate { DW_TAG_enumeration_type, 0, die_enum_create }, 1637*7c478bd9Sstevel@tonic-gate { DW_TAG_lexical_block, DW_F_NOTDP, die_lexblk_descend }, 1638*7c478bd9Sstevel@tonic-gate { DW_TAG_pointer_type, 0, die_pointer_create }, 1639*7c478bd9Sstevel@tonic-gate { DW_TAG_structure_type, 0, die_struct_create }, 1640*7c478bd9Sstevel@tonic-gate { DW_TAG_subroutine_type, 0, die_funcptr_create }, 1641*7c478bd9Sstevel@tonic-gate { DW_TAG_typedef, 0, die_typedef_create }, 1642*7c478bd9Sstevel@tonic-gate { DW_TAG_union_type, 0, die_union_create }, 1643*7c478bd9Sstevel@tonic-gate { DW_TAG_base_type, 0, die_base_create }, 1644*7c478bd9Sstevel@tonic-gate { DW_TAG_const_type, 0, die_const_create }, 1645*7c478bd9Sstevel@tonic-gate { DW_TAG_subprogram, DW_F_NOTDP, die_function_create }, 1646*7c478bd9Sstevel@tonic-gate { DW_TAG_variable, DW_F_NOTDP, die_variable_create }, 1647*7c478bd9Sstevel@tonic-gate { DW_TAG_volatile_type, 0, die_volatile_create }, 1648*7c478bd9Sstevel@tonic-gate { DW_TAG_restrict_type, 0, die_restrict_create }, 1649*7c478bd9Sstevel@tonic-gate { 0, NULL } 1650*7c478bd9Sstevel@tonic-gate }; 1651*7c478bd9Sstevel@tonic-gate 1652*7c478bd9Sstevel@tonic-gate static const die_creator_t * 1653*7c478bd9Sstevel@tonic-gate die_tag2ctor(Dwarf_Half tag) 1654*7c478bd9Sstevel@tonic-gate { 1655*7c478bd9Sstevel@tonic-gate const die_creator_t *dc; 1656*7c478bd9Sstevel@tonic-gate 1657*7c478bd9Sstevel@tonic-gate for (dc = die_creators; dc->dc_create != NULL; dc++) { 1658*7c478bd9Sstevel@tonic-gate if (dc->dc_tag == tag) 1659*7c478bd9Sstevel@tonic-gate return (dc); 1660*7c478bd9Sstevel@tonic-gate } 1661*7c478bd9Sstevel@tonic-gate 1662*7c478bd9Sstevel@tonic-gate return (NULL); 1663*7c478bd9Sstevel@tonic-gate } 1664*7c478bd9Sstevel@tonic-gate 1665*7c478bd9Sstevel@tonic-gate static void 1666*7c478bd9Sstevel@tonic-gate die_create_one(dwarf_t *dw, Dwarf_Die die) 1667*7c478bd9Sstevel@tonic-gate { 1668*7c478bd9Sstevel@tonic-gate Dwarf_Off off = die_off(dw, die); 1669*7c478bd9Sstevel@tonic-gate const die_creator_t *dc; 1670*7c478bd9Sstevel@tonic-gate Dwarf_Half tag; 1671*7c478bd9Sstevel@tonic-gate tdesc_t *tdp; 1672*7c478bd9Sstevel@tonic-gate 1673*7c478bd9Sstevel@tonic-gate debug(3, "die %llu: create_one\n", off); 1674*7c478bd9Sstevel@tonic-gate 1675*7c478bd9Sstevel@tonic-gate if (off > dw->dw_maxoff) { 1676*7c478bd9Sstevel@tonic-gate terminate("illegal die offset %llu (max %llu)\n", off, 1677*7c478bd9Sstevel@tonic-gate dw->dw_maxoff); 1678*7c478bd9Sstevel@tonic-gate } 1679*7c478bd9Sstevel@tonic-gate 1680*7c478bd9Sstevel@tonic-gate tag = die_tag(dw, die); 1681*7c478bd9Sstevel@tonic-gate 1682*7c478bd9Sstevel@tonic-gate if ((dc = die_tag2ctor(tag)) == NULL) { 1683*7c478bd9Sstevel@tonic-gate debug(2, "die %llu: ignoring tag type %x\n", off, tag); 1684*7c478bd9Sstevel@tonic-gate return; 1685*7c478bd9Sstevel@tonic-gate } 1686*7c478bd9Sstevel@tonic-gate 1687*7c478bd9Sstevel@tonic-gate if ((tdp = tdesc_lookup(dw, off)) == NULL && 1688*7c478bd9Sstevel@tonic-gate !(dc->dc_flags & DW_F_NOTDP)) { 1689*7c478bd9Sstevel@tonic-gate tdp = xcalloc(sizeof (tdesc_t)); 1690*7c478bd9Sstevel@tonic-gate tdp->t_id = off; 1691*7c478bd9Sstevel@tonic-gate tdesc_add(dw, tdp); 1692*7c478bd9Sstevel@tonic-gate } 1693*7c478bd9Sstevel@tonic-gate 1694*7c478bd9Sstevel@tonic-gate if (tdp != NULL) 1695*7c478bd9Sstevel@tonic-gate tdp->t_name = die_name(dw, die); 1696*7c478bd9Sstevel@tonic-gate 1697*7c478bd9Sstevel@tonic-gate dc->dc_create(dw, die, off, tdp); 1698*7c478bd9Sstevel@tonic-gate } 1699*7c478bd9Sstevel@tonic-gate 1700*7c478bd9Sstevel@tonic-gate static void 1701*7c478bd9Sstevel@tonic-gate die_create(dwarf_t *dw, Dwarf_Die die) 1702*7c478bd9Sstevel@tonic-gate { 1703*7c478bd9Sstevel@tonic-gate do { 1704*7c478bd9Sstevel@tonic-gate die_create_one(dw, die); 1705*7c478bd9Sstevel@tonic-gate } while ((die = die_sibling(dw, die)) != NULL); 1706*7c478bd9Sstevel@tonic-gate } 1707*7c478bd9Sstevel@tonic-gate 1708*7c478bd9Sstevel@tonic-gate static tdtrav_cb_f die_resolvers[] = { 1709*7c478bd9Sstevel@tonic-gate NULL, 1710*7c478bd9Sstevel@tonic-gate NULL, /* intrinsic */ 1711*7c478bd9Sstevel@tonic-gate NULL, /* pointer */ 1712*7c478bd9Sstevel@tonic-gate die_array_resolve, /* array */ 1713*7c478bd9Sstevel@tonic-gate NULL, /* function */ 1714*7c478bd9Sstevel@tonic-gate die_sou_resolve, /* struct */ 1715*7c478bd9Sstevel@tonic-gate die_sou_resolve, /* union */ 1716*7c478bd9Sstevel@tonic-gate die_enum_resolve, /* enum */ 1717*7c478bd9Sstevel@tonic-gate die_fwd_resolve, /* forward */ 1718*7c478bd9Sstevel@tonic-gate NULL, /* typedef */ 1719*7c478bd9Sstevel@tonic-gate NULL, /* typedef unres */ 1720*7c478bd9Sstevel@tonic-gate NULL, /* volatile */ 1721*7c478bd9Sstevel@tonic-gate NULL, /* const */ 1722*7c478bd9Sstevel@tonic-gate NULL, /* restrict */ 1723*7c478bd9Sstevel@tonic-gate }; 1724*7c478bd9Sstevel@tonic-gate 1725*7c478bd9Sstevel@tonic-gate static tdtrav_cb_f die_fail_reporters[] = { 1726*7c478bd9Sstevel@tonic-gate NULL, 1727*7c478bd9Sstevel@tonic-gate NULL, /* intrinsic */ 1728*7c478bd9Sstevel@tonic-gate NULL, /* pointer */ 1729*7c478bd9Sstevel@tonic-gate die_array_failed, /* array */ 1730*7c478bd9Sstevel@tonic-gate NULL, /* function */ 1731*7c478bd9Sstevel@tonic-gate die_sou_failed, /* struct */ 1732*7c478bd9Sstevel@tonic-gate die_sou_failed, /* union */ 1733*7c478bd9Sstevel@tonic-gate NULL, /* enum */ 1734*7c478bd9Sstevel@tonic-gate NULL, /* forward */ 1735*7c478bd9Sstevel@tonic-gate NULL, /* typedef */ 1736*7c478bd9Sstevel@tonic-gate NULL, /* typedef unres */ 1737*7c478bd9Sstevel@tonic-gate NULL, /* volatile */ 1738*7c478bd9Sstevel@tonic-gate NULL, /* const */ 1739*7c478bd9Sstevel@tonic-gate NULL, /* restrict */ 1740*7c478bd9Sstevel@tonic-gate }; 1741*7c478bd9Sstevel@tonic-gate 1742*7c478bd9Sstevel@tonic-gate static void 1743*7c478bd9Sstevel@tonic-gate die_resolve(dwarf_t *dw) 1744*7c478bd9Sstevel@tonic-gate { 1745*7c478bd9Sstevel@tonic-gate int last = -1; 1746*7c478bd9Sstevel@tonic-gate int pass = 0; 1747*7c478bd9Sstevel@tonic-gate 1748*7c478bd9Sstevel@tonic-gate do { 1749*7c478bd9Sstevel@tonic-gate pass++; 1750*7c478bd9Sstevel@tonic-gate dw->dw_nunres = 0; 1751*7c478bd9Sstevel@tonic-gate 1752*7c478bd9Sstevel@tonic-gate (void) iitraverse_hash(dw->dw_td->td_iihash, 1753*7c478bd9Sstevel@tonic-gate &dw->dw_td->td_curvgen, NULL, NULL, die_resolvers, dw); 1754*7c478bd9Sstevel@tonic-gate 1755*7c478bd9Sstevel@tonic-gate debug(3, "resolve: pass %d, %u left\n", pass, dw->dw_nunres); 1756*7c478bd9Sstevel@tonic-gate 1757*7c478bd9Sstevel@tonic-gate if (dw->dw_nunres == last) { 1758*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: failed to resolve the following " 1759*7c478bd9Sstevel@tonic-gate "types:\n", progname); 1760*7c478bd9Sstevel@tonic-gate 1761*7c478bd9Sstevel@tonic-gate (void) iitraverse_hash(dw->dw_td->td_iihash, 1762*7c478bd9Sstevel@tonic-gate &dw->dw_td->td_curvgen, NULL, NULL, 1763*7c478bd9Sstevel@tonic-gate die_fail_reporters, dw); 1764*7c478bd9Sstevel@tonic-gate 1765*7c478bd9Sstevel@tonic-gate terminate("failed to resolve types\n"); 1766*7c478bd9Sstevel@tonic-gate } 1767*7c478bd9Sstevel@tonic-gate 1768*7c478bd9Sstevel@tonic-gate last = dw->dw_nunres; 1769*7c478bd9Sstevel@tonic-gate 1770*7c478bd9Sstevel@tonic-gate } while (dw->dw_nunres != 0); 1771*7c478bd9Sstevel@tonic-gate } 1772*7c478bd9Sstevel@tonic-gate 1773*7c478bd9Sstevel@tonic-gate static size_t 1774*7c478bd9Sstevel@tonic-gate elf_ptrsz(Elf *elf) 1775*7c478bd9Sstevel@tonic-gate { 1776*7c478bd9Sstevel@tonic-gate GElf_Ehdr ehdr; 1777*7c478bd9Sstevel@tonic-gate 1778*7c478bd9Sstevel@tonic-gate if (gelf_getehdr(elf, &ehdr) == NULL) { 1779*7c478bd9Sstevel@tonic-gate terminate("failed to read ELF header: %s\n", 1780*7c478bd9Sstevel@tonic-gate elf_errmsg(elf_errno())); 1781*7c478bd9Sstevel@tonic-gate } 1782*7c478bd9Sstevel@tonic-gate 1783*7c478bd9Sstevel@tonic-gate if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) 1784*7c478bd9Sstevel@tonic-gate return (4); 1785*7c478bd9Sstevel@tonic-gate else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) 1786*7c478bd9Sstevel@tonic-gate return (8); 1787*7c478bd9Sstevel@tonic-gate else 1788*7c478bd9Sstevel@tonic-gate terminate("unknown ELF class %d\n", ehdr.e_ident[EI_CLASS]); 1789*7c478bd9Sstevel@tonic-gate 1790*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1791*7c478bd9Sstevel@tonic-gate return (0); 1792*7c478bd9Sstevel@tonic-gate } 1793*7c478bd9Sstevel@tonic-gate 1794*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1795*7c478bd9Sstevel@tonic-gate int 1796*7c478bd9Sstevel@tonic-gate dw_read(tdata_t *td, Elf *elf, const char *filename) 1797*7c478bd9Sstevel@tonic-gate { 1798*7c478bd9Sstevel@tonic-gate Dwarf_Unsigned abboff, hdrlen, nxthdr; 1799*7c478bd9Sstevel@tonic-gate Dwarf_Half vers, addrsz; 1800*7c478bd9Sstevel@tonic-gate Dwarf_Die cu, child; 1801*7c478bd9Sstevel@tonic-gate dwarf_t dw; 1802*7c478bd9Sstevel@tonic-gate char *prod = NULL; 1803*7c478bd9Sstevel@tonic-gate int rc; 1804*7c478bd9Sstevel@tonic-gate 1805*7c478bd9Sstevel@tonic-gate bzero(&dw, sizeof (dwarf_t)); 1806*7c478bd9Sstevel@tonic-gate dw.dw_td = td; 1807*7c478bd9Sstevel@tonic-gate dw.dw_ptrsz = elf_ptrsz(elf); 1808*7c478bd9Sstevel@tonic-gate dw.dw_mfgtid_last = TID_MFGTID_BASE; 1809*7c478bd9Sstevel@tonic-gate dw.dw_tidhash = hash_new(TDESC_HASH_BUCKETS, tdesc_idhash, tdesc_idcmp); 1810*7c478bd9Sstevel@tonic-gate dw.dw_fwdhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash, 1811*7c478bd9Sstevel@tonic-gate tdesc_namecmp); 1812*7c478bd9Sstevel@tonic-gate dw.dw_enumhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash, 1813*7c478bd9Sstevel@tonic-gate tdesc_namecmp); 1814*7c478bd9Sstevel@tonic-gate 1815*7c478bd9Sstevel@tonic-gate if ((rc = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dw.dw_dw, 1816*7c478bd9Sstevel@tonic-gate &dw.dw_err)) == DW_DLV_NO_ENTRY) { 1817*7c478bd9Sstevel@tonic-gate errno = ENOENT; 1818*7c478bd9Sstevel@tonic-gate return (-1); 1819*7c478bd9Sstevel@tonic-gate } else if (rc != DW_DLV_OK) { 1820*7c478bd9Sstevel@tonic-gate if (dwarf_errno(dw.dw_err) == DW_DLE_DEBUG_INFO_NULL) { 1821*7c478bd9Sstevel@tonic-gate /* 1822*7c478bd9Sstevel@tonic-gate * There's no type data in the DWARF section, but 1823*7c478bd9Sstevel@tonic-gate * libdwarf is too clever to handle that properly. 1824*7c478bd9Sstevel@tonic-gate */ 1825*7c478bd9Sstevel@tonic-gate return (0); 1826*7c478bd9Sstevel@tonic-gate } 1827*7c478bd9Sstevel@tonic-gate 1828*7c478bd9Sstevel@tonic-gate terminate("failed to initialize DWARF: %s\n", 1829*7c478bd9Sstevel@tonic-gate dwarf_errmsg(dw.dw_err)); 1830*7c478bd9Sstevel@tonic-gate } 1831*7c478bd9Sstevel@tonic-gate 1832*7c478bd9Sstevel@tonic-gate if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff, 1833*7c478bd9Sstevel@tonic-gate &addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_OK || 1834*7c478bd9Sstevel@tonic-gate (cu = die_sibling(&dw, NULL)) == NULL || 1835*7c478bd9Sstevel@tonic-gate (child = die_child(&dw, cu)) == NULL) 1836*7c478bd9Sstevel@tonic-gate terminate("file does not contain dwarf type data " 1837*7c478bd9Sstevel@tonic-gate "(try compiling with -g)\n"); 1838*7c478bd9Sstevel@tonic-gate 1839*7c478bd9Sstevel@tonic-gate dw.dw_maxoff = nxthdr - 1; 1840*7c478bd9Sstevel@tonic-gate 1841*7c478bd9Sstevel@tonic-gate if (dw.dw_maxoff > TID_FILEMAX) 1842*7c478bd9Sstevel@tonic-gate terminate("file contains too many types\n"); 1843*7c478bd9Sstevel@tonic-gate 1844*7c478bd9Sstevel@tonic-gate debug(1, "DWARF version: %d\n", vers); 1845*7c478bd9Sstevel@tonic-gate if (vers != DWARF_VERSION) { 1846*7c478bd9Sstevel@tonic-gate terminate("file contains incompatible version %d DWARF code " 1847*7c478bd9Sstevel@tonic-gate "(version 2 required)\n", vers); 1848*7c478bd9Sstevel@tonic-gate } 1849*7c478bd9Sstevel@tonic-gate 1850*7c478bd9Sstevel@tonic-gate if (die_string(&dw, cu, DW_AT_producer, &prod, 0)) { 1851*7c478bd9Sstevel@tonic-gate debug(1, "DWARF emitter: %s\n", prod); 1852*7c478bd9Sstevel@tonic-gate free(prod); 1853*7c478bd9Sstevel@tonic-gate } 1854*7c478bd9Sstevel@tonic-gate 1855*7c478bd9Sstevel@tonic-gate if ((dw.dw_cuname = die_name(&dw, cu)) != NULL) { 1856*7c478bd9Sstevel@tonic-gate char *base = xstrdup(basename(dw.dw_cuname)); 1857*7c478bd9Sstevel@tonic-gate free(dw.dw_cuname); 1858*7c478bd9Sstevel@tonic-gate dw.dw_cuname = base; 1859*7c478bd9Sstevel@tonic-gate 1860*7c478bd9Sstevel@tonic-gate debug(1, "CU name: %s\n", dw.dw_cuname); 1861*7c478bd9Sstevel@tonic-gate } 1862*7c478bd9Sstevel@tonic-gate 1863*7c478bd9Sstevel@tonic-gate die_create(&dw, child); 1864*7c478bd9Sstevel@tonic-gate 1865*7c478bd9Sstevel@tonic-gate if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff, 1866*7c478bd9Sstevel@tonic-gate &addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_NO_ENTRY) 1867*7c478bd9Sstevel@tonic-gate terminate("multiple compilation units not supported\n"); 1868*7c478bd9Sstevel@tonic-gate 1869*7c478bd9Sstevel@tonic-gate (void) dwarf_finish(dw.dw_dw, &dw.dw_err); 1870*7c478bd9Sstevel@tonic-gate 1871*7c478bd9Sstevel@tonic-gate die_resolve(&dw); 1872*7c478bd9Sstevel@tonic-gate 1873*7c478bd9Sstevel@tonic-gate /* leak the dwarf_t */ 1874*7c478bd9Sstevel@tonic-gate 1875*7c478bd9Sstevel@tonic-gate return (0); 1876*7c478bd9Sstevel@tonic-gate } 1877