17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 54d232658Sjohnlev * Common Development and Distribution License (the "License"). 64d232658Sjohnlev * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22ae115bc7Smrj * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 2509d1f807SJason King /* 2609d1f807SJason King * Copyright 2012 Jason King. All rights reserved. 2709d1f807SJason King * Use is subject to license terms. 2809d1f807SJason King */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * DWARF to tdata conversion 327c478bd9Sstevel@tonic-gate * 337c478bd9Sstevel@tonic-gate * For the most part, conversion is straightforward, proceeding in two passes. 347c478bd9Sstevel@tonic-gate * On the first pass, we iterate through every die, creating new type nodes as 357c478bd9Sstevel@tonic-gate * necessary. Referenced tdesc_t's are created in an uninitialized state, thus 367c478bd9Sstevel@tonic-gate * allowing type reference pointers to be filled in. If the tdesc_t 377c478bd9Sstevel@tonic-gate * corresponding to a given die can be completely filled out (sizes and offsets 387c478bd9Sstevel@tonic-gate * calculated, and so forth) without using any referenced types, the tdesc_t is 397c478bd9Sstevel@tonic-gate * marked as resolved. Consider an array type. If the type corresponding to 407c478bd9Sstevel@tonic-gate * the array contents has not yet been processed, we will create a blank tdesc 417c478bd9Sstevel@tonic-gate * for the contents type (only the type ID will be filled in, relying upon the 427c478bd9Sstevel@tonic-gate * later portion of the first pass to encounter and complete the referenced 437c478bd9Sstevel@tonic-gate * type). We will then attempt to determine the size of the array. If the 447c478bd9Sstevel@tonic-gate * array has a byte size attribute, we will have completely characterized the 457c478bd9Sstevel@tonic-gate * array type, and will be able to mark it as resolved. The lack of a byte 467c478bd9Sstevel@tonic-gate * size attribute, on the other hand, will prevent us from fully resolving the 477c478bd9Sstevel@tonic-gate * type, as the size will only be calculable with reference to the contents 487c478bd9Sstevel@tonic-gate * type, which has not, as yet, been encountered. The array type will thus be 497c478bd9Sstevel@tonic-gate * left without the resolved flag, and the first pass will continue. 507c478bd9Sstevel@tonic-gate * 517c478bd9Sstevel@tonic-gate * When we begin the second pass, we will have created tdesc_t nodes for every 527c478bd9Sstevel@tonic-gate * type in the section. We will traverse the tree, from the iidescs down, 537c478bd9Sstevel@tonic-gate * processing each unresolved node. As the referenced nodes will have been 547c478bd9Sstevel@tonic-gate * populated, the array type used in our example above will be able to use the 557c478bd9Sstevel@tonic-gate * size of the referenced types (if available) to determine its own type. The 567c478bd9Sstevel@tonic-gate * traversal will be repeated until all types have been resolved or we have 577c478bd9Sstevel@tonic-gate * failed to make progress. When all tdescs have been resolved, the conversion 587c478bd9Sstevel@tonic-gate * is complete. 597c478bd9Sstevel@tonic-gate * 607c478bd9Sstevel@tonic-gate * There are, as always, a few special cases that are handled during the first 617c478bd9Sstevel@tonic-gate * and second passes: 627c478bd9Sstevel@tonic-gate * 637c478bd9Sstevel@tonic-gate * 1. Empty enums - GCC will occasionally emit an enum without any members. 647c478bd9Sstevel@tonic-gate * Later on in the file, it will emit the same enum type, though this time 657c478bd9Sstevel@tonic-gate * with the full complement of members. All references to the memberless 667c478bd9Sstevel@tonic-gate * enum need to be redirected to the full definition. During the first 677c478bd9Sstevel@tonic-gate * pass, each enum is entered in dm_enumhash, along with a pointer to its 687c478bd9Sstevel@tonic-gate * corresponding tdesc_t. If, during the second pass, we encounter a 697c478bd9Sstevel@tonic-gate * memberless enum, we use the hash to locate the full definition. All 707c478bd9Sstevel@tonic-gate * tdescs referencing the empty enum are then redirected. 717c478bd9Sstevel@tonic-gate * 727c478bd9Sstevel@tonic-gate * 2. Forward declarations - If the compiler sees a forward declaration for 737c478bd9Sstevel@tonic-gate * a structure, followed by the definition of that structure, it will emit 747c478bd9Sstevel@tonic-gate * DWARF data for both the forward declaration and the definition. We need 757c478bd9Sstevel@tonic-gate * to resolve the forward declarations when possible, by redirecting 767c478bd9Sstevel@tonic-gate * forward-referencing tdescs to the actual struct/union definitions. This 777c478bd9Sstevel@tonic-gate * redirection is done completely within the first pass. We begin by 787c478bd9Sstevel@tonic-gate * recording all forward declarations in dw_fwdhash. When we define a 797c478bd9Sstevel@tonic-gate * structure, we check to see if there have been any corresponding forward 807c478bd9Sstevel@tonic-gate * declarations. If so, we redirect the tdescs which referenced the forward 817c478bd9Sstevel@tonic-gate * declarations to the structure or union definition. 827c478bd9Sstevel@tonic-gate * 837c478bd9Sstevel@tonic-gate * XXX see if a post traverser will allow the elimination of repeated pass 2 847c478bd9Sstevel@tonic-gate * traversals. 857c478bd9Sstevel@tonic-gate */ 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate #include <stdio.h> 887c478bd9Sstevel@tonic-gate #include <stdlib.h> 897c478bd9Sstevel@tonic-gate #include <strings.h> 907c478bd9Sstevel@tonic-gate #include <errno.h> 917c478bd9Sstevel@tonic-gate #include <libelf.h> 927c478bd9Sstevel@tonic-gate #include <libdwarf.h> 937c478bd9Sstevel@tonic-gate #include <libgen.h> 947c478bd9Sstevel@tonic-gate #include <dwarf.h> 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate #include "ctf_headers.h" 977c478bd9Sstevel@tonic-gate #include "ctftools.h" 987c478bd9Sstevel@tonic-gate #include "memory.h" 997c478bd9Sstevel@tonic-gate #include "list.h" 1007c478bd9Sstevel@tonic-gate #include "traverse.h" 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate /* The version of DWARF which we support. */ 1037c478bd9Sstevel@tonic-gate #define DWARF_VERSION 2 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * We need to define a couple of our own intrinsics, to smooth out some of the 1077c478bd9Sstevel@tonic-gate * differences between the GCC and DevPro DWARF emitters. See the referenced 1087c478bd9Sstevel@tonic-gate * routines and the special cases in the file comment for more details. 1097c478bd9Sstevel@tonic-gate * 1107c478bd9Sstevel@tonic-gate * Type IDs are 32 bits wide. We're going to use the top of that field to 1117c478bd9Sstevel@tonic-gate * indicate types that we've created ourselves. 1127c478bd9Sstevel@tonic-gate */ 1137c478bd9Sstevel@tonic-gate #define TID_FILEMAX 0x3fffffff /* highest tid from file */ 1147c478bd9Sstevel@tonic-gate #define TID_VOID 0x40000001 /* see die_void() */ 1157c478bd9Sstevel@tonic-gate #define TID_LONG 0x40000002 /* see die_array() */ 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate #define TID_MFGTID_BASE 0x40000003 /* first mfg'd tid */ 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* 1207c478bd9Sstevel@tonic-gate * To reduce the staggering amount of error-handling code that would otherwise 1217c478bd9Sstevel@tonic-gate * be required, the attribute-retrieval routines handle most of their own 1227c478bd9Sstevel@tonic-gate * errors. If the following flag is supplied as the value of the `req' 1237c478bd9Sstevel@tonic-gate * argument, they will also handle the absence of a requested attribute by 1247c478bd9Sstevel@tonic-gate * terminating the program. 1257c478bd9Sstevel@tonic-gate */ 1267c478bd9Sstevel@tonic-gate #define DW_ATTR_REQ 1 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate #define TDESC_HASH_BUCKETS 511 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate typedef struct dwarf { 1317c478bd9Sstevel@tonic-gate Dwarf_Debug dw_dw; /* for libdwarf */ 1327c478bd9Sstevel@tonic-gate Dwarf_Error dw_err; /* for libdwarf */ 1337c478bd9Sstevel@tonic-gate Dwarf_Unsigned dw_maxoff; /* highest legal offset in this cu */ 1347c478bd9Sstevel@tonic-gate tdata_t *dw_td; /* root of the tdesc/iidesc tree */ 1357c478bd9Sstevel@tonic-gate hash_t *dw_tidhash; /* hash of tdescs by t_id */ 1367c478bd9Sstevel@tonic-gate hash_t *dw_fwdhash; /* hash of fwd decls by name */ 1377c478bd9Sstevel@tonic-gate hash_t *dw_enumhash; /* hash of memberless enums by name */ 1387c478bd9Sstevel@tonic-gate tdesc_t *dw_void; /* manufactured void type */ 1397c478bd9Sstevel@tonic-gate tdesc_t *dw_long; /* manufactured long type for arrays */ 1407c478bd9Sstevel@tonic-gate size_t dw_ptrsz; /* size of a pointer in this file */ 1417c478bd9Sstevel@tonic-gate tid_t dw_mfgtid_last; /* last mfg'd type ID used */ 1427c478bd9Sstevel@tonic-gate uint_t dw_nunres; /* count of unresolved types */ 1437c478bd9Sstevel@tonic-gate char *dw_cuname; /* name of compilation unit */ 1447c478bd9Sstevel@tonic-gate } dwarf_t; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate static void die_create_one(dwarf_t *, Dwarf_Die); 1477c478bd9Sstevel@tonic-gate static void die_create(dwarf_t *, Dwarf_Die); 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate static tid_t 1507c478bd9Sstevel@tonic-gate mfgtid_next(dwarf_t *dw) 1517c478bd9Sstevel@tonic-gate { 1527c478bd9Sstevel@tonic-gate return (++dw->dw_mfgtid_last); 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate static void 1567c478bd9Sstevel@tonic-gate tdesc_add(dwarf_t *dw, tdesc_t *tdp) 1577c478bd9Sstevel@tonic-gate { 1587c478bd9Sstevel@tonic-gate hash_add(dw->dw_tidhash, tdp); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate static tdesc_t * 1627c478bd9Sstevel@tonic-gate tdesc_lookup(dwarf_t *dw, int tid) 1637c478bd9Sstevel@tonic-gate { 1647c478bd9Sstevel@tonic-gate tdesc_t tmpl, *tdp; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate tmpl.t_id = tid; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate if (hash_find(dw->dw_tidhash, &tmpl, (void **)&tdp)) 1697c478bd9Sstevel@tonic-gate return (tdp); 1707c478bd9Sstevel@tonic-gate else 1717c478bd9Sstevel@tonic-gate return (NULL); 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate /* 1757c478bd9Sstevel@tonic-gate * Resolve a tdesc down to a node which should have a size. Returns the size, 1767c478bd9Sstevel@tonic-gate * zero if the size hasn't yet been determined. 1777c478bd9Sstevel@tonic-gate */ 1787c478bd9Sstevel@tonic-gate static size_t 1797c478bd9Sstevel@tonic-gate tdesc_size(tdesc_t *tdp) 1807c478bd9Sstevel@tonic-gate { 1817c478bd9Sstevel@tonic-gate for (;;) { 1827c478bd9Sstevel@tonic-gate switch (tdp->t_type) { 1837c478bd9Sstevel@tonic-gate case INTRINSIC: 1847c478bd9Sstevel@tonic-gate case POINTER: 1857c478bd9Sstevel@tonic-gate case ARRAY: 1867c478bd9Sstevel@tonic-gate case FUNCTION: 1877c478bd9Sstevel@tonic-gate case STRUCT: 1887c478bd9Sstevel@tonic-gate case UNION: 1897c478bd9Sstevel@tonic-gate case ENUM: 1907c478bd9Sstevel@tonic-gate return (tdp->t_size); 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate case FORWARD: 1937c478bd9Sstevel@tonic-gate return (0); 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate case TYPEDEF: 1967c478bd9Sstevel@tonic-gate case VOLATILE: 1977c478bd9Sstevel@tonic-gate case CONST: 1987c478bd9Sstevel@tonic-gate case RESTRICT: 1997c478bd9Sstevel@tonic-gate tdp = tdp->t_tdesc; 2007c478bd9Sstevel@tonic-gate continue; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate case 0: /* not yet defined */ 2037c478bd9Sstevel@tonic-gate return (0); 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate default: 2067c478bd9Sstevel@tonic-gate terminate("tdp %u: tdesc_size on unknown type %d\n", 2077c478bd9Sstevel@tonic-gate tdp->t_id, tdp->t_type); 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate static size_t 2137c478bd9Sstevel@tonic-gate tdesc_bitsize(tdesc_t *tdp) 2147c478bd9Sstevel@tonic-gate { 2157c478bd9Sstevel@tonic-gate for (;;) { 2167c478bd9Sstevel@tonic-gate switch (tdp->t_type) { 2177c478bd9Sstevel@tonic-gate case INTRINSIC: 2187c478bd9Sstevel@tonic-gate return (tdp->t_intr->intr_nbits); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate case ARRAY: 2217c478bd9Sstevel@tonic-gate case FUNCTION: 2227c478bd9Sstevel@tonic-gate case STRUCT: 2237c478bd9Sstevel@tonic-gate case UNION: 2247c478bd9Sstevel@tonic-gate case ENUM: 2257c478bd9Sstevel@tonic-gate case POINTER: 226626fe1bfSsethg return (tdp->t_size * NBBY); 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate case FORWARD: 2297c478bd9Sstevel@tonic-gate return (0); 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate case TYPEDEF: 2327c478bd9Sstevel@tonic-gate case VOLATILE: 2337c478bd9Sstevel@tonic-gate case RESTRICT: 2347c478bd9Sstevel@tonic-gate case CONST: 2357c478bd9Sstevel@tonic-gate tdp = tdp->t_tdesc; 2367c478bd9Sstevel@tonic-gate continue; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate case 0: /* not yet defined */ 2397c478bd9Sstevel@tonic-gate return (0); 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate default: 2427c478bd9Sstevel@tonic-gate terminate("tdp %u: tdesc_bitsize on unknown type %d\n", 2437c478bd9Sstevel@tonic-gate tdp->t_id, tdp->t_type); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate static tdesc_t * 2497c478bd9Sstevel@tonic-gate tdesc_basetype(tdesc_t *tdp) 2507c478bd9Sstevel@tonic-gate { 2517c478bd9Sstevel@tonic-gate for (;;) { 2527c478bd9Sstevel@tonic-gate switch (tdp->t_type) { 2537c478bd9Sstevel@tonic-gate case TYPEDEF: 2547c478bd9Sstevel@tonic-gate case VOLATILE: 2557c478bd9Sstevel@tonic-gate case RESTRICT: 2567c478bd9Sstevel@tonic-gate case CONST: 2577c478bd9Sstevel@tonic-gate tdp = tdp->t_tdesc; 2587c478bd9Sstevel@tonic-gate break; 2597c478bd9Sstevel@tonic-gate case 0: /* not yet defined */ 2607c478bd9Sstevel@tonic-gate return (NULL); 2617c478bd9Sstevel@tonic-gate default: 2627c478bd9Sstevel@tonic-gate return (tdp); 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate static Dwarf_Off 2687c478bd9Sstevel@tonic-gate die_off(dwarf_t *dw, Dwarf_Die die) 2697c478bd9Sstevel@tonic-gate { 2707c478bd9Sstevel@tonic-gate Dwarf_Off off; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate if (dwarf_dieoffset(die, &off, &dw->dw_err) == DW_DLV_OK) 2737c478bd9Sstevel@tonic-gate return (off); 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate terminate("failed to get offset for die: %s\n", 2767c478bd9Sstevel@tonic-gate dwarf_errmsg(dw->dw_err)); 2777c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2787c478bd9Sstevel@tonic-gate return (0); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate static Dwarf_Die 2827c478bd9Sstevel@tonic-gate die_sibling(dwarf_t *dw, Dwarf_Die die) 2837c478bd9Sstevel@tonic-gate { 2847c478bd9Sstevel@tonic-gate Dwarf_Die sib; 2857c478bd9Sstevel@tonic-gate int rc; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate if ((rc = dwarf_siblingof(dw->dw_dw, die, &sib, &dw->dw_err)) == 2887c478bd9Sstevel@tonic-gate DW_DLV_OK) 2897c478bd9Sstevel@tonic-gate return (sib); 2907c478bd9Sstevel@tonic-gate else if (rc == DW_DLV_NO_ENTRY) 2917c478bd9Sstevel@tonic-gate return (NULL); 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate terminate("die %llu: failed to find type sibling: %s\n", 2947c478bd9Sstevel@tonic-gate die_off(dw, die), dwarf_errmsg(dw->dw_err)); 2957c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2967c478bd9Sstevel@tonic-gate return (NULL); 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate static Dwarf_Die 3007c478bd9Sstevel@tonic-gate die_child(dwarf_t *dw, Dwarf_Die die) 3017c478bd9Sstevel@tonic-gate { 3027c478bd9Sstevel@tonic-gate Dwarf_Die child; 3037c478bd9Sstevel@tonic-gate int rc; 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate if ((rc = dwarf_child(die, &child, &dw->dw_err)) == DW_DLV_OK) 3067c478bd9Sstevel@tonic-gate return (child); 3077c478bd9Sstevel@tonic-gate else if (rc == DW_DLV_NO_ENTRY) 3087c478bd9Sstevel@tonic-gate return (NULL); 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate terminate("die %llu: failed to find type child: %s\n", 3117c478bd9Sstevel@tonic-gate die_off(dw, die), dwarf_errmsg(dw->dw_err)); 3127c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3137c478bd9Sstevel@tonic-gate return (NULL); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate static Dwarf_Half 3177c478bd9Sstevel@tonic-gate die_tag(dwarf_t *dw, Dwarf_Die die) 3187c478bd9Sstevel@tonic-gate { 3197c478bd9Sstevel@tonic-gate Dwarf_Half tag; 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate if (dwarf_tag(die, &tag, &dw->dw_err) == DW_DLV_OK) 3227c478bd9Sstevel@tonic-gate return (tag); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get tag for type: %s\n", 3257c478bd9Sstevel@tonic-gate die_off(dw, die), dwarf_errmsg(dw->dw_err)); 3267c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3277c478bd9Sstevel@tonic-gate return (0); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate static Dwarf_Attribute 3317c478bd9Sstevel@tonic-gate die_attr(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, int req) 3327c478bd9Sstevel@tonic-gate { 3337c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 3347c478bd9Sstevel@tonic-gate int rc; 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate if ((rc = dwarf_attr(die, name, &attr, &dw->dw_err)) == DW_DLV_OK) { 3377c478bd9Sstevel@tonic-gate return (attr); 3387c478bd9Sstevel@tonic-gate } else if (rc == DW_DLV_NO_ENTRY) { 3397c478bd9Sstevel@tonic-gate if (req) { 3407c478bd9Sstevel@tonic-gate terminate("die %llu: no attr 0x%x\n", die_off(dw, die), 3417c478bd9Sstevel@tonic-gate name); 3427c478bd9Sstevel@tonic-gate } else { 3437c478bd9Sstevel@tonic-gate return (NULL); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get attribute for type: %s\n", 3487c478bd9Sstevel@tonic-gate die_off(dw, die), dwarf_errmsg(dw->dw_err)); 3497c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3507c478bd9Sstevel@tonic-gate return (NULL); 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate static Dwarf_Half 3547c478bd9Sstevel@tonic-gate die_attr_form(dwarf_t *dw, Dwarf_Attribute attr) 3557c478bd9Sstevel@tonic-gate { 3567c478bd9Sstevel@tonic-gate Dwarf_Half form; 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate if (dwarf_whatform(attr, &form, &dw->dw_err) == DW_DLV_OK) 3597c478bd9Sstevel@tonic-gate return (form); 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate terminate("failed to get attribute form for type: %s\n", 3627c478bd9Sstevel@tonic-gate dwarf_errmsg(dw->dw_err)); 3637c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3647c478bd9Sstevel@tonic-gate return (0); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 36709d1f807SJason King /* 36809d1f807SJason King * the following functions lookup the value of an attribute in a DIE: 36909d1f807SJason King * 37009d1f807SJason King * die_signed 37109d1f807SJason King * die_unsigned 37209d1f807SJason King * die_bool 37309d1f807SJason King * die_string 37409d1f807SJason King * 37509d1f807SJason King * They all take the same parameters (with the exception of valp which is 37609d1f807SJason King * a pointer to the type of the attribute we are looking up): 37709d1f807SJason King * 37809d1f807SJason King * dw - the dwarf object to look in 37909d1f807SJason King * die - the DIE we're interested in 38009d1f807SJason King * name - the name of the attribute to lookup 38109d1f807SJason King * valp - pointer to where the value of the attribute is placed 38209d1f807SJason King * req - if the value is required (0 / non-zero) 38309d1f807SJason King * 38409d1f807SJason King * If the attribute is not found, one of the following happens: 38509d1f807SJason King * - program terminates (req is non-zero) 38609d1f807SJason King * - function returns 0 38709d1f807SJason King * 38809d1f807SJason King * If the value is found, and in a form (class) we can handle, the function 38909d1f807SJason King * returns 1. 39009d1f807SJason King * 39109d1f807SJason King * Currently, we can only handle attribute values that are stored as 39209d1f807SJason King * constants (immediate value). If an attribute has a form we cannot 39309d1f807SJason King * handle (for example VLAs may store the dimensions of the array 39409d1f807SJason King * as a DWARF expression that can compute it at runtime by reading 39509d1f807SJason King * values off the stack or other locations in memory), it is treated 39609d1f807SJason King * the same as if the attribute does not exist. 39709d1f807SJason King */ 3987c478bd9Sstevel@tonic-gate static int 3997c478bd9Sstevel@tonic-gate die_signed(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Signed *valp, 4007c478bd9Sstevel@tonic-gate int req) 4017c478bd9Sstevel@tonic-gate { 4027c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 4037c478bd9Sstevel@tonic-gate Dwarf_Signed val; 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 4067c478bd9Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate if (dwarf_formsdata(attr, &val, &dw->dw_err) != DW_DLV_OK) { 40909d1f807SJason King if (req == 0) 41009d1f807SJason King return (0); 41109d1f807SJason King 4127c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get signed (form 0x%x)\n", 4137c478bd9Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate *valp = val; 4197c478bd9Sstevel@tonic-gate return (1); 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate static int 4237c478bd9Sstevel@tonic-gate die_unsigned(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Unsigned *valp, 4247c478bd9Sstevel@tonic-gate int req) 4257c478bd9Sstevel@tonic-gate { 4267c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 4277c478bd9Sstevel@tonic-gate Dwarf_Unsigned val; 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 4307c478bd9Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate if (dwarf_formudata(attr, &val, &dw->dw_err) != DW_DLV_OK) { 43309d1f807SJason King if (req == 0) 43409d1f807SJason King return (0); 43509d1f807SJason King 4367c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get unsigned (form 0x%x)\n", 4377c478bd9Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate *valp = val; 4437c478bd9Sstevel@tonic-gate return (1); 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate static int 4477c478bd9Sstevel@tonic-gate die_bool(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Bool *valp, int req) 4487c478bd9Sstevel@tonic-gate { 4497c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 4507c478bd9Sstevel@tonic-gate Dwarf_Bool val; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 4537c478bd9Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate if (dwarf_formflag(attr, &val, &dw->dw_err) != DW_DLV_OK) { 45609d1f807SJason King if (req == 0) 45709d1f807SJason King return (0); 45809d1f807SJason King 4597c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get bool (form 0x%x)\n", 4607c478bd9Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate *valp = val; 4667c478bd9Sstevel@tonic-gate return (1); 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate static int 4707c478bd9Sstevel@tonic-gate die_string(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, char **strp, int req) 4717c478bd9Sstevel@tonic-gate { 4727c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 4737c478bd9Sstevel@tonic-gate char *str; 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 4767c478bd9Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate if (dwarf_formstring(attr, &str, &dw->dw_err) != DW_DLV_OK) { 47909d1f807SJason King if (req == 0) 48009d1f807SJason King return (0); 48109d1f807SJason King 4827c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get string (form 0x%x)\n", 4837c478bd9Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate *strp = xstrdup(str); 4877c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, str, DW_DLA_STRING); 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate return (1); 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate static Dwarf_Off 4937c478bd9Sstevel@tonic-gate die_attr_ref(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name) 4947c478bd9Sstevel@tonic-gate { 4957c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 4967c478bd9Sstevel@tonic-gate Dwarf_Off off; 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate attr = die_attr(dw, die, name, DW_ATTR_REQ); 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate if (dwarf_formref(attr, &off, &dw->dw_err) != DW_DLV_OK) { 5017c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get ref (form 0x%x)\n", 5027c478bd9Sstevel@tonic-gate die_off(dw, die), die_attr_form(dw, attr)); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate return (off); 5087c478bd9Sstevel@tonic-gate } 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate static char * 5117c478bd9Sstevel@tonic-gate die_name(dwarf_t *dw, Dwarf_Die die) 5127c478bd9Sstevel@tonic-gate { 5137c478bd9Sstevel@tonic-gate char *str = NULL; 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate (void) die_string(dw, die, DW_AT_name, &str, 0); 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate return (str); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate static int 5217c478bd9Sstevel@tonic-gate die_isdecl(dwarf_t *dw, Dwarf_Die die) 5227c478bd9Sstevel@tonic-gate { 5237c478bd9Sstevel@tonic-gate Dwarf_Bool val; 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate return (die_bool(dw, die, DW_AT_declaration, &val, 0) && val); 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate static int 5297c478bd9Sstevel@tonic-gate die_isglobal(dwarf_t *dw, Dwarf_Die die) 5307c478bd9Sstevel@tonic-gate { 5317c478bd9Sstevel@tonic-gate Dwarf_Signed vis; 5327c478bd9Sstevel@tonic-gate Dwarf_Bool ext; 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate /* 5357c478bd9Sstevel@tonic-gate * Some compilers (gcc) use DW_AT_external to indicate function 5367c478bd9Sstevel@tonic-gate * visibility. Others (Sun) use DW_AT_visibility. 5377c478bd9Sstevel@tonic-gate */ 5387c478bd9Sstevel@tonic-gate if (die_signed(dw, die, DW_AT_visibility, &vis, 0)) 5397c478bd9Sstevel@tonic-gate return (vis == DW_VIS_exported); 5407c478bd9Sstevel@tonic-gate else 5417c478bd9Sstevel@tonic-gate return (die_bool(dw, die, DW_AT_external, &ext, 0) && ext); 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate static tdesc_t * 5457c478bd9Sstevel@tonic-gate die_add(dwarf_t *dw, Dwarf_Off off) 5467c478bd9Sstevel@tonic-gate { 5477c478bd9Sstevel@tonic-gate tdesc_t *tdp = xcalloc(sizeof (tdesc_t)); 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate tdp->t_id = off; 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate tdesc_add(dw, tdp); 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate return (tdp); 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate static tdesc_t * 5577c478bd9Sstevel@tonic-gate die_lookup_pass1(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name) 5587c478bd9Sstevel@tonic-gate { 5597c478bd9Sstevel@tonic-gate Dwarf_Off ref = die_attr_ref(dw, die, name); 5607c478bd9Sstevel@tonic-gate tdesc_t *tdp; 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate if ((tdp = tdesc_lookup(dw, ref)) != NULL) 5637c478bd9Sstevel@tonic-gate return (tdp); 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate return (die_add(dw, ref)); 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate static int 5697c478bd9Sstevel@tonic-gate die_mem_offset(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, 5707c478bd9Sstevel@tonic-gate Dwarf_Unsigned *valp, int req) 5717c478bd9Sstevel@tonic-gate { 5727c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 5737c478bd9Sstevel@tonic-gate Dwarf_Locdesc *loc; 5747c478bd9Sstevel@tonic-gate Dwarf_Signed locnum; 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, name, req)) == NULL) 5777c478bd9Sstevel@tonic-gate return (0); /* die_attr will terminate for us if necessary */ 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate if (dwarf_loclist(attr, &loc, &locnum, &dw->dw_err) != DW_DLV_OK) { 5807c478bd9Sstevel@tonic-gate terminate("die %llu: failed to get mem offset location list\n", 5817c478bd9Sstevel@tonic-gate die_off(dw, die)); 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) { 5877c478bd9Sstevel@tonic-gate terminate("die %llu: cannot parse member offset\n", 5887c478bd9Sstevel@tonic-gate die_off(dw, die)); 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate *valp = loc->ld_s->lr_number; 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, loc->ld_s, DW_DLA_LOC_BLOCK); 5947c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, loc, DW_DLA_LOCDESC); 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate return (1); 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate static tdesc_t * 6007c478bd9Sstevel@tonic-gate tdesc_intr_common(dwarf_t *dw, int tid, const char *name, size_t sz) 6017c478bd9Sstevel@tonic-gate { 6027c478bd9Sstevel@tonic-gate tdesc_t *tdp; 6037c478bd9Sstevel@tonic-gate intr_t *intr; 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate intr = xcalloc(sizeof (intr_t)); 6067c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 6077c478bd9Sstevel@tonic-gate intr->intr_signed = 1; 6087c478bd9Sstevel@tonic-gate intr->intr_nbits = sz * NBBY; 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate tdp = xcalloc(sizeof (tdesc_t)); 6117c478bd9Sstevel@tonic-gate tdp->t_name = xstrdup(name); 6127c478bd9Sstevel@tonic-gate tdp->t_size = sz; 6137c478bd9Sstevel@tonic-gate tdp->t_id = tid; 6147c478bd9Sstevel@tonic-gate tdp->t_type = INTRINSIC; 6157c478bd9Sstevel@tonic-gate tdp->t_intr = intr; 6167c478bd9Sstevel@tonic-gate tdp->t_flags = TDESC_F_RESOLVED; 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate tdesc_add(dw, tdp); 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate return (tdp); 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate /* 6247c478bd9Sstevel@tonic-gate * Manufacture a void type. Used for gcc-emitted stabs, where the lack of a 6257c478bd9Sstevel@tonic-gate * type reference implies a reference to a void type. A void *, for example 6267c478bd9Sstevel@tonic-gate * will be represented by a pointer die without a DW_AT_type. CTF requires 6277c478bd9Sstevel@tonic-gate * that pointer nodes point to something, so we'll create a void for use as 6287c478bd9Sstevel@tonic-gate * the target. Note that the DWARF data may already create a void type. Ours 6297c478bd9Sstevel@tonic-gate * would then be a duplicate, but it'll be removed in the self-uniquification 6307c478bd9Sstevel@tonic-gate * merge performed at the completion of DWARF->tdesc conversion. 6317c478bd9Sstevel@tonic-gate */ 6327c478bd9Sstevel@tonic-gate static tdesc_t * 6337c478bd9Sstevel@tonic-gate tdesc_intr_void(dwarf_t *dw) 6347c478bd9Sstevel@tonic-gate { 6357c478bd9Sstevel@tonic-gate if (dw->dw_void == NULL) 6367c478bd9Sstevel@tonic-gate dw->dw_void = tdesc_intr_common(dw, TID_VOID, "void", 0); 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate return (dw->dw_void); 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate static tdesc_t * 6427c478bd9Sstevel@tonic-gate tdesc_intr_long(dwarf_t *dw) 6437c478bd9Sstevel@tonic-gate { 6447c478bd9Sstevel@tonic-gate if (dw->dw_long == NULL) { 6457c478bd9Sstevel@tonic-gate dw->dw_long = tdesc_intr_common(dw, TID_LONG, "long", 6467c478bd9Sstevel@tonic-gate dw->dw_ptrsz); 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate return (dw->dw_long); 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate /* 6537c478bd9Sstevel@tonic-gate * Used for creating bitfield types. We create a copy of an existing intrinsic, 6547c478bd9Sstevel@tonic-gate * adjusting the size of the copy to match what the caller requested. The 6557c478bd9Sstevel@tonic-gate * caller can then use the copy as the type for a bitfield structure member. 6567c478bd9Sstevel@tonic-gate */ 6577c478bd9Sstevel@tonic-gate static tdesc_t * 6587c478bd9Sstevel@tonic-gate tdesc_intr_clone(dwarf_t *dw, tdesc_t *old, size_t bitsz) 6597c478bd9Sstevel@tonic-gate { 6607c478bd9Sstevel@tonic-gate tdesc_t *new = xcalloc(sizeof (tdesc_t)); 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate if (!(old->t_flags & TDESC_F_RESOLVED)) { 6637c478bd9Sstevel@tonic-gate terminate("tdp %u: attempt to make a bit field from an " 6647c478bd9Sstevel@tonic-gate "unresolved type\n", old->t_id); 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate new->t_name = xstrdup(old->t_name); 6687c478bd9Sstevel@tonic-gate new->t_size = old->t_size; 6697c478bd9Sstevel@tonic-gate new->t_id = mfgtid_next(dw); 6707c478bd9Sstevel@tonic-gate new->t_type = INTRINSIC; 6717c478bd9Sstevel@tonic-gate new->t_flags = TDESC_F_RESOLVED; 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate new->t_intr = xcalloc(sizeof (intr_t)); 6747c478bd9Sstevel@tonic-gate bcopy(old->t_intr, new->t_intr, sizeof (intr_t)); 6757c478bd9Sstevel@tonic-gate new->t_intr->intr_nbits = bitsz; 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate tdesc_add(dw, new); 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate return (new); 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate static void 6837c478bd9Sstevel@tonic-gate tdesc_array_create(dwarf_t *dw, Dwarf_Die dim, tdesc_t *arrtdp, 6847c478bd9Sstevel@tonic-gate tdesc_t *dimtdp) 6857c478bd9Sstevel@tonic-gate { 6867c478bd9Sstevel@tonic-gate Dwarf_Unsigned uval; 6877c478bd9Sstevel@tonic-gate Dwarf_Signed sval; 6887c478bd9Sstevel@tonic-gate tdesc_t *ctdp; 6897c478bd9Sstevel@tonic-gate Dwarf_Die dim2; 6907c478bd9Sstevel@tonic-gate ardef_t *ar; 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate if ((dim2 = die_sibling(dw, dim)) == NULL) { 6937c478bd9Sstevel@tonic-gate ctdp = arrtdp; 6947c478bd9Sstevel@tonic-gate } else if (die_tag(dw, dim2) == DW_TAG_subrange_type) { 6957c478bd9Sstevel@tonic-gate ctdp = xcalloc(sizeof (tdesc_t)); 6967c478bd9Sstevel@tonic-gate ctdp->t_id = mfgtid_next(dw); 6977c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating new type %u for sub-dimension\n", 6987c478bd9Sstevel@tonic-gate die_off(dw, dim2), ctdp->t_id); 6997c478bd9Sstevel@tonic-gate tdesc_array_create(dw, dim2, arrtdp, ctdp); 7007c478bd9Sstevel@tonic-gate } else { 7017c478bd9Sstevel@tonic-gate terminate("die %llu: unexpected non-subrange node in array\n", 7027c478bd9Sstevel@tonic-gate die_off(dw, dim2)); 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate dimtdp->t_type = ARRAY; 7067c478bd9Sstevel@tonic-gate dimtdp->t_ardef = ar = xcalloc(sizeof (ardef_t)); 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate /* 7097c478bd9Sstevel@tonic-gate * Array bounds can be signed or unsigned, but there are several kinds 7107c478bd9Sstevel@tonic-gate * of signless forms (data1, data2, etc) that take their sign from the 7117c478bd9Sstevel@tonic-gate * routine that is trying to interpret them. That is, data1 can be 7127c478bd9Sstevel@tonic-gate * either signed or unsigned, depending on whether you use the signed or 7137c478bd9Sstevel@tonic-gate * unsigned accessor function. GCC will use the signless forms to store 7147c478bd9Sstevel@tonic-gate * unsigned values which have their high bit set, so we need to try to 7157c478bd9Sstevel@tonic-gate * read them first as unsigned to get positive values. We could also 7167c478bd9Sstevel@tonic-gate * try signed first, falling back to unsigned if we got a negative 7177c478bd9Sstevel@tonic-gate * value. 7187c478bd9Sstevel@tonic-gate */ 7197c478bd9Sstevel@tonic-gate if (die_unsigned(dw, dim, DW_AT_upper_bound, &uval, 0)) 7207c478bd9Sstevel@tonic-gate ar->ad_nelems = uval + 1; 7217c478bd9Sstevel@tonic-gate else if (die_signed(dw, dim, DW_AT_upper_bound, &sval, 0)) 7227c478bd9Sstevel@tonic-gate ar->ad_nelems = sval + 1; 7237c478bd9Sstevel@tonic-gate else 7247c478bd9Sstevel@tonic-gate ar->ad_nelems = 0; 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate /* 7277c478bd9Sstevel@tonic-gate * Different compilers use different index types. Force the type to be 7287c478bd9Sstevel@tonic-gate * a common, known value (long). 7297c478bd9Sstevel@tonic-gate */ 7307c478bd9Sstevel@tonic-gate ar->ad_idxtype = tdesc_intr_long(dw); 7317c478bd9Sstevel@tonic-gate ar->ad_contents = ctdp; 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate if (ar->ad_contents->t_size != 0) { 7347c478bd9Sstevel@tonic-gate dimtdp->t_size = ar->ad_contents->t_size * ar->ad_nelems; 7357c478bd9Sstevel@tonic-gate dimtdp->t_flags |= TDESC_F_RESOLVED; 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate } 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate /* 7407c478bd9Sstevel@tonic-gate * Create a tdesc from an array node. Some arrays will come with byte size 7417c478bd9Sstevel@tonic-gate * attributes, and thus can be resolved immediately. Others don't, and will 7427c478bd9Sstevel@tonic-gate * need to wait until the second pass for resolution. 7437c478bd9Sstevel@tonic-gate */ 7447c478bd9Sstevel@tonic-gate static void 7457c478bd9Sstevel@tonic-gate die_array_create(dwarf_t *dw, Dwarf_Die arr, Dwarf_Off off, tdesc_t *tdp) 7467c478bd9Sstevel@tonic-gate { 7477c478bd9Sstevel@tonic-gate tdesc_t *arrtdp = die_lookup_pass1(dw, arr, DW_AT_type); 7487c478bd9Sstevel@tonic-gate Dwarf_Unsigned uval; 7497c478bd9Sstevel@tonic-gate Dwarf_Die dim; 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating array\n", off); 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate if ((dim = die_child(dw, arr)) == NULL || 7547c478bd9Sstevel@tonic-gate die_tag(dw, dim) != DW_TAG_subrange_type) 7557c478bd9Sstevel@tonic-gate terminate("die %llu: failed to retrieve array bounds\n", off); 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate tdesc_array_create(dw, dim, arrtdp, tdp); 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate if (die_unsigned(dw, arr, DW_AT_byte_size, &uval, 0)) { 7607c478bd9Sstevel@tonic-gate tdesc_t *dimtdp; 7617c478bd9Sstevel@tonic-gate int flags; 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate tdp->t_size = uval; 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate /* 7667c478bd9Sstevel@tonic-gate * Ensure that sub-dimensions have sizes too before marking 7677c478bd9Sstevel@tonic-gate * as resolved. 7687c478bd9Sstevel@tonic-gate */ 7697c478bd9Sstevel@tonic-gate flags = TDESC_F_RESOLVED; 7707c478bd9Sstevel@tonic-gate for (dimtdp = tdp->t_ardef->ad_contents; 7717c478bd9Sstevel@tonic-gate dimtdp->t_type == ARRAY; 7727c478bd9Sstevel@tonic-gate dimtdp = dimtdp->t_ardef->ad_contents) { 7737c478bd9Sstevel@tonic-gate if (!(dimtdp->t_flags & TDESC_F_RESOLVED)) { 7747c478bd9Sstevel@tonic-gate flags = 0; 7757c478bd9Sstevel@tonic-gate break; 7767c478bd9Sstevel@tonic-gate } 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate tdp->t_flags |= flags; 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate debug(3, "die %llu: array nelems %u size %u\n", off, 7837c478bd9Sstevel@tonic-gate tdp->t_ardef->ad_nelems, tdp->t_size); 7847c478bd9Sstevel@tonic-gate } 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 7877c478bd9Sstevel@tonic-gate static int 7887c478bd9Sstevel@tonic-gate die_array_resolve(tdesc_t *tdp, tdesc_t **tdpp, void *private) 7897c478bd9Sstevel@tonic-gate { 7907c478bd9Sstevel@tonic-gate dwarf_t *dw = private; 7917c478bd9Sstevel@tonic-gate size_t sz; 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 7947c478bd9Sstevel@tonic-gate return (1); 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate debug(3, "trying to resolve array %d (cont %d)\n", tdp->t_id, 7977c478bd9Sstevel@tonic-gate tdp->t_ardef->ad_contents->t_id); 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate if ((sz = tdesc_size(tdp->t_ardef->ad_contents)) == 0) { 8007c478bd9Sstevel@tonic-gate debug(3, "unable to resolve array %s (%d) contents %d\n", 8014d232658Sjohnlev tdesc_name(tdp), tdp->t_id, 8027c478bd9Sstevel@tonic-gate tdp->t_ardef->ad_contents->t_id); 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate dw->dw_nunres++; 8057c478bd9Sstevel@tonic-gate return (1); 8067c478bd9Sstevel@tonic-gate } 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate tdp->t_size = sz * tdp->t_ardef->ad_nelems; 8097c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate debug(3, "resolved array %d: %u bytes\n", tdp->t_id, tdp->t_size); 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate return (1); 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 8177c478bd9Sstevel@tonic-gate static int 8187c478bd9Sstevel@tonic-gate die_array_failed(tdesc_t *tdp, tdesc_t **tdpp, void *private) 8197c478bd9Sstevel@tonic-gate { 8207c478bd9Sstevel@tonic-gate tdesc_t *cont = tdp->t_ardef->ad_contents; 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 8237c478bd9Sstevel@tonic-gate return (1); 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate fprintf(stderr, "Array %d: failed to size contents type %s (%d)\n", 8264d232658Sjohnlev tdp->t_id, tdesc_name(cont), cont->t_id); 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate return (1); 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate /* 8327c478bd9Sstevel@tonic-gate * Most enums (those with members) will be resolved during this first pass. 8337c478bd9Sstevel@tonic-gate * Others - those without members (see the file comment) - won't be, and will 8347c478bd9Sstevel@tonic-gate * need to wait until the second pass when they can be matched with their full 8357c478bd9Sstevel@tonic-gate * definitions. 8367c478bd9Sstevel@tonic-gate */ 8377c478bd9Sstevel@tonic-gate static void 8387c478bd9Sstevel@tonic-gate die_enum_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 8397c478bd9Sstevel@tonic-gate { 8407c478bd9Sstevel@tonic-gate Dwarf_Die mem; 8417c478bd9Sstevel@tonic-gate Dwarf_Unsigned uval; 8427c478bd9Sstevel@tonic-gate Dwarf_Signed sval; 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating enum\n", off); 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate tdp->t_type = ENUM; 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate (void) die_unsigned(dw, die, DW_AT_byte_size, &uval, DW_ATTR_REQ); 8497c478bd9Sstevel@tonic-gate tdp->t_size = uval; 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate if ((mem = die_child(dw, die)) != NULL) { 8527c478bd9Sstevel@tonic-gate elist_t **elastp = &tdp->t_emem; 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate do { 8557c478bd9Sstevel@tonic-gate elist_t *el; 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate if (die_tag(dw, mem) != DW_TAG_enumerator) { 8587c478bd9Sstevel@tonic-gate /* Nested type declaration */ 8597c478bd9Sstevel@tonic-gate die_create_one(dw, mem); 8607c478bd9Sstevel@tonic-gate continue; 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate el = xcalloc(sizeof (elist_t)); 8647c478bd9Sstevel@tonic-gate el->el_name = die_name(dw, mem); 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate if (die_signed(dw, mem, DW_AT_const_value, &sval, 0)) { 8677c478bd9Sstevel@tonic-gate el->el_number = sval; 8687c478bd9Sstevel@tonic-gate } else if (die_unsigned(dw, mem, DW_AT_const_value, 8697c478bd9Sstevel@tonic-gate &uval, 0)) { 8707c478bd9Sstevel@tonic-gate el->el_number = uval; 8717c478bd9Sstevel@tonic-gate } else { 8727c478bd9Sstevel@tonic-gate terminate("die %llu: enum %llu: member without " 8737c478bd9Sstevel@tonic-gate "value\n", off, die_off(dw, mem)); 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate debug(3, "die %llu: enum %llu: created %s = %d\n", off, 8777c478bd9Sstevel@tonic-gate die_off(dw, mem), el->el_name, el->el_number); 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate *elastp = el; 8807c478bd9Sstevel@tonic-gate elastp = &el->el_next; 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate } while ((mem = die_sibling(dw, mem)) != NULL); 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate hash_add(dw->dw_enumhash, tdp); 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate if (tdp->t_name != NULL) { 8897c478bd9Sstevel@tonic-gate iidesc_t *ii = xcalloc(sizeof (iidesc_t)); 8907c478bd9Sstevel@tonic-gate ii->ii_type = II_SOU; 8917c478bd9Sstevel@tonic-gate ii->ii_name = xstrdup(tdp->t_name); 8927c478bd9Sstevel@tonic-gate ii->ii_dtype = tdp; 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate static int 9007c478bd9Sstevel@tonic-gate die_enum_match(void *arg1, void *arg2) 9017c478bd9Sstevel@tonic-gate { 9027c478bd9Sstevel@tonic-gate tdesc_t *tdp = arg1, **fullp = arg2; 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate if (tdp->t_emem != NULL) { 9057c478bd9Sstevel@tonic-gate *fullp = tdp; 9067c478bd9Sstevel@tonic-gate return (-1); /* stop the iteration */ 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate return (0); 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 9137c478bd9Sstevel@tonic-gate static int 9147c478bd9Sstevel@tonic-gate die_enum_resolve(tdesc_t *tdp, tdesc_t **tdpp, void *private) 9157c478bd9Sstevel@tonic-gate { 9167c478bd9Sstevel@tonic-gate dwarf_t *dw = private; 9177c478bd9Sstevel@tonic-gate tdesc_t *full = NULL; 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 9207c478bd9Sstevel@tonic-gate return (1); 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate (void) hash_find_iter(dw->dw_enumhash, tdp, die_enum_match, &full); 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate /* 9257c478bd9Sstevel@tonic-gate * The answer to this one won't change from iteration to iteration, 9267c478bd9Sstevel@tonic-gate * so don't even try. 9277c478bd9Sstevel@tonic-gate */ 9287c478bd9Sstevel@tonic-gate if (full == NULL) { 9294d232658Sjohnlev terminate("tdp %u: enum %s has no members\n", tdp->t_id, 9304d232658Sjohnlev tdesc_name(tdp)); 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate debug(3, "tdp %u: enum %s redirected to %u\n", tdp->t_id, 9344d232658Sjohnlev tdesc_name(tdp), full->t_id); 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate return (1); 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate static int 9427c478bd9Sstevel@tonic-gate die_fwd_map(void *arg1, void *arg2) 9437c478bd9Sstevel@tonic-gate { 9447c478bd9Sstevel@tonic-gate tdesc_t *fwd = arg1, *sou = arg2; 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate debug(3, "tdp %u: mapped forward %s to sou %u\n", fwd->t_id, 9474d232658Sjohnlev tdesc_name(fwd), sou->t_id); 9487c478bd9Sstevel@tonic-gate fwd->t_tdesc = sou; 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate return (0); 9517c478bd9Sstevel@tonic-gate } 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate /* 9547c478bd9Sstevel@tonic-gate * Structures and unions will never be resolved during the first pass, as we 9557c478bd9Sstevel@tonic-gate * won't be able to fully determine the member sizes. The second pass, which 9567c478bd9Sstevel@tonic-gate * have access to sizing information, will be able to complete the resolution. 9577c478bd9Sstevel@tonic-gate */ 9587c478bd9Sstevel@tonic-gate static void 9597c478bd9Sstevel@tonic-gate die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp, 9607c478bd9Sstevel@tonic-gate int type, const char *typename) 9617c478bd9Sstevel@tonic-gate { 9627c478bd9Sstevel@tonic-gate Dwarf_Unsigned sz, bitsz, bitoff; 9637c478bd9Sstevel@tonic-gate Dwarf_Die mem; 9647c478bd9Sstevel@tonic-gate mlist_t *ml, **mlastp; 9657c478bd9Sstevel@tonic-gate iidesc_t *ii; 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate tdp->t_type = (die_isdecl(dw, str) ? FORWARD : type); 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating %s %s\n", off, 9707c478bd9Sstevel@tonic-gate (tdp->t_type == FORWARD ? "forward decl" : typename), 9714d232658Sjohnlev tdesc_name(tdp)); 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate if (tdp->t_type == FORWARD) { 9747c478bd9Sstevel@tonic-gate hash_add(dw->dw_fwdhash, tdp); 9757c478bd9Sstevel@tonic-gate return; 9767c478bd9Sstevel@tonic-gate } 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate (void) hash_find_iter(dw->dw_fwdhash, tdp, die_fwd_map, tdp); 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate (void) die_unsigned(dw, str, DW_AT_byte_size, &sz, DW_ATTR_REQ); 9817c478bd9Sstevel@tonic-gate tdp->t_size = sz; 9827c478bd9Sstevel@tonic-gate 983ae115bc7Smrj /* 984ae115bc7Smrj * GCC allows empty SOUs as an extension. 985ae115bc7Smrj */ 9867c478bd9Sstevel@tonic-gate if ((mem = die_child(dw, str)) == NULL) 987ae115bc7Smrj goto out; 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate mlastp = &tdp->t_members; 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate do { 9927c478bd9Sstevel@tonic-gate Dwarf_Off memoff = die_off(dw, mem); 9937c478bd9Sstevel@tonic-gate Dwarf_Half tag = die_tag(dw, mem); 9947c478bd9Sstevel@tonic-gate Dwarf_Unsigned mloff; 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate if (tag != DW_TAG_member) { 9977c478bd9Sstevel@tonic-gate /* Nested type declaration */ 9987c478bd9Sstevel@tonic-gate die_create_one(dw, mem); 9997c478bd9Sstevel@tonic-gate continue; 10007c478bd9Sstevel@tonic-gate } 10017c478bd9Sstevel@tonic-gate 10027c478bd9Sstevel@tonic-gate debug(3, "die %llu: mem %llu: creating member\n", off, memoff); 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate ml = xcalloc(sizeof (mlist_t)); 10057c478bd9Sstevel@tonic-gate 1006e824d57fSjohnlev /* 1007e824d57fSjohnlev * This could be a GCC anon struct/union member, so we'll allow 1008e824d57fSjohnlev * an empty name, even though nothing can really handle them 1009e824d57fSjohnlev * properly. Note that some versions of GCC miss out debug 1010e824d57fSjohnlev * info for anon structs, though recent versions are fixed (gcc 1011e824d57fSjohnlev * bug 11816). 1012e824d57fSjohnlev */ 1013e824d57fSjohnlev if ((ml->ml_name = die_name(dw, mem)) == NULL) 1014e824d57fSjohnlev ml->ml_name = ""; 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate ml->ml_type = die_lookup_pass1(dw, mem, DW_AT_type); 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate if (die_mem_offset(dw, mem, DW_AT_data_member_location, 10197c478bd9Sstevel@tonic-gate &mloff, 0)) { 10207c478bd9Sstevel@tonic-gate debug(3, "die %llu: got mloff %llx\n", off, 10217c478bd9Sstevel@tonic-gate (u_longlong_t)mloff); 10227c478bd9Sstevel@tonic-gate ml->ml_offset = mloff * 8; 10237c478bd9Sstevel@tonic-gate } 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate if (die_unsigned(dw, mem, DW_AT_bit_size, &bitsz, 0)) 10267c478bd9Sstevel@tonic-gate ml->ml_size = bitsz; 10277c478bd9Sstevel@tonic-gate else 10287c478bd9Sstevel@tonic-gate ml->ml_size = tdesc_bitsize(ml->ml_type); 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate if (die_unsigned(dw, mem, DW_AT_bit_offset, &bitoff, 0)) { 10317c478bd9Sstevel@tonic-gate #ifdef _BIG_ENDIAN 10327c478bd9Sstevel@tonic-gate ml->ml_offset += bitoff; 10337c478bd9Sstevel@tonic-gate #else 1034626fe1bfSsethg ml->ml_offset += tdesc_bitsize(ml->ml_type) - bitoff - 1035626fe1bfSsethg ml->ml_size; 10367c478bd9Sstevel@tonic-gate #endif 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate 1039e824d57fSjohnlev debug(3, "die %llu: mem %llu: created \"%s\" (off %u sz %u)\n", 10407c478bd9Sstevel@tonic-gate off, memoff, ml->ml_name, ml->ml_offset, ml->ml_size); 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate *mlastp = ml; 10437c478bd9Sstevel@tonic-gate mlastp = &ml->ml_next; 10447c478bd9Sstevel@tonic-gate } while ((mem = die_sibling(dw, mem)) != NULL); 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate /* 10477c478bd9Sstevel@tonic-gate * GCC will attempt to eliminate unused types, thus decreasing the 10487c478bd9Sstevel@tonic-gate * size of the emitted dwarf. That is, if you declare a foo_t in your 10497c478bd9Sstevel@tonic-gate * header, include said header in your source file, and neglect to 10507c478bd9Sstevel@tonic-gate * actually use (directly or indirectly) the foo_t in the source file, 10517c478bd9Sstevel@tonic-gate * the foo_t won't make it into the emitted DWARF. So, at least, goes 10527c478bd9Sstevel@tonic-gate * the theory. 10537c478bd9Sstevel@tonic-gate * 10547c478bd9Sstevel@tonic-gate * Occasionally, it'll emit the DW_TAG_structure_type for the foo_t, 10557c478bd9Sstevel@tonic-gate * and then neglect to emit the members. Strangely, the loner struct 10567c478bd9Sstevel@tonic-gate * tag will always be followed by a proper nested declaration of 10577c478bd9Sstevel@tonic-gate * something else. This is clearly a bug, but we're not going to have 10587c478bd9Sstevel@tonic-gate * time to get it fixed before this goo goes back, so we'll have to work 10597c478bd9Sstevel@tonic-gate * around it. If we see a no-membered struct with a nested declaration 10607c478bd9Sstevel@tonic-gate * (i.e. die_child of the struct tag won't be null), we'll ignore it. 10617c478bd9Sstevel@tonic-gate * Being paranoid, we won't simply remove it from the hash. Instead, 10627c478bd9Sstevel@tonic-gate * we'll decline to create an iidesc for it, thus ensuring that this 10637c478bd9Sstevel@tonic-gate * type won't make it into the output file. To be safe, we'll also 10647c478bd9Sstevel@tonic-gate * change the name. 10657c478bd9Sstevel@tonic-gate */ 10667c478bd9Sstevel@tonic-gate if (tdp->t_members == NULL) { 10674d232658Sjohnlev const char *old = tdesc_name(tdp); 10687c478bd9Sstevel@tonic-gate size_t newsz = 7 + strlen(old) + 1; 10697c478bd9Sstevel@tonic-gate char *new = xmalloc(newsz); 10707c478bd9Sstevel@tonic-gate (void) snprintf(new, newsz, "orphan %s", old); 10717c478bd9Sstevel@tonic-gate 10724d232658Sjohnlev debug(3, "die %llu: worked around %s %s\n", off, typename, old); 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate if (tdp->t_name != NULL) 10757c478bd9Sstevel@tonic-gate free(tdp->t_name); 10767c478bd9Sstevel@tonic-gate tdp->t_name = new; 1077ae115bc7Smrj return; 10787c478bd9Sstevel@tonic-gate } 10797c478bd9Sstevel@tonic-gate 1080ae115bc7Smrj out: 1081ae115bc7Smrj if (tdp->t_name != NULL) { 10827c478bd9Sstevel@tonic-gate ii = xcalloc(sizeof (iidesc_t)); 10837c478bd9Sstevel@tonic-gate ii->ii_type = II_SOU; 10847c478bd9Sstevel@tonic-gate ii->ii_name = xstrdup(tdp->t_name); 10857c478bd9Sstevel@tonic-gate ii->ii_dtype = tdp; 10867c478bd9Sstevel@tonic-gate 10877c478bd9Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 10887c478bd9Sstevel@tonic-gate } 10897c478bd9Sstevel@tonic-gate } 10907c478bd9Sstevel@tonic-gate 10917c478bd9Sstevel@tonic-gate static void 10927c478bd9Sstevel@tonic-gate die_struct_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 10937c478bd9Sstevel@tonic-gate { 10947c478bd9Sstevel@tonic-gate die_sou_create(dw, die, off, tdp, STRUCT, "struct"); 10957c478bd9Sstevel@tonic-gate } 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate static void 10987c478bd9Sstevel@tonic-gate die_union_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 10997c478bd9Sstevel@tonic-gate { 11007c478bd9Sstevel@tonic-gate die_sou_create(dw, die, off, tdp, UNION, "union"); 11017c478bd9Sstevel@tonic-gate } 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 11047c478bd9Sstevel@tonic-gate static int 11057c478bd9Sstevel@tonic-gate die_sou_resolve(tdesc_t *tdp, tdesc_t **tdpp, void *private) 11067c478bd9Sstevel@tonic-gate { 11077c478bd9Sstevel@tonic-gate dwarf_t *dw = private; 11087c478bd9Sstevel@tonic-gate mlist_t *ml; 11097c478bd9Sstevel@tonic-gate tdesc_t *mt; 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 11127c478bd9Sstevel@tonic-gate return (1); 11137c478bd9Sstevel@tonic-gate 11144d232658Sjohnlev debug(3, "resolving sou %s\n", tdesc_name(tdp)); 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate for (ml = tdp->t_members; ml != NULL; ml = ml->ml_next) { 11177c478bd9Sstevel@tonic-gate if (ml->ml_size == 0) { 1118ae115bc7Smrj mt = tdesc_basetype(ml->ml_type); 1119ae115bc7Smrj 1120ae115bc7Smrj if ((ml->ml_size = tdesc_bitsize(mt)) != 0) 1121ae115bc7Smrj continue; 1122ae115bc7Smrj 1123ae115bc7Smrj /* 1124ae115bc7Smrj * For empty members, or GCC/C99 flexible array 1125ae115bc7Smrj * members, a size of 0 is correct. 1126ae115bc7Smrj */ 1127ae115bc7Smrj if (mt->t_members == NULL) 1128ae115bc7Smrj continue; 1129ae115bc7Smrj if (mt->t_type == ARRAY && mt->t_ardef->ad_nelems == 0) 1130ae115bc7Smrj continue; 1131ae115bc7Smrj 11327c478bd9Sstevel@tonic-gate dw->dw_nunres++; 11337c478bd9Sstevel@tonic-gate return (1); 11347c478bd9Sstevel@tonic-gate } 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate if ((mt = tdesc_basetype(ml->ml_type)) == NULL) { 11377c478bd9Sstevel@tonic-gate dw->dw_nunres++; 11387c478bd9Sstevel@tonic-gate return (1); 11397c478bd9Sstevel@tonic-gate } 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate if (ml->ml_size != 0 && mt->t_type == INTRINSIC && 11427c478bd9Sstevel@tonic-gate mt->t_intr->intr_nbits != ml->ml_size) { 11437c478bd9Sstevel@tonic-gate /* 11447c478bd9Sstevel@tonic-gate * This member is a bitfield, and needs to reference 11457c478bd9Sstevel@tonic-gate * an intrinsic type with the same width. If the 11467c478bd9Sstevel@tonic-gate * currently-referenced type isn't of the same width, 11477c478bd9Sstevel@tonic-gate * we'll copy it, adjusting the width of the copy to 11487c478bd9Sstevel@tonic-gate * the size we'd like. 11497c478bd9Sstevel@tonic-gate */ 11507c478bd9Sstevel@tonic-gate debug(3, "tdp %u: creating bitfield for %d bits\n", 11517c478bd9Sstevel@tonic-gate tdp->t_id, ml->ml_size); 11527c478bd9Sstevel@tonic-gate 11537c478bd9Sstevel@tonic-gate ml->ml_type = tdesc_intr_clone(dw, mt, ml->ml_size); 11547c478bd9Sstevel@tonic-gate } 11557c478bd9Sstevel@tonic-gate } 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate return (1); 11607c478bd9Sstevel@tonic-gate } 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 11637c478bd9Sstevel@tonic-gate static int 11647c478bd9Sstevel@tonic-gate die_sou_failed(tdesc_t *tdp, tdesc_t **tdpp, void *private) 11657c478bd9Sstevel@tonic-gate { 11667c478bd9Sstevel@tonic-gate const char *typename = (tdp->t_type == STRUCT ? "struct" : "union"); 11677c478bd9Sstevel@tonic-gate mlist_t *ml; 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate if (tdp->t_flags & TDESC_F_RESOLVED) 11707c478bd9Sstevel@tonic-gate return (1); 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate for (ml = tdp->t_members; ml != NULL; ml = ml->ml_next) { 11737c478bd9Sstevel@tonic-gate if (ml->ml_size == 0) { 1174e824d57fSjohnlev fprintf(stderr, "%s %d: failed to size member \"%s\" " 1175e824d57fSjohnlev "of type %s (%d)\n", typename, tdp->t_id, 1176e824d57fSjohnlev ml->ml_name, tdesc_name(ml->ml_type), 1177e824d57fSjohnlev ml->ml_type->t_id); 11787c478bd9Sstevel@tonic-gate } 11797c478bd9Sstevel@tonic-gate } 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate return (1); 11827c478bd9Sstevel@tonic-gate } 11837c478bd9Sstevel@tonic-gate 11847c478bd9Sstevel@tonic-gate static void 11857c478bd9Sstevel@tonic-gate die_funcptr_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 11867c478bd9Sstevel@tonic-gate { 11877c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 11887c478bd9Sstevel@tonic-gate Dwarf_Half tag; 11897c478bd9Sstevel@tonic-gate Dwarf_Die arg; 11907c478bd9Sstevel@tonic-gate fndef_t *fn; 11917c478bd9Sstevel@tonic-gate int i; 11927c478bd9Sstevel@tonic-gate 11937c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating function pointer\n", off); 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate /* 11967c478bd9Sstevel@tonic-gate * We'll begin by processing any type definition nodes that may be 11977c478bd9Sstevel@tonic-gate * lurking underneath this one. 11987c478bd9Sstevel@tonic-gate */ 11997c478bd9Sstevel@tonic-gate for (arg = die_child(dw, die); arg != NULL; 12007c478bd9Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 12017c478bd9Sstevel@tonic-gate if ((tag = die_tag(dw, arg)) != DW_TAG_formal_parameter && 12027c478bd9Sstevel@tonic-gate tag != DW_TAG_unspecified_parameters) { 12037c478bd9Sstevel@tonic-gate /* Nested type declaration */ 12047c478bd9Sstevel@tonic-gate die_create_one(dw, arg); 12057c478bd9Sstevel@tonic-gate } 12067c478bd9Sstevel@tonic-gate } 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate if (die_isdecl(dw, die)) { 12097c478bd9Sstevel@tonic-gate /* 12107c478bd9Sstevel@tonic-gate * This is a prototype. We don't add prototypes to the 12117c478bd9Sstevel@tonic-gate * tree, so we're going to drop the tdesc. Unfortunately, 12127c478bd9Sstevel@tonic-gate * it has already been added to the tree. Nobody will reference 12137c478bd9Sstevel@tonic-gate * it, though, and it will be leaked. 12147c478bd9Sstevel@tonic-gate */ 12157c478bd9Sstevel@tonic-gate return; 12167c478bd9Sstevel@tonic-gate } 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate fn = xcalloc(sizeof (fndef_t)); 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate tdp->t_type = FUNCTION; 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, DW_AT_type, 0)) != NULL) { 12237c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 12247c478bd9Sstevel@tonic-gate fn->fn_ret = die_lookup_pass1(dw, die, DW_AT_type); 12257c478bd9Sstevel@tonic-gate } else { 12267c478bd9Sstevel@tonic-gate fn->fn_ret = tdesc_intr_void(dw); 12277c478bd9Sstevel@tonic-gate } 12287c478bd9Sstevel@tonic-gate 12297c478bd9Sstevel@tonic-gate /* 12307c478bd9Sstevel@tonic-gate * Count the arguments to the function, then read them in. 12317c478bd9Sstevel@tonic-gate */ 12327c478bd9Sstevel@tonic-gate for (fn->fn_nargs = 0, arg = die_child(dw, die); arg != NULL; 12337c478bd9Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 12347c478bd9Sstevel@tonic-gate if ((tag = die_tag(dw, arg)) == DW_TAG_formal_parameter) 12357c478bd9Sstevel@tonic-gate fn->fn_nargs++; 12367c478bd9Sstevel@tonic-gate else if (tag == DW_TAG_unspecified_parameters && 12377c478bd9Sstevel@tonic-gate fn->fn_nargs > 0) 12387c478bd9Sstevel@tonic-gate fn->fn_vargs = 1; 12397c478bd9Sstevel@tonic-gate } 12407c478bd9Sstevel@tonic-gate 12417c478bd9Sstevel@tonic-gate if (fn->fn_nargs != 0) { 12427c478bd9Sstevel@tonic-gate debug(3, "die %llu: adding %d argument%s\n", off, fn->fn_nargs, 12437c478bd9Sstevel@tonic-gate (fn->fn_nargs > 1 ? "s" : "")); 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate fn->fn_args = xcalloc(sizeof (tdesc_t *) * fn->fn_nargs); 12467c478bd9Sstevel@tonic-gate for (i = 0, arg = die_child(dw, die); 12477c478bd9Sstevel@tonic-gate arg != NULL && i < fn->fn_nargs; 12487c478bd9Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 12497c478bd9Sstevel@tonic-gate if (die_tag(dw, arg) != DW_TAG_formal_parameter) 12507c478bd9Sstevel@tonic-gate continue; 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate fn->fn_args[i++] = die_lookup_pass1(dw, arg, 12537c478bd9Sstevel@tonic-gate DW_AT_type); 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate } 12567c478bd9Sstevel@tonic-gate 12577c478bd9Sstevel@tonic-gate tdp->t_fndef = fn; 12587c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate /* 12627c478bd9Sstevel@tonic-gate * GCC and DevPro use different names for the base types. While the terms are 12637c478bd9Sstevel@tonic-gate * the same, they are arranged in a different order. Some terms, such as int, 12647c478bd9Sstevel@tonic-gate * are implied in one, and explicitly named in the other. Given a base type 12657c478bd9Sstevel@tonic-gate * as input, this routine will return a common name, along with an intr_t 12667c478bd9Sstevel@tonic-gate * that reflects said name. 12677c478bd9Sstevel@tonic-gate */ 12687c478bd9Sstevel@tonic-gate static intr_t * 12697c478bd9Sstevel@tonic-gate die_base_name_parse(const char *name, char **newp) 12707c478bd9Sstevel@tonic-gate { 12717c478bd9Sstevel@tonic-gate char buf[100]; 12727c478bd9Sstevel@tonic-gate char *base, *c; 12737c478bd9Sstevel@tonic-gate int nlong = 0, nshort = 0, nchar = 0, nint = 0; 12747c478bd9Sstevel@tonic-gate int sign = 1; 12757c478bd9Sstevel@tonic-gate char fmt = '\0'; 12767c478bd9Sstevel@tonic-gate intr_t *intr; 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate if (strlen(name) > sizeof (buf) - 1) 12797c478bd9Sstevel@tonic-gate terminate("base type name \"%s\" is too long\n", name); 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate strncpy(buf, name, sizeof (buf)); 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate for (c = strtok(buf, " "); c != NULL; c = strtok(NULL, " ")) { 12847c478bd9Sstevel@tonic-gate if (strcmp(c, "signed") == 0) 12857c478bd9Sstevel@tonic-gate sign = 1; 12867c478bd9Sstevel@tonic-gate else if (strcmp(c, "unsigned") == 0) 12877c478bd9Sstevel@tonic-gate sign = 0; 12887c478bd9Sstevel@tonic-gate else if (strcmp(c, "long") == 0) 12897c478bd9Sstevel@tonic-gate nlong++; 12907c478bd9Sstevel@tonic-gate else if (strcmp(c, "char") == 0) { 12917c478bd9Sstevel@tonic-gate nchar++; 12927c478bd9Sstevel@tonic-gate fmt = 'c'; 12937c478bd9Sstevel@tonic-gate } else if (strcmp(c, "short") == 0) 12947c478bd9Sstevel@tonic-gate nshort++; 12957c478bd9Sstevel@tonic-gate else if (strcmp(c, "int") == 0) 12967c478bd9Sstevel@tonic-gate nint++; 12977c478bd9Sstevel@tonic-gate else { 12987c478bd9Sstevel@tonic-gate /* 12997c478bd9Sstevel@tonic-gate * If we don't recognize any of the tokens, we'll tell 13007c478bd9Sstevel@tonic-gate * the caller to fall back to the dwarf-provided 13017c478bd9Sstevel@tonic-gate * encoding information. 13027c478bd9Sstevel@tonic-gate */ 13037c478bd9Sstevel@tonic-gate return (NULL); 13047c478bd9Sstevel@tonic-gate } 13057c478bd9Sstevel@tonic-gate } 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate if (nchar > 1 || nshort > 1 || nint > 1 || nlong > 2) 13087c478bd9Sstevel@tonic-gate return (NULL); 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate if (nchar > 0) { 13117c478bd9Sstevel@tonic-gate if (nlong > 0 || nshort > 0 || nint > 0) 13127c478bd9Sstevel@tonic-gate return (NULL); 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate base = "char"; 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate } else if (nshort > 0) { 13177c478bd9Sstevel@tonic-gate if (nlong > 0) 13187c478bd9Sstevel@tonic-gate return (NULL); 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate base = "short"; 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate } else if (nlong > 0) { 13237c478bd9Sstevel@tonic-gate base = "long"; 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate } else { 13267c478bd9Sstevel@tonic-gate base = "int"; 13277c478bd9Sstevel@tonic-gate } 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate intr = xcalloc(sizeof (intr_t)); 13307c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 13317c478bd9Sstevel@tonic-gate intr->intr_signed = sign; 13327c478bd9Sstevel@tonic-gate intr->intr_iformat = fmt; 13337c478bd9Sstevel@tonic-gate 13347c478bd9Sstevel@tonic-gate snprintf(buf, sizeof (buf), "%s%s%s", 13357c478bd9Sstevel@tonic-gate (sign ? "" : "unsigned "), 13367c478bd9Sstevel@tonic-gate (nlong > 1 ? "long " : ""), 13377c478bd9Sstevel@tonic-gate base); 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate *newp = xstrdup(buf); 13407c478bd9Sstevel@tonic-gate return (intr); 13417c478bd9Sstevel@tonic-gate } 13427c478bd9Sstevel@tonic-gate 13437c478bd9Sstevel@tonic-gate typedef struct fp_size_map { 13447c478bd9Sstevel@tonic-gate size_t fsm_typesz[2]; /* size of {32,64} type */ 13457c478bd9Sstevel@tonic-gate uint_t fsm_enc[3]; /* CTF_FP_* for {bare,cplx,imagry} type */ 13467c478bd9Sstevel@tonic-gate } fp_size_map_t; 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate static const fp_size_map_t fp_encodings[] = { 13497c478bd9Sstevel@tonic-gate { { 4, 4 }, { CTF_FP_SINGLE, CTF_FP_CPLX, CTF_FP_IMAGRY } }, 13507c478bd9Sstevel@tonic-gate { { 8, 8 }, { CTF_FP_DOUBLE, CTF_FP_DCPLX, CTF_FP_DIMAGRY } }, 135189518a1cSdmick #ifdef __sparc 135289518a1cSdmick { { 16, 16 }, { CTF_FP_LDOUBLE, CTF_FP_LDCPLX, CTF_FP_LDIMAGRY } }, 135389518a1cSdmick #else 13547c478bd9Sstevel@tonic-gate { { 12, 16 }, { CTF_FP_LDOUBLE, CTF_FP_LDCPLX, CTF_FP_LDIMAGRY } }, 135589518a1cSdmick #endif 13567c478bd9Sstevel@tonic-gate { { 0, 0 } } 13577c478bd9Sstevel@tonic-gate }; 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate static uint_t 13607c478bd9Sstevel@tonic-gate die_base_type2enc(dwarf_t *dw, Dwarf_Off off, Dwarf_Signed enc, size_t sz) 13617c478bd9Sstevel@tonic-gate { 13627c478bd9Sstevel@tonic-gate const fp_size_map_t *map = fp_encodings; 13637c478bd9Sstevel@tonic-gate uint_t szidx = dw->dw_ptrsz == sizeof (uint64_t); 13647c478bd9Sstevel@tonic-gate uint_t mult = 1, col = 0; 13657c478bd9Sstevel@tonic-gate 13667c478bd9Sstevel@tonic-gate if (enc == DW_ATE_complex_float) { 13677c478bd9Sstevel@tonic-gate mult = 2; 13687c478bd9Sstevel@tonic-gate col = 1; 13697c478bd9Sstevel@tonic-gate } else if (enc == DW_ATE_imaginary_float || 13707c478bd9Sstevel@tonic-gate enc == DW_ATE_SUN_imaginary_float) 13717c478bd9Sstevel@tonic-gate col = 2; 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate while (map->fsm_typesz[szidx] != 0) { 13747c478bd9Sstevel@tonic-gate if (map->fsm_typesz[szidx] * mult == sz) 13757c478bd9Sstevel@tonic-gate return (map->fsm_enc[col]); 13767c478bd9Sstevel@tonic-gate map++; 13777c478bd9Sstevel@tonic-gate } 13787c478bd9Sstevel@tonic-gate 13797c478bd9Sstevel@tonic-gate terminate("die %llu: unrecognized real type size %u\n", off, sz); 13807c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 13817c478bd9Sstevel@tonic-gate return (0); 13827c478bd9Sstevel@tonic-gate } 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate static intr_t * 13857c478bd9Sstevel@tonic-gate die_base_from_dwarf(dwarf_t *dw, Dwarf_Die base, Dwarf_Off off, size_t sz) 13867c478bd9Sstevel@tonic-gate { 13877c478bd9Sstevel@tonic-gate intr_t *intr = xcalloc(sizeof (intr_t)); 13887c478bd9Sstevel@tonic-gate Dwarf_Signed enc; 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate (void) die_signed(dw, base, DW_AT_encoding, &enc, DW_ATTR_REQ); 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate switch (enc) { 13937c478bd9Sstevel@tonic-gate case DW_ATE_unsigned: 13947c478bd9Sstevel@tonic-gate case DW_ATE_address: 13957c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 13967c478bd9Sstevel@tonic-gate break; 13977c478bd9Sstevel@tonic-gate case DW_ATE_unsigned_char: 13987c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 13997c478bd9Sstevel@tonic-gate intr->intr_iformat = 'c'; 14007c478bd9Sstevel@tonic-gate break; 14017c478bd9Sstevel@tonic-gate case DW_ATE_signed: 14027c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 14037c478bd9Sstevel@tonic-gate intr->intr_signed = 1; 14047c478bd9Sstevel@tonic-gate break; 14057c478bd9Sstevel@tonic-gate case DW_ATE_signed_char: 14067c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 14077c478bd9Sstevel@tonic-gate intr->intr_signed = 1; 14087c478bd9Sstevel@tonic-gate intr->intr_iformat = 'c'; 14097c478bd9Sstevel@tonic-gate break; 14107c478bd9Sstevel@tonic-gate case DW_ATE_boolean: 14117c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 14127c478bd9Sstevel@tonic-gate intr->intr_signed = 1; 14137c478bd9Sstevel@tonic-gate intr->intr_iformat = 'b'; 14147c478bd9Sstevel@tonic-gate break; 14157c478bd9Sstevel@tonic-gate case DW_ATE_float: 14167c478bd9Sstevel@tonic-gate case DW_ATE_complex_float: 14177c478bd9Sstevel@tonic-gate case DW_ATE_imaginary_float: 14187c478bd9Sstevel@tonic-gate case DW_ATE_SUN_imaginary_float: 14197c478bd9Sstevel@tonic-gate case DW_ATE_SUN_interval_float: 14207c478bd9Sstevel@tonic-gate intr->intr_type = INTR_REAL; 14217c478bd9Sstevel@tonic-gate intr->intr_signed = 1; 14227c478bd9Sstevel@tonic-gate intr->intr_fformat = die_base_type2enc(dw, off, enc, sz); 14237c478bd9Sstevel@tonic-gate break; 14247c478bd9Sstevel@tonic-gate default: 14257c478bd9Sstevel@tonic-gate terminate("die %llu: unknown base type encoding 0x%llx\n", 14267c478bd9Sstevel@tonic-gate off, enc); 14277c478bd9Sstevel@tonic-gate } 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate return (intr); 14307c478bd9Sstevel@tonic-gate } 14317c478bd9Sstevel@tonic-gate 14327c478bd9Sstevel@tonic-gate static void 14337c478bd9Sstevel@tonic-gate die_base_create(dwarf_t *dw, Dwarf_Die base, Dwarf_Off off, tdesc_t *tdp) 14347c478bd9Sstevel@tonic-gate { 14357c478bd9Sstevel@tonic-gate Dwarf_Unsigned sz; 14367c478bd9Sstevel@tonic-gate intr_t *intr; 14377c478bd9Sstevel@tonic-gate char *new; 14387c478bd9Sstevel@tonic-gate 14397c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating base type\n", off); 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate /* 14427c478bd9Sstevel@tonic-gate * The compilers have their own clever (internally inconsistent) ideas 14437c478bd9Sstevel@tonic-gate * as to what base types should look like. Some times gcc will, for 14447c478bd9Sstevel@tonic-gate * example, use DW_ATE_signed_char for char. Other times, however, it 14457c478bd9Sstevel@tonic-gate * will use DW_ATE_signed. Needless to say, this causes some problems 14467c478bd9Sstevel@tonic-gate * down the road, particularly with merging. We do, however, use the 14477c478bd9Sstevel@tonic-gate * DWARF idea of type sizes, as this allows us to avoid caring about 14487c478bd9Sstevel@tonic-gate * the data model. 14497c478bd9Sstevel@tonic-gate */ 14507c478bd9Sstevel@tonic-gate (void) die_unsigned(dw, base, DW_AT_byte_size, &sz, DW_ATTR_REQ); 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate if (tdp->t_name == NULL) 14537c478bd9Sstevel@tonic-gate terminate("die %llu: base type without name\n", off); 14547c478bd9Sstevel@tonic-gate 14557c478bd9Sstevel@tonic-gate /* XXX make a name parser for float too */ 14567c478bd9Sstevel@tonic-gate if ((intr = die_base_name_parse(tdp->t_name, &new)) != NULL) { 14577c478bd9Sstevel@tonic-gate /* Found it. We'll use the parsed version */ 14587c478bd9Sstevel@tonic-gate debug(3, "die %llu: name \"%s\" remapped to \"%s\"\n", off, 14594d232658Sjohnlev tdesc_name(tdp), new); 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate free(tdp->t_name); 14627c478bd9Sstevel@tonic-gate tdp->t_name = new; 14637c478bd9Sstevel@tonic-gate } else { 14647c478bd9Sstevel@tonic-gate /* 14657c478bd9Sstevel@tonic-gate * We didn't recognize the type, so we'll create an intr_t 14667c478bd9Sstevel@tonic-gate * based on the DWARF data. 14677c478bd9Sstevel@tonic-gate */ 14687c478bd9Sstevel@tonic-gate debug(3, "die %llu: using dwarf data for base \"%s\"\n", off, 14694d232658Sjohnlev tdesc_name(tdp)); 14707c478bd9Sstevel@tonic-gate 14717c478bd9Sstevel@tonic-gate intr = die_base_from_dwarf(dw, base, off, sz); 14727c478bd9Sstevel@tonic-gate } 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate intr->intr_nbits = sz * 8; 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate tdp->t_type = INTRINSIC; 14777c478bd9Sstevel@tonic-gate tdp->t_intr = intr; 14787c478bd9Sstevel@tonic-gate tdp->t_size = sz; 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 14817c478bd9Sstevel@tonic-gate } 14827c478bd9Sstevel@tonic-gate 14837c478bd9Sstevel@tonic-gate static void 14847c478bd9Sstevel@tonic-gate die_through_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp, 14857c478bd9Sstevel@tonic-gate int type, const char *typename) 14867c478bd9Sstevel@tonic-gate { 14877c478bd9Sstevel@tonic-gate Dwarf_Attribute attr; 14887c478bd9Sstevel@tonic-gate 14897c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating %s\n", off, typename); 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate tdp->t_type = type; 14927c478bd9Sstevel@tonic-gate 14937c478bd9Sstevel@tonic-gate if ((attr = die_attr(dw, die, DW_AT_type, 0)) != NULL) { 14947c478bd9Sstevel@tonic-gate dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); 14957c478bd9Sstevel@tonic-gate tdp->t_tdesc = die_lookup_pass1(dw, die, DW_AT_type); 14967c478bd9Sstevel@tonic-gate } else { 14977c478bd9Sstevel@tonic-gate tdp->t_tdesc = tdesc_intr_void(dw); 14987c478bd9Sstevel@tonic-gate } 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate if (type == POINTER) 15017c478bd9Sstevel@tonic-gate tdp->t_size = dw->dw_ptrsz; 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate tdp->t_flags |= TDESC_F_RESOLVED; 15047c478bd9Sstevel@tonic-gate 15057c478bd9Sstevel@tonic-gate if (type == TYPEDEF) { 15067c478bd9Sstevel@tonic-gate iidesc_t *ii = xcalloc(sizeof (iidesc_t)); 15077c478bd9Sstevel@tonic-gate ii->ii_type = II_TYPE; 15087c478bd9Sstevel@tonic-gate ii->ii_name = xstrdup(tdp->t_name); 15097c478bd9Sstevel@tonic-gate ii->ii_dtype = tdp; 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 15127c478bd9Sstevel@tonic-gate } 15137c478bd9Sstevel@tonic-gate } 15147c478bd9Sstevel@tonic-gate 15157c478bd9Sstevel@tonic-gate static void 15167c478bd9Sstevel@tonic-gate die_typedef_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 15177c478bd9Sstevel@tonic-gate { 15187c478bd9Sstevel@tonic-gate die_through_create(dw, die, off, tdp, TYPEDEF, "typedef"); 15197c478bd9Sstevel@tonic-gate } 15207c478bd9Sstevel@tonic-gate 15217c478bd9Sstevel@tonic-gate static void 15227c478bd9Sstevel@tonic-gate die_const_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 15237c478bd9Sstevel@tonic-gate { 15247c478bd9Sstevel@tonic-gate die_through_create(dw, die, off, tdp, CONST, "const"); 15257c478bd9Sstevel@tonic-gate } 15267c478bd9Sstevel@tonic-gate 15277c478bd9Sstevel@tonic-gate static void 15287c478bd9Sstevel@tonic-gate die_pointer_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 15297c478bd9Sstevel@tonic-gate { 15307c478bd9Sstevel@tonic-gate die_through_create(dw, die, off, tdp, POINTER, "pointer"); 15317c478bd9Sstevel@tonic-gate } 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate static void 15347c478bd9Sstevel@tonic-gate die_restrict_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 15357c478bd9Sstevel@tonic-gate { 15367c478bd9Sstevel@tonic-gate die_through_create(dw, die, off, tdp, RESTRICT, "restrict"); 15377c478bd9Sstevel@tonic-gate } 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate static void 15407c478bd9Sstevel@tonic-gate die_volatile_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 15417c478bd9Sstevel@tonic-gate { 15427c478bd9Sstevel@tonic-gate die_through_create(dw, die, off, tdp, VOLATILE, "volatile"); 15437c478bd9Sstevel@tonic-gate } 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate /*ARGSUSED3*/ 15467c478bd9Sstevel@tonic-gate static void 15477c478bd9Sstevel@tonic-gate die_function_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 15487c478bd9Sstevel@tonic-gate { 15497c478bd9Sstevel@tonic-gate Dwarf_Die arg; 15507c478bd9Sstevel@tonic-gate Dwarf_Half tag; 15517c478bd9Sstevel@tonic-gate iidesc_t *ii; 15527c478bd9Sstevel@tonic-gate char *name; 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating function definition\n", off); 15557c478bd9Sstevel@tonic-gate 15567c478bd9Sstevel@tonic-gate /* 15577c478bd9Sstevel@tonic-gate * We'll begin by processing any type definition nodes that may be 15587c478bd9Sstevel@tonic-gate * lurking underneath this one. 15597c478bd9Sstevel@tonic-gate */ 15607c478bd9Sstevel@tonic-gate for (arg = die_child(dw, die); arg != NULL; 15617c478bd9Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 15627c478bd9Sstevel@tonic-gate if ((tag = die_tag(dw, arg)) != DW_TAG_formal_parameter && 15637c478bd9Sstevel@tonic-gate tag != DW_TAG_variable) { 15647c478bd9Sstevel@tonic-gate /* Nested type declaration */ 15657c478bd9Sstevel@tonic-gate die_create_one(dw, arg); 15667c478bd9Sstevel@tonic-gate } 15677c478bd9Sstevel@tonic-gate } 15687c478bd9Sstevel@tonic-gate 15697c478bd9Sstevel@tonic-gate if (die_isdecl(dw, die) || (name = die_name(dw, die)) == NULL) { 15707c478bd9Sstevel@tonic-gate /* 15717c478bd9Sstevel@tonic-gate * We process neither prototypes nor subprograms without 15727c478bd9Sstevel@tonic-gate * names. 15737c478bd9Sstevel@tonic-gate */ 15747c478bd9Sstevel@tonic-gate return; 15757c478bd9Sstevel@tonic-gate } 15767c478bd9Sstevel@tonic-gate 15777c478bd9Sstevel@tonic-gate ii = xcalloc(sizeof (iidesc_t)); 15787c478bd9Sstevel@tonic-gate ii->ii_type = die_isglobal(dw, die) ? II_GFUN : II_SFUN; 15797c478bd9Sstevel@tonic-gate ii->ii_name = name; 15807c478bd9Sstevel@tonic-gate if (ii->ii_type == II_SFUN) 15817c478bd9Sstevel@tonic-gate ii->ii_owner = xstrdup(dw->dw_cuname); 15827c478bd9Sstevel@tonic-gate 15837c478bd9Sstevel@tonic-gate debug(3, "die %llu: function %s is %s\n", off, ii->ii_name, 15847c478bd9Sstevel@tonic-gate (ii->ii_type == II_GFUN ? "global" : "static")); 15857c478bd9Sstevel@tonic-gate 15867c478bd9Sstevel@tonic-gate if (die_attr(dw, die, DW_AT_type, 0) != NULL) 15877c478bd9Sstevel@tonic-gate ii->ii_dtype = die_lookup_pass1(dw, die, DW_AT_type); 15887c478bd9Sstevel@tonic-gate else 15897c478bd9Sstevel@tonic-gate ii->ii_dtype = tdesc_intr_void(dw); 15907c478bd9Sstevel@tonic-gate 15917c478bd9Sstevel@tonic-gate for (arg = die_child(dw, die); arg != NULL; 15927c478bd9Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 15937c478bd9Sstevel@tonic-gate char *name; 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate debug(3, "die %llu: looking at sub member at %llu\n", 15967c478bd9Sstevel@tonic-gate off, die_off(dw, die)); 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate if (die_tag(dw, arg) != DW_TAG_formal_parameter) 15997c478bd9Sstevel@tonic-gate continue; 16007c478bd9Sstevel@tonic-gate 16017c478bd9Sstevel@tonic-gate if ((name = die_name(dw, arg)) == NULL) { 16027c478bd9Sstevel@tonic-gate terminate("die %llu: func arg %d has no name\n", 16037c478bd9Sstevel@tonic-gate off, ii->ii_nargs + 1); 16047c478bd9Sstevel@tonic-gate } 16057c478bd9Sstevel@tonic-gate 16067c478bd9Sstevel@tonic-gate if (strcmp(name, "...") == 0) { 16077c478bd9Sstevel@tonic-gate free(name); 16087c478bd9Sstevel@tonic-gate ii->ii_vargs = 1; 16097c478bd9Sstevel@tonic-gate continue; 16107c478bd9Sstevel@tonic-gate } 16117c478bd9Sstevel@tonic-gate 16127c478bd9Sstevel@tonic-gate ii->ii_nargs++; 16137c478bd9Sstevel@tonic-gate } 16147c478bd9Sstevel@tonic-gate 16157c478bd9Sstevel@tonic-gate if (ii->ii_nargs > 0) { 16167c478bd9Sstevel@tonic-gate int i; 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate debug(3, "die %llu: function has %d argument%s\n", off, 16197c478bd9Sstevel@tonic-gate ii->ii_nargs, (ii->ii_nargs == 1 ? "" : "s")); 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate ii->ii_args = xcalloc(sizeof (tdesc_t) * ii->ii_nargs); 16227c478bd9Sstevel@tonic-gate 16237c478bd9Sstevel@tonic-gate for (arg = die_child(dw, die), i = 0; 16247c478bd9Sstevel@tonic-gate arg != NULL && i < ii->ii_nargs; 16257c478bd9Sstevel@tonic-gate arg = die_sibling(dw, arg)) { 16267c478bd9Sstevel@tonic-gate if (die_tag(dw, arg) != DW_TAG_formal_parameter) 16277c478bd9Sstevel@tonic-gate continue; 16287c478bd9Sstevel@tonic-gate 16297c478bd9Sstevel@tonic-gate ii->ii_args[i++] = die_lookup_pass1(dw, arg, 16307c478bd9Sstevel@tonic-gate DW_AT_type); 16317c478bd9Sstevel@tonic-gate } 16327c478bd9Sstevel@tonic-gate } 16337c478bd9Sstevel@tonic-gate 16347c478bd9Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 16357c478bd9Sstevel@tonic-gate } 16367c478bd9Sstevel@tonic-gate 16377c478bd9Sstevel@tonic-gate /*ARGSUSED3*/ 16387c478bd9Sstevel@tonic-gate static void 16397c478bd9Sstevel@tonic-gate die_variable_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 16407c478bd9Sstevel@tonic-gate { 16417c478bd9Sstevel@tonic-gate iidesc_t *ii; 16427c478bd9Sstevel@tonic-gate char *name; 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate debug(3, "die %llu: creating object definition\n", off); 16457c478bd9Sstevel@tonic-gate 16467c478bd9Sstevel@tonic-gate if (die_isdecl(dw, die) || (name = die_name(dw, die)) == NULL) 16477c478bd9Sstevel@tonic-gate return; /* skip prototypes and nameless objects */ 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate ii = xcalloc(sizeof (iidesc_t)); 16507c478bd9Sstevel@tonic-gate ii->ii_type = die_isglobal(dw, die) ? II_GVAR : II_SVAR; 16517c478bd9Sstevel@tonic-gate ii->ii_name = name; 16527c478bd9Sstevel@tonic-gate ii->ii_dtype = die_lookup_pass1(dw, die, DW_AT_type); 16537c478bd9Sstevel@tonic-gate if (ii->ii_type == II_SVAR) 16547c478bd9Sstevel@tonic-gate ii->ii_owner = xstrdup(dw->dw_cuname); 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate iidesc_add(dw->dw_td->td_iihash, ii); 16577c478bd9Sstevel@tonic-gate } 16587c478bd9Sstevel@tonic-gate 16597c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 16607c478bd9Sstevel@tonic-gate static int 16617c478bd9Sstevel@tonic-gate die_fwd_resolve(tdesc_t *fwd, tdesc_t **fwdp, void *private) 16627c478bd9Sstevel@tonic-gate { 16637c478bd9Sstevel@tonic-gate if (fwd->t_flags & TDESC_F_RESOLVED) 16647c478bd9Sstevel@tonic-gate return (1); 16657c478bd9Sstevel@tonic-gate 16667c478bd9Sstevel@tonic-gate if (fwd->t_tdesc != NULL) { 16674d232658Sjohnlev debug(3, "tdp %u: unforwarded %s\n", fwd->t_id, 16684d232658Sjohnlev tdesc_name(fwd)); 16697c478bd9Sstevel@tonic-gate *fwdp = fwd->t_tdesc; 16707c478bd9Sstevel@tonic-gate } 16717c478bd9Sstevel@tonic-gate 16727c478bd9Sstevel@tonic-gate fwd->t_flags |= TDESC_F_RESOLVED; 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate return (1); 16757c478bd9Sstevel@tonic-gate } 16767c478bd9Sstevel@tonic-gate 16777c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 16787c478bd9Sstevel@tonic-gate static void 16797c478bd9Sstevel@tonic-gate die_lexblk_descend(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) 16807c478bd9Sstevel@tonic-gate { 16817c478bd9Sstevel@tonic-gate Dwarf_Die child = die_child(dw, die); 16827c478bd9Sstevel@tonic-gate 16837c478bd9Sstevel@tonic-gate if (child != NULL) 16847c478bd9Sstevel@tonic-gate die_create(dw, child); 16857c478bd9Sstevel@tonic-gate } 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate /* 16887c478bd9Sstevel@tonic-gate * Used to map the die to a routine which can parse it, using the tag to do the 16897c478bd9Sstevel@tonic-gate * mapping. While the processing of most tags entails the creation of a tdesc, 16907c478bd9Sstevel@tonic-gate * there are a few which don't - primarily those which result in the creation of 16917c478bd9Sstevel@tonic-gate * iidescs which refer to existing tdescs. 16927c478bd9Sstevel@tonic-gate */ 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate #define DW_F_NOTDP 0x1 /* Don't create a tdesc for the creator */ 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate typedef struct die_creator { 16977c478bd9Sstevel@tonic-gate Dwarf_Half dc_tag; 16987c478bd9Sstevel@tonic-gate uint16_t dc_flags; 16997c478bd9Sstevel@tonic-gate void (*dc_create)(dwarf_t *, Dwarf_Die, Dwarf_Off, tdesc_t *); 17007c478bd9Sstevel@tonic-gate } die_creator_t; 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate static const die_creator_t die_creators[] = { 17037c478bd9Sstevel@tonic-gate { DW_TAG_array_type, 0, die_array_create }, 17047c478bd9Sstevel@tonic-gate { DW_TAG_enumeration_type, 0, die_enum_create }, 17057c478bd9Sstevel@tonic-gate { DW_TAG_lexical_block, DW_F_NOTDP, die_lexblk_descend }, 17067c478bd9Sstevel@tonic-gate { DW_TAG_pointer_type, 0, die_pointer_create }, 17077c478bd9Sstevel@tonic-gate { DW_TAG_structure_type, 0, die_struct_create }, 17087c478bd9Sstevel@tonic-gate { DW_TAG_subroutine_type, 0, die_funcptr_create }, 17097c478bd9Sstevel@tonic-gate { DW_TAG_typedef, 0, die_typedef_create }, 17107c478bd9Sstevel@tonic-gate { DW_TAG_union_type, 0, die_union_create }, 17117c478bd9Sstevel@tonic-gate { DW_TAG_base_type, 0, die_base_create }, 17127c478bd9Sstevel@tonic-gate { DW_TAG_const_type, 0, die_const_create }, 17137c478bd9Sstevel@tonic-gate { DW_TAG_subprogram, DW_F_NOTDP, die_function_create }, 17147c478bd9Sstevel@tonic-gate { DW_TAG_variable, DW_F_NOTDP, die_variable_create }, 17157c478bd9Sstevel@tonic-gate { DW_TAG_volatile_type, 0, die_volatile_create }, 17167c478bd9Sstevel@tonic-gate { DW_TAG_restrict_type, 0, die_restrict_create }, 1717*ad0b1ea5SRichard PALO { 0, 0, NULL } 17187c478bd9Sstevel@tonic-gate }; 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate static const die_creator_t * 17217c478bd9Sstevel@tonic-gate die_tag2ctor(Dwarf_Half tag) 17227c478bd9Sstevel@tonic-gate { 17237c478bd9Sstevel@tonic-gate const die_creator_t *dc; 17247c478bd9Sstevel@tonic-gate 17257c478bd9Sstevel@tonic-gate for (dc = die_creators; dc->dc_create != NULL; dc++) { 17267c478bd9Sstevel@tonic-gate if (dc->dc_tag == tag) 17277c478bd9Sstevel@tonic-gate return (dc); 17287c478bd9Sstevel@tonic-gate } 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate return (NULL); 17317c478bd9Sstevel@tonic-gate } 17327c478bd9Sstevel@tonic-gate 17337c478bd9Sstevel@tonic-gate static void 17347c478bd9Sstevel@tonic-gate die_create_one(dwarf_t *dw, Dwarf_Die die) 17357c478bd9Sstevel@tonic-gate { 17367c478bd9Sstevel@tonic-gate Dwarf_Off off = die_off(dw, die); 17377c478bd9Sstevel@tonic-gate const die_creator_t *dc; 17387c478bd9Sstevel@tonic-gate Dwarf_Half tag; 17397c478bd9Sstevel@tonic-gate tdesc_t *tdp; 17407c478bd9Sstevel@tonic-gate 17417c478bd9Sstevel@tonic-gate debug(3, "die %llu: create_one\n", off); 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate if (off > dw->dw_maxoff) { 17447c478bd9Sstevel@tonic-gate terminate("illegal die offset %llu (max %llu)\n", off, 17457c478bd9Sstevel@tonic-gate dw->dw_maxoff); 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate tag = die_tag(dw, die); 17497c478bd9Sstevel@tonic-gate 17507c478bd9Sstevel@tonic-gate if ((dc = die_tag2ctor(tag)) == NULL) { 17517c478bd9Sstevel@tonic-gate debug(2, "die %llu: ignoring tag type %x\n", off, tag); 17527c478bd9Sstevel@tonic-gate return; 17537c478bd9Sstevel@tonic-gate } 17547c478bd9Sstevel@tonic-gate 17557c478bd9Sstevel@tonic-gate if ((tdp = tdesc_lookup(dw, off)) == NULL && 17567c478bd9Sstevel@tonic-gate !(dc->dc_flags & DW_F_NOTDP)) { 17577c478bd9Sstevel@tonic-gate tdp = xcalloc(sizeof (tdesc_t)); 17587c478bd9Sstevel@tonic-gate tdp->t_id = off; 17597c478bd9Sstevel@tonic-gate tdesc_add(dw, tdp); 17607c478bd9Sstevel@tonic-gate } 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate if (tdp != NULL) 17637c478bd9Sstevel@tonic-gate tdp->t_name = die_name(dw, die); 17647c478bd9Sstevel@tonic-gate 17657c478bd9Sstevel@tonic-gate dc->dc_create(dw, die, off, tdp); 17667c478bd9Sstevel@tonic-gate } 17677c478bd9Sstevel@tonic-gate 17687c478bd9Sstevel@tonic-gate static void 17697c478bd9Sstevel@tonic-gate die_create(dwarf_t *dw, Dwarf_Die die) 17707c478bd9Sstevel@tonic-gate { 17717c478bd9Sstevel@tonic-gate do { 17727c478bd9Sstevel@tonic-gate die_create_one(dw, die); 17737c478bd9Sstevel@tonic-gate } while ((die = die_sibling(dw, die)) != NULL); 17747c478bd9Sstevel@tonic-gate } 17757c478bd9Sstevel@tonic-gate 17767c478bd9Sstevel@tonic-gate static tdtrav_cb_f die_resolvers[] = { 17777c478bd9Sstevel@tonic-gate NULL, 17787c478bd9Sstevel@tonic-gate NULL, /* intrinsic */ 17797c478bd9Sstevel@tonic-gate NULL, /* pointer */ 17807c478bd9Sstevel@tonic-gate die_array_resolve, /* array */ 17817c478bd9Sstevel@tonic-gate NULL, /* function */ 17827c478bd9Sstevel@tonic-gate die_sou_resolve, /* struct */ 17837c478bd9Sstevel@tonic-gate die_sou_resolve, /* union */ 17847c478bd9Sstevel@tonic-gate die_enum_resolve, /* enum */ 17857c478bd9Sstevel@tonic-gate die_fwd_resolve, /* forward */ 17867c478bd9Sstevel@tonic-gate NULL, /* typedef */ 17877c478bd9Sstevel@tonic-gate NULL, /* typedef unres */ 17887c478bd9Sstevel@tonic-gate NULL, /* volatile */ 17897c478bd9Sstevel@tonic-gate NULL, /* const */ 17907c478bd9Sstevel@tonic-gate NULL, /* restrict */ 17917c478bd9Sstevel@tonic-gate }; 17927c478bd9Sstevel@tonic-gate 17937c478bd9Sstevel@tonic-gate static tdtrav_cb_f die_fail_reporters[] = { 17947c478bd9Sstevel@tonic-gate NULL, 17957c478bd9Sstevel@tonic-gate NULL, /* intrinsic */ 17967c478bd9Sstevel@tonic-gate NULL, /* pointer */ 17977c478bd9Sstevel@tonic-gate die_array_failed, /* array */ 17987c478bd9Sstevel@tonic-gate NULL, /* function */ 17997c478bd9Sstevel@tonic-gate die_sou_failed, /* struct */ 18007c478bd9Sstevel@tonic-gate die_sou_failed, /* union */ 18017c478bd9Sstevel@tonic-gate NULL, /* enum */ 18027c478bd9Sstevel@tonic-gate NULL, /* forward */ 18037c478bd9Sstevel@tonic-gate NULL, /* typedef */ 18047c478bd9Sstevel@tonic-gate NULL, /* typedef unres */ 18057c478bd9Sstevel@tonic-gate NULL, /* volatile */ 18067c478bd9Sstevel@tonic-gate NULL, /* const */ 18077c478bd9Sstevel@tonic-gate NULL, /* restrict */ 18087c478bd9Sstevel@tonic-gate }; 18097c478bd9Sstevel@tonic-gate 18107c478bd9Sstevel@tonic-gate static void 18117c478bd9Sstevel@tonic-gate die_resolve(dwarf_t *dw) 18127c478bd9Sstevel@tonic-gate { 18137c478bd9Sstevel@tonic-gate int last = -1; 18147c478bd9Sstevel@tonic-gate int pass = 0; 18157c478bd9Sstevel@tonic-gate 18167c478bd9Sstevel@tonic-gate do { 18177c478bd9Sstevel@tonic-gate pass++; 18187c478bd9Sstevel@tonic-gate dw->dw_nunres = 0; 18197c478bd9Sstevel@tonic-gate 18207c478bd9Sstevel@tonic-gate (void) iitraverse_hash(dw->dw_td->td_iihash, 18217c478bd9Sstevel@tonic-gate &dw->dw_td->td_curvgen, NULL, NULL, die_resolvers, dw); 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate debug(3, "resolve: pass %d, %u left\n", pass, dw->dw_nunres); 18247c478bd9Sstevel@tonic-gate 18257c478bd9Sstevel@tonic-gate if (dw->dw_nunres == last) { 18267c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: failed to resolve the following " 18277c478bd9Sstevel@tonic-gate "types:\n", progname); 18287c478bd9Sstevel@tonic-gate 18297c478bd9Sstevel@tonic-gate (void) iitraverse_hash(dw->dw_td->td_iihash, 18307c478bd9Sstevel@tonic-gate &dw->dw_td->td_curvgen, NULL, NULL, 18317c478bd9Sstevel@tonic-gate die_fail_reporters, dw); 18327c478bd9Sstevel@tonic-gate 18337c478bd9Sstevel@tonic-gate terminate("failed to resolve types\n"); 18347c478bd9Sstevel@tonic-gate } 18357c478bd9Sstevel@tonic-gate 18367c478bd9Sstevel@tonic-gate last = dw->dw_nunres; 18377c478bd9Sstevel@tonic-gate 18387c478bd9Sstevel@tonic-gate } while (dw->dw_nunres != 0); 18397c478bd9Sstevel@tonic-gate } 18407c478bd9Sstevel@tonic-gate 184153ffad05SRichard Lowe /* 18426188327dSRichard Lowe * Any object containing a function or object symbol at any scope should also 18436188327dSRichard Lowe * contain DWARF data. 184453ffad05SRichard Lowe */ 184553ffad05SRichard Lowe static boolean_t 184653ffad05SRichard Lowe should_have_dwarf(Elf *elf) 184753ffad05SRichard Lowe { 184853ffad05SRichard Lowe Elf_Scn *scn = NULL; 18496188327dSRichard Lowe Elf_Data *data = NULL; 18506188327dSRichard Lowe GElf_Shdr shdr; 18516188327dSRichard Lowe GElf_Sym sym; 18526188327dSRichard Lowe uint32_t symdx = 0; 18536188327dSRichard Lowe size_t nsyms = 0; 18546188327dSRichard Lowe boolean_t found = B_FALSE; 185553ffad05SRichard Lowe 185653ffad05SRichard Lowe while ((scn = elf_nextscn(elf, scn)) != NULL) { 185753ffad05SRichard Lowe gelf_getshdr(scn, &shdr); 185853ffad05SRichard Lowe 18596188327dSRichard Lowe if (shdr.sh_type == SHT_SYMTAB) { 18606188327dSRichard Lowe found = B_TRUE; 18616188327dSRichard Lowe break; 18626188327dSRichard Lowe } 18636188327dSRichard Lowe } 18646188327dSRichard Lowe 18656188327dSRichard Lowe if (!found) 18666188327dSRichard Lowe terminate("cannot convert stripped objects\n"); 18676188327dSRichard Lowe 18686188327dSRichard Lowe data = elf_getdata(scn, NULL); 18696188327dSRichard Lowe nsyms = shdr.sh_size / shdr.sh_entsize; 18706188327dSRichard Lowe 18716188327dSRichard Lowe for (symdx = 0; symdx < nsyms; symdx++) { 18726188327dSRichard Lowe gelf_getsym(data, symdx, &sym); 18736188327dSRichard Lowe 18746188327dSRichard Lowe if ((GELF_ST_TYPE(sym.st_info) == STT_FUNC) || 18756188327dSRichard Lowe (GELF_ST_TYPE(sym.st_info) == STT_TLS) || 18766188327dSRichard Lowe (GELF_ST_TYPE(sym.st_info) == STT_OBJECT)) { 18776188327dSRichard Lowe char *name; 18786188327dSRichard Lowe 18796188327dSRichard Lowe name = elf_strptr(elf, shdr.sh_link, sym.st_name); 18806188327dSRichard Lowe 18816188327dSRichard Lowe /* Studio emits these local symbols regardless */ 18826188327dSRichard Lowe if ((strcmp(name, "Bbss.bss") != 0) && 18836188327dSRichard Lowe (strcmp(name, "Ttbss.bss") != 0) && 18846188327dSRichard Lowe (strcmp(name, "Ddata.data") != 0) && 18856188327dSRichard Lowe (strcmp(name, "Ttdata.data") != 0) && 18866188327dSRichard Lowe (strcmp(name, "Drodata.rodata") != 0)) 188753ffad05SRichard Lowe return (B_TRUE); 188853ffad05SRichard Lowe } 18896188327dSRichard Lowe } 189053ffad05SRichard Lowe 189153ffad05SRichard Lowe return (B_FALSE); 189253ffad05SRichard Lowe } 189353ffad05SRichard Lowe 18947c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 18957c478bd9Sstevel@tonic-gate int 18967c478bd9Sstevel@tonic-gate dw_read(tdata_t *td, Elf *elf, const char *filename) 18977c478bd9Sstevel@tonic-gate { 18987c478bd9Sstevel@tonic-gate Dwarf_Unsigned abboff, hdrlen, nxthdr; 18997c478bd9Sstevel@tonic-gate Dwarf_Half vers, addrsz; 19007c478bd9Sstevel@tonic-gate Dwarf_Die cu, child; 19017c478bd9Sstevel@tonic-gate dwarf_t dw; 19027c478bd9Sstevel@tonic-gate char *prod = NULL; 19037c478bd9Sstevel@tonic-gate int rc; 19047c478bd9Sstevel@tonic-gate 19057c478bd9Sstevel@tonic-gate bzero(&dw, sizeof (dwarf_t)); 19067c478bd9Sstevel@tonic-gate dw.dw_td = td; 19077c478bd9Sstevel@tonic-gate dw.dw_ptrsz = elf_ptrsz(elf); 19087c478bd9Sstevel@tonic-gate dw.dw_mfgtid_last = TID_MFGTID_BASE; 19097c478bd9Sstevel@tonic-gate dw.dw_tidhash = hash_new(TDESC_HASH_BUCKETS, tdesc_idhash, tdesc_idcmp); 19107c478bd9Sstevel@tonic-gate dw.dw_fwdhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash, 19117c478bd9Sstevel@tonic-gate tdesc_namecmp); 19127c478bd9Sstevel@tonic-gate dw.dw_enumhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash, 19137c478bd9Sstevel@tonic-gate tdesc_namecmp); 19147c478bd9Sstevel@tonic-gate 19157c478bd9Sstevel@tonic-gate if ((rc = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dw.dw_dw, 19167c478bd9Sstevel@tonic-gate &dw.dw_err)) == DW_DLV_NO_ENTRY) { 191753ffad05SRichard Lowe if (should_have_dwarf(elf)) { 19187c478bd9Sstevel@tonic-gate errno = ENOENT; 19197c478bd9Sstevel@tonic-gate return (-1); 192053ffad05SRichard Lowe } else { 192153ffad05SRichard Lowe return (0); 192253ffad05SRichard Lowe } 19237c478bd9Sstevel@tonic-gate } else if (rc != DW_DLV_OK) { 19247c478bd9Sstevel@tonic-gate if (dwarf_errno(dw.dw_err) == DW_DLE_DEBUG_INFO_NULL) { 19257c478bd9Sstevel@tonic-gate /* 19267c478bd9Sstevel@tonic-gate * There's no type data in the DWARF section, but 19277c478bd9Sstevel@tonic-gate * libdwarf is too clever to handle that properly. 19287c478bd9Sstevel@tonic-gate */ 19297c478bd9Sstevel@tonic-gate return (0); 19307c478bd9Sstevel@tonic-gate } 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate terminate("failed to initialize DWARF: %s\n", 19337c478bd9Sstevel@tonic-gate dwarf_errmsg(dw.dw_err)); 19347c478bd9Sstevel@tonic-gate } 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff, 19375257890aSRichard Lowe &addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_OK) 19385257890aSRichard Lowe terminate("file does not contain valid DWARF data: %s\n", 19395257890aSRichard Lowe dwarf_errmsg(dw.dw_err)); 19405257890aSRichard Lowe 194153ffad05SRichard Lowe /* 194253ffad05SRichard Lowe * Some compilers emit no DWARF for empty files, others emit an empty 194353ffad05SRichard Lowe * compilation unit. 194453ffad05SRichard Lowe */ 19455257890aSRichard Lowe if ((cu = die_sibling(&dw, NULL)) == NULL || 194653ffad05SRichard Lowe ((child = die_child(&dw, cu)) == NULL) && 194753ffad05SRichard Lowe should_have_dwarf(elf)) { 19487c478bd9Sstevel@tonic-gate terminate("file does not contain dwarf type data " 19497c478bd9Sstevel@tonic-gate "(try compiling with -g)\n"); 195053ffad05SRichard Lowe } else if (child == NULL) { 195153ffad05SRichard Lowe return (0); 195253ffad05SRichard Lowe } 19537c478bd9Sstevel@tonic-gate 19547c478bd9Sstevel@tonic-gate dw.dw_maxoff = nxthdr - 1; 19557c478bd9Sstevel@tonic-gate 19567c478bd9Sstevel@tonic-gate if (dw.dw_maxoff > TID_FILEMAX) 19577c478bd9Sstevel@tonic-gate terminate("file contains too many types\n"); 19587c478bd9Sstevel@tonic-gate 19597c478bd9Sstevel@tonic-gate debug(1, "DWARF version: %d\n", vers); 19607c478bd9Sstevel@tonic-gate if (vers != DWARF_VERSION) { 19617c478bd9Sstevel@tonic-gate terminate("file contains incompatible version %d DWARF code " 19627c478bd9Sstevel@tonic-gate "(version 2 required)\n", vers); 19637c478bd9Sstevel@tonic-gate } 19647c478bd9Sstevel@tonic-gate 19657c478bd9Sstevel@tonic-gate if (die_string(&dw, cu, DW_AT_producer, &prod, 0)) { 19667c478bd9Sstevel@tonic-gate debug(1, "DWARF emitter: %s\n", prod); 19677c478bd9Sstevel@tonic-gate free(prod); 19687c478bd9Sstevel@tonic-gate } 19697c478bd9Sstevel@tonic-gate 19707c478bd9Sstevel@tonic-gate if ((dw.dw_cuname = die_name(&dw, cu)) != NULL) { 19717c478bd9Sstevel@tonic-gate char *base = xstrdup(basename(dw.dw_cuname)); 19727c478bd9Sstevel@tonic-gate free(dw.dw_cuname); 19737c478bd9Sstevel@tonic-gate dw.dw_cuname = base; 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate debug(1, "CU name: %s\n", dw.dw_cuname); 19767c478bd9Sstevel@tonic-gate } 19777c478bd9Sstevel@tonic-gate 19787c478bd9Sstevel@tonic-gate die_create(&dw, child); 19797c478bd9Sstevel@tonic-gate 19807c478bd9Sstevel@tonic-gate if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff, 19817c478bd9Sstevel@tonic-gate &addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_NO_ENTRY) 19827c478bd9Sstevel@tonic-gate terminate("multiple compilation units not supported\n"); 19837c478bd9Sstevel@tonic-gate 19847c478bd9Sstevel@tonic-gate (void) dwarf_finish(dw.dw_dw, &dw.dw_err); 19857c478bd9Sstevel@tonic-gate 19867c478bd9Sstevel@tonic-gate die_resolve(&dw); 19877c478bd9Sstevel@tonic-gate 1988e824d57fSjohnlev cvt_fixups(td, dw.dw_ptrsz); 1989e824d57fSjohnlev 19907c478bd9Sstevel@tonic-gate /* leak the dwarf_t */ 19917c478bd9Sstevel@tonic-gate 19927c478bd9Sstevel@tonic-gate return (0); 19937c478bd9Sstevel@tonic-gate } 1994