10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1882Sjohnlev * Common Development and Distribution License (the "License"). 6*1882Sjohnlev * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*1882Sjohnlev * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * This file is a sewer. 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include <limits.h> 330Sstevel@tonic-gate #include <stdarg.h> 340Sstevel@tonic-gate #include <stdio.h> 350Sstevel@tonic-gate #include <assert.h> 360Sstevel@tonic-gate #include <strings.h> 370Sstevel@tonic-gate #include <setjmp.h> 380Sstevel@tonic-gate #include <ctype.h> 390Sstevel@tonic-gate #include <uts/common/sys/ctf.h> 400Sstevel@tonic-gate 410Sstevel@tonic-gate #include "ctftools.h" 420Sstevel@tonic-gate #include "memory.h" 430Sstevel@tonic-gate #include "list.h" 440Sstevel@tonic-gate 450Sstevel@tonic-gate #define HASH(NUM) ((int)(NUM & (BUCKETS - 1))) 460Sstevel@tonic-gate #define BUCKETS 128 470Sstevel@tonic-gate 480Sstevel@tonic-gate #define TYPEPAIRMULT 10000 490Sstevel@tonic-gate #define MAKETYPEID(file, num) ((file) * TYPEPAIRMULT + num) 500Sstevel@tonic-gate #define TYPEFILE(tid) ((tid) / TYPEPAIRMULT) 510Sstevel@tonic-gate #define TYPENUM(tid) ((tid) % TYPEPAIRMULT) 520Sstevel@tonic-gate 530Sstevel@tonic-gate #define expected(a, b, c) _expected(a, b, c, __LINE__) 540Sstevel@tonic-gate 550Sstevel@tonic-gate static int faketypenumber = 100000000; 560Sstevel@tonic-gate 570Sstevel@tonic-gate static tdesc_t *hash_table[BUCKETS]; 580Sstevel@tonic-gate static tdesc_t *name_table[BUCKETS]; 590Sstevel@tonic-gate 600Sstevel@tonic-gate list_t *typedbitfldmems; 610Sstevel@tonic-gate 620Sstevel@tonic-gate static void reset(void); 630Sstevel@tonic-gate static jmp_buf resetbuf; 640Sstevel@tonic-gate 650Sstevel@tonic-gate static char *soudef(char *cp, stabtype_t type, tdesc_t **rtdp); 660Sstevel@tonic-gate static void enumdef(char *cp, tdesc_t **rtdp); 670Sstevel@tonic-gate static int compute_sum(char *w); 680Sstevel@tonic-gate tdesc_t *lookupname(char *name); 690Sstevel@tonic-gate 700Sstevel@tonic-gate static char *number(char *cp, int *n); 710Sstevel@tonic-gate static char *name(char *cp, char **w); 720Sstevel@tonic-gate static char *id(char *cp, int *h); 730Sstevel@tonic-gate static char *whitesp(char *cp); 740Sstevel@tonic-gate static void addhash(tdesc_t *tdp, int num); 750Sstevel@tonic-gate static int tagadd(char *w, int h, tdesc_t *tdp); 760Sstevel@tonic-gate static char *tdefdecl(char *cp, int h, tdesc_t **rtdp); 770Sstevel@tonic-gate static char *intrinsic(char *cp, tdesc_t **rtdp); 780Sstevel@tonic-gate static char *arraydef(char *cp, tdesc_t **rtdp); 790Sstevel@tonic-gate 800Sstevel@tonic-gate extern int debug_level; 810Sstevel@tonic-gate int debug_parse = DEBUG_PARSE; 820Sstevel@tonic-gate 830Sstevel@tonic-gate /*PRINTFLIKE3*/ 840Sstevel@tonic-gate static void 850Sstevel@tonic-gate parse_debug(int level, char *cp, char *fmt, ...) 860Sstevel@tonic-gate { 870Sstevel@tonic-gate va_list ap; 880Sstevel@tonic-gate char buf[1024]; 890Sstevel@tonic-gate char tmp[32]; 900Sstevel@tonic-gate int i; 910Sstevel@tonic-gate 920Sstevel@tonic-gate if (level > debug_level || !debug_parse) 930Sstevel@tonic-gate return; 940Sstevel@tonic-gate 950Sstevel@tonic-gate if (cp != NULL) { 960Sstevel@tonic-gate for (i = 0; i < 30; i++) { 970Sstevel@tonic-gate if (cp[i] == '\0') 980Sstevel@tonic-gate break; 990Sstevel@tonic-gate if (!iscntrl(cp[i])) 1000Sstevel@tonic-gate tmp[i] = cp[i]; 1010Sstevel@tonic-gate } 1020Sstevel@tonic-gate tmp[i] = '\0'; 1030Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s [cp='%s']\n", fmt, tmp); 1040Sstevel@tonic-gate } else { 1050Sstevel@tonic-gate strcpy(buf, fmt); 1060Sstevel@tonic-gate strcat(buf, "\n"); 1070Sstevel@tonic-gate } 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate va_start(ap, fmt); 1100Sstevel@tonic-gate vadebug(level, buf, ap); 1110Sstevel@tonic-gate va_end(ap); 1120Sstevel@tonic-gate } 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate /* Report unexpected syntax in stabs. */ 1150Sstevel@tonic-gate static void 1160Sstevel@tonic-gate _expected( 1170Sstevel@tonic-gate char *who, /* what function, or part thereof, is reporting */ 1180Sstevel@tonic-gate char *what, /* what was expected */ 1190Sstevel@tonic-gate char *where, /* where we were in the line of input */ 1200Sstevel@tonic-gate int line) 1210Sstevel@tonic-gate { 1220Sstevel@tonic-gate fprintf(stderr, "%s, expecting \"%s\" at \"%s\"\n", who, what, where); 1230Sstevel@tonic-gate fprintf(stderr, "code line: %d, file %s\n", line, 1240Sstevel@tonic-gate (curhdr ? curhdr : "NO FILE")); 1250Sstevel@tonic-gate reset(); 1260Sstevel@tonic-gate } 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate /*ARGSUSED*/ 1290Sstevel@tonic-gate void 1300Sstevel@tonic-gate parse_init(tdata_t *td) 1310Sstevel@tonic-gate { 1320Sstevel@tonic-gate int i; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate for (i = 0; i < BUCKETS; i++) { 1350Sstevel@tonic-gate hash_table[i] = NULL; 1360Sstevel@tonic-gate name_table[i] = NULL; 1370Sstevel@tonic-gate } 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate if (typedbitfldmems != NULL) { 1400Sstevel@tonic-gate list_free(typedbitfldmems, NULL, NULL); 1410Sstevel@tonic-gate typedbitfldmems = NULL; 1420Sstevel@tonic-gate } 1430Sstevel@tonic-gate } 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate void 1460Sstevel@tonic-gate parse_finish(tdata_t *td) 1470Sstevel@tonic-gate { 1480Sstevel@tonic-gate td->td_nextid = ++faketypenumber; 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate static tdesc_t * 1520Sstevel@tonic-gate unres_new(int tid) 1530Sstevel@tonic-gate { 1540Sstevel@tonic-gate tdesc_t *tdp; 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate tdp = xcalloc(sizeof (*tdp)); 1570Sstevel@tonic-gate tdp->t_type = TYPEDEF_UNRES; 1580Sstevel@tonic-gate tdp->t_id = tid; 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate return (tdp); 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate char * 1640Sstevel@tonic-gate read_tid(char *cp, tdesc_t **tdpp) 1650Sstevel@tonic-gate { 1660Sstevel@tonic-gate tdesc_t *tdp; 1670Sstevel@tonic-gate int tid; 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate cp = id(cp, &tid); 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate assert(tid != 0); 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate if (*cp == '=') { 1740Sstevel@tonic-gate if (!(cp = tdefdecl(cp + 1, tid, &tdp))) 1750Sstevel@tonic-gate return (NULL); 1760Sstevel@tonic-gate if (tdp->t_id && tdp->t_id != tid) { 1770Sstevel@tonic-gate tdesc_t *ntdp = xcalloc(sizeof (*ntdp)); 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 1800Sstevel@tonic-gate ntdp->t_tdesc = tdp; 1810Sstevel@tonic-gate tdp = ntdp; 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate addhash(tdp, tid); 1840Sstevel@tonic-gate } else if ((tdp = lookup(tid)) == NULL) 1850Sstevel@tonic-gate tdp = unres_new(tid); 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate *tdpp = tdp; 1880Sstevel@tonic-gate return (cp); 1890Sstevel@tonic-gate } 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate static iitype_t 1920Sstevel@tonic-gate parse_fun(char *cp, iidesc_t *ii) 1930Sstevel@tonic-gate { 1940Sstevel@tonic-gate iitype_t iitype; 1950Sstevel@tonic-gate tdesc_t *tdp; 1960Sstevel@tonic-gate tdesc_t **args = NULL; 1970Sstevel@tonic-gate int nargs = 0; 1980Sstevel@tonic-gate int va = 0; 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate /* 2010Sstevel@tonic-gate * name:P prototype 2020Sstevel@tonic-gate * name:F global function 2030Sstevel@tonic-gate * name:f static function 2040Sstevel@tonic-gate */ 2050Sstevel@tonic-gate switch (*cp++) { 2060Sstevel@tonic-gate case 'P': 2070Sstevel@tonic-gate iitype = II_NOT; /* not interesting */ 2080Sstevel@tonic-gate break; 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate case 'F': 2110Sstevel@tonic-gate iitype = II_GFUN; 2120Sstevel@tonic-gate break; 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate case 'f': 2150Sstevel@tonic-gate iitype = II_SFUN; 2160Sstevel@tonic-gate break; 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate default: 2190Sstevel@tonic-gate expected("parse_nfun", "[PfF]", cp - 1); 2200Sstevel@tonic-gate } 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate if (!(cp = read_tid(cp, &tdp))) 2230Sstevel@tonic-gate return (-1); 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate if (*cp) 2260Sstevel@tonic-gate args = xmalloc(sizeof (tdesc_t *) * FUNCARG_DEF); 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate while (*cp && *++cp) { 2290Sstevel@tonic-gate if (*cp == '0') { 2300Sstevel@tonic-gate va = 1; 2310Sstevel@tonic-gate continue; 2320Sstevel@tonic-gate } 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate nargs++; 2350Sstevel@tonic-gate if (nargs > FUNCARG_DEF) 2360Sstevel@tonic-gate args = xrealloc(args, sizeof (tdesc_t *) * nargs); 2370Sstevel@tonic-gate if (!(cp = read_tid(cp, &args[nargs - 1]))) 2380Sstevel@tonic-gate return (-1); 2390Sstevel@tonic-gate } 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate ii->ii_type = iitype; 2420Sstevel@tonic-gate ii->ii_dtype = tdp; 2430Sstevel@tonic-gate ii->ii_nargs = nargs; 2440Sstevel@tonic-gate ii->ii_args = args; 2450Sstevel@tonic-gate ii->ii_vargs = va; 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate return (iitype); 2480Sstevel@tonic-gate } 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate static iitype_t 2510Sstevel@tonic-gate parse_sym(char *cp, iidesc_t *ii) 2520Sstevel@tonic-gate { 2530Sstevel@tonic-gate tdesc_t *tdp; 2540Sstevel@tonic-gate iitype_t iitype; 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate /* 2570Sstevel@tonic-gate * name:G global variable 2580Sstevel@tonic-gate * name:S static variable 2590Sstevel@tonic-gate */ 2600Sstevel@tonic-gate switch (*cp++) { 2610Sstevel@tonic-gate case 'G': 2620Sstevel@tonic-gate iitype = II_GVAR; 2630Sstevel@tonic-gate break; 2640Sstevel@tonic-gate case 'S': 2650Sstevel@tonic-gate iitype = II_SVAR; 2660Sstevel@tonic-gate break; 2670Sstevel@tonic-gate case 'p': 2680Sstevel@tonic-gate iitype = II_PSYM; 2690Sstevel@tonic-gate break; 2700Sstevel@tonic-gate case '(': 2710Sstevel@tonic-gate cp--; 2720Sstevel@tonic-gate /*FALLTHROUGH*/ 2730Sstevel@tonic-gate case 'r': 2740Sstevel@tonic-gate case 'V': 2750Sstevel@tonic-gate iitype = II_NOT; /* not interesting */ 2760Sstevel@tonic-gate break; 2770Sstevel@tonic-gate default: 2780Sstevel@tonic-gate expected("parse_sym", "[GprSV(]", cp - 1); 2790Sstevel@tonic-gate } 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate if (!(cp = read_tid(cp, &tdp))) 2820Sstevel@tonic-gate return (-1); 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate ii->ii_type = iitype; 2850Sstevel@tonic-gate ii->ii_dtype = tdp; 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate return (iitype); 2880Sstevel@tonic-gate } 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate static iitype_t 2910Sstevel@tonic-gate parse_type(char *cp, iidesc_t *ii) 2920Sstevel@tonic-gate { 2930Sstevel@tonic-gate tdesc_t *tdp, *ntdp; 2940Sstevel@tonic-gate int tid; 2950Sstevel@tonic-gate 2960Sstevel@tonic-gate if (*cp++ != 't') 2970Sstevel@tonic-gate expected("parse_type", "t (type)", cp - 1); 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate cp = id(cp, &tid); 3000Sstevel@tonic-gate if ((tdp = lookup(tid)) == NULL) { 3010Sstevel@tonic-gate if (*cp++ != '=') 3020Sstevel@tonic-gate expected("parse_type", "= (definition)", cp - 1); 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate (void) tdefdecl(cp, tid, &tdp); 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate if (tdp->t_id == tid) { 3070Sstevel@tonic-gate assert(tdp->t_type != TYPEDEF); 3080Sstevel@tonic-gate assert(!lookup(tdp->t_id)); 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate if (!streq(tdp->t_name, ii->ii_name)) { 3110Sstevel@tonic-gate ntdp = xcalloc(sizeof (*ntdp)); 3120Sstevel@tonic-gate ntdp->t_name = xstrdup(ii->ii_name); 3130Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 3140Sstevel@tonic-gate ntdp->t_tdesc = tdp; 3150Sstevel@tonic-gate tdp->t_id = faketypenumber++; 3160Sstevel@tonic-gate tdp = ntdp; 3170Sstevel@tonic-gate } 3180Sstevel@tonic-gate } else if (tdp->t_id == 0) { 3190Sstevel@tonic-gate assert(tdp->t_type == FORWARD || 3200Sstevel@tonic-gate tdp->t_type == INTRINSIC); 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate if (tdp->t_name && !streq(tdp->t_name, ii->ii_name)) { 3230Sstevel@tonic-gate ntdp = xcalloc(sizeof (*ntdp)); 3240Sstevel@tonic-gate ntdp->t_name = xstrdup(ii->ii_name); 3250Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 3260Sstevel@tonic-gate ntdp->t_tdesc = tdp; 3270Sstevel@tonic-gate tdp->t_id = faketypenumber++; 3280Sstevel@tonic-gate tdp = ntdp; 3290Sstevel@tonic-gate } 3300Sstevel@tonic-gate } else if (tdp->t_id != tid) { 3310Sstevel@tonic-gate ntdp = xcalloc(sizeof (*ntdp)); 3320Sstevel@tonic-gate ntdp->t_name = xstrdup(ii->ii_name); 3330Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 3340Sstevel@tonic-gate ntdp->t_tdesc = tdp; 3350Sstevel@tonic-gate tdp = ntdp; 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate if (tagadd(ii->ii_name, tid, tdp) < 0) 3390Sstevel@tonic-gate return (-1); 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate ii->ii_type = II_TYPE; 3430Sstevel@tonic-gate ii->ii_dtype = tdp; 3440Sstevel@tonic-gate return (II_TYPE); 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate static iitype_t 3480Sstevel@tonic-gate parse_sou(char *cp, iidesc_t *idp) 3490Sstevel@tonic-gate { 3500Sstevel@tonic-gate tdesc_t *rtdp; 3510Sstevel@tonic-gate int tid; 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate if (*cp++ != 'T') 3540Sstevel@tonic-gate expected("parse_sou", "T (sou)", cp - 1); 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate cp = id(cp, &tid); 3570Sstevel@tonic-gate if (*cp++ != '=') 3580Sstevel@tonic-gate expected("parse_sou", "= (definition)", cp - 1); 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate parse_debug(1, NULL, "parse_sou: declaring '%s'", idp->ii_name ? 3610Sstevel@tonic-gate idp->ii_name : "(anon)"); 3620Sstevel@tonic-gate if ((rtdp = lookup(tid)) != NULL) { 3630Sstevel@tonic-gate if (idp->ii_name != NULL) { 3640Sstevel@tonic-gate if (rtdp->t_name != NULL && 3650Sstevel@tonic-gate strcmp(rtdp->t_name, idp->ii_name) != 0) { 3660Sstevel@tonic-gate tdesc_t *tdp; 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate tdp = xcalloc(sizeof (*tdp)); 3690Sstevel@tonic-gate tdp->t_name = xstrdup(idp->ii_name); 3700Sstevel@tonic-gate tdp->t_type = TYPEDEF; 3710Sstevel@tonic-gate tdp->t_tdesc = rtdp; 3720Sstevel@tonic-gate addhash(tdp, tid); /* for *(x,y) types */ 3730Sstevel@tonic-gate parse_debug(3, NULL, " %s defined as %s(%d)", 374*1882Sjohnlev idp->ii_name, tdesc_name(rtdp), tid); 3750Sstevel@tonic-gate } else if (rtdp->t_name == NULL) { 3760Sstevel@tonic-gate rtdp->t_name = xstrdup(idp->ii_name); 3770Sstevel@tonic-gate addhash(rtdp, tid); 3780Sstevel@tonic-gate } 3790Sstevel@tonic-gate } 3800Sstevel@tonic-gate } else { 3810Sstevel@tonic-gate rtdp = xcalloc(sizeof (*rtdp)); 3820Sstevel@tonic-gate rtdp->t_name = idp->ii_name ? xstrdup(idp->ii_name) : NULL; 3830Sstevel@tonic-gate addhash(rtdp, tid); 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate switch (*cp++) { 3870Sstevel@tonic-gate case 's': 3880Sstevel@tonic-gate (void) soudef(cp, STRUCT, &rtdp); 3890Sstevel@tonic-gate break; 3900Sstevel@tonic-gate case 'u': 3910Sstevel@tonic-gate (void) soudef(cp, UNION, &rtdp); 3920Sstevel@tonic-gate break; 3930Sstevel@tonic-gate case 'e': 3940Sstevel@tonic-gate enumdef(cp, &rtdp); 3950Sstevel@tonic-gate break; 3960Sstevel@tonic-gate default: 3970Sstevel@tonic-gate expected("parse_sou", "<tag type s/u/e>", cp - 1); 3980Sstevel@tonic-gate break; 3990Sstevel@tonic-gate } 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate idp->ii_type = II_SOU; 4020Sstevel@tonic-gate idp->ii_dtype = rtdp; 4030Sstevel@tonic-gate return (II_SOU); 4040Sstevel@tonic-gate } 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate int 4070Sstevel@tonic-gate parse_stab(stab_t *stab, char *cp, iidesc_t **iidescp) 4080Sstevel@tonic-gate { 4090Sstevel@tonic-gate iidesc_t *ii = NULL; 4100Sstevel@tonic-gate iitype_t (*parse)(char *, iidesc_t *); 4110Sstevel@tonic-gate int rc; 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate /* 4140Sstevel@tonic-gate * set up for reset() 4150Sstevel@tonic-gate */ 4160Sstevel@tonic-gate if (setjmp(resetbuf)) 4170Sstevel@tonic-gate return (-1); 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate cp = whitesp(cp); 4200Sstevel@tonic-gate ii = iidesc_new(NULL); 4210Sstevel@tonic-gate cp = name(cp, &ii->ii_name); 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate switch (stab->n_type) { 4240Sstevel@tonic-gate case N_FUN: 4250Sstevel@tonic-gate parse = parse_fun; 4260Sstevel@tonic-gate break; 4270Sstevel@tonic-gate 4280Sstevel@tonic-gate case N_LSYM: 4290Sstevel@tonic-gate if (*cp == 't') 4300Sstevel@tonic-gate parse = parse_type; 4310Sstevel@tonic-gate else if (*cp == 'T') 4320Sstevel@tonic-gate parse = parse_sou; 4330Sstevel@tonic-gate else 4340Sstevel@tonic-gate parse = parse_sym; 4350Sstevel@tonic-gate break; 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate case N_GSYM: 4380Sstevel@tonic-gate case N_LCSYM: 4390Sstevel@tonic-gate case N_PSYM: 4400Sstevel@tonic-gate case N_ROSYM: 4410Sstevel@tonic-gate case N_RSYM: 4420Sstevel@tonic-gate case N_STSYM: 4430Sstevel@tonic-gate parse = parse_sym; 4440Sstevel@tonic-gate break; 4450Sstevel@tonic-gate default: 4460Sstevel@tonic-gate parse_debug(1, cp, "Unknown stab type %#x", stab->n_type); 4470Sstevel@tonic-gate bzero(&resetbuf, sizeof (resetbuf)); 4480Sstevel@tonic-gate return (-1); 4490Sstevel@tonic-gate } 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate rc = parse(cp, ii); 4520Sstevel@tonic-gate bzero(&resetbuf, sizeof (resetbuf)); 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate if (rc < 0 || ii->ii_type == II_NOT) { 4550Sstevel@tonic-gate iidesc_free(ii, NULL); 4560Sstevel@tonic-gate return (rc); 4570Sstevel@tonic-gate } 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate *iidescp = ii; 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate return (1); 4620Sstevel@tonic-gate } 4630Sstevel@tonic-gate 4640Sstevel@tonic-gate /* 4650Sstevel@tonic-gate * Check if we have this node in the hash table already 4660Sstevel@tonic-gate */ 4670Sstevel@tonic-gate tdesc_t * 4680Sstevel@tonic-gate lookup(int h) 4690Sstevel@tonic-gate { 4700Sstevel@tonic-gate int bucket = HASH(h); 4710Sstevel@tonic-gate tdesc_t *tdp = hash_table[bucket]; 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate while (tdp != NULL) { 4740Sstevel@tonic-gate if (tdp->t_id == h) 4750Sstevel@tonic-gate return (tdp); 4760Sstevel@tonic-gate tdp = tdp->t_hash; 4770Sstevel@tonic-gate } 4780Sstevel@tonic-gate return (NULL); 4790Sstevel@tonic-gate } 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate static char * 4820Sstevel@tonic-gate whitesp(char *cp) 4830Sstevel@tonic-gate { 4840Sstevel@tonic-gate char c; 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate for (c = *cp++; isspace(c); c = *cp++); 4870Sstevel@tonic-gate --cp; 4880Sstevel@tonic-gate return (cp); 4890Sstevel@tonic-gate } 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate static char * 4920Sstevel@tonic-gate name(char *cp, char **w) 4930Sstevel@tonic-gate { 4940Sstevel@tonic-gate char *new, *orig, c; 4950Sstevel@tonic-gate int len; 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate orig = cp; 4980Sstevel@tonic-gate c = *cp++; 4990Sstevel@tonic-gate if (c == ':') 5000Sstevel@tonic-gate *w = NULL; 5010Sstevel@tonic-gate else if (isalpha(c) || strchr("_.$", c)) { 5020Sstevel@tonic-gate for (c = *cp++; isalnum(c) || strchr(" _.$", c); c = *cp++) 5030Sstevel@tonic-gate ; 5040Sstevel@tonic-gate if (c != ':') 5050Sstevel@tonic-gate reset(); 5060Sstevel@tonic-gate len = cp - orig; 5070Sstevel@tonic-gate new = xmalloc(len); 5080Sstevel@tonic-gate while (orig < cp - 1) 5090Sstevel@tonic-gate *new++ = *orig++; 5100Sstevel@tonic-gate *new = '\0'; 5110Sstevel@tonic-gate *w = new - (len - 1); 5120Sstevel@tonic-gate } else 5130Sstevel@tonic-gate reset(); 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate return (cp); 5160Sstevel@tonic-gate } 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate static char * 5190Sstevel@tonic-gate number(char *cp, int *n) 5200Sstevel@tonic-gate { 5210Sstevel@tonic-gate char *next; 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate *n = (int)strtol(cp, &next, 10); 5240Sstevel@tonic-gate if (next == cp) 5250Sstevel@tonic-gate expected("number", "<number>", cp); 5260Sstevel@tonic-gate return (next); 5270Sstevel@tonic-gate } 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate static char * 5300Sstevel@tonic-gate id(char *cp, int *h) 5310Sstevel@tonic-gate { 5320Sstevel@tonic-gate int n1, n2; 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate if (*cp == '(') { /* SunPro style */ 5350Sstevel@tonic-gate cp++; 5360Sstevel@tonic-gate cp = number(cp, &n1); 5370Sstevel@tonic-gate if (*cp++ != ',') 5380Sstevel@tonic-gate expected("id", ",", cp - 1); 5390Sstevel@tonic-gate cp = number(cp, &n2); 5400Sstevel@tonic-gate if (*cp++ != ')') 5410Sstevel@tonic-gate expected("id", ")", cp - 1); 5420Sstevel@tonic-gate *h = MAKETYPEID(n1, n2); 5430Sstevel@tonic-gate } else if (isdigit(*cp)) { /* gcc style */ 5440Sstevel@tonic-gate cp = number(cp, &n1); 5450Sstevel@tonic-gate *h = n1; 5460Sstevel@tonic-gate } else { 5470Sstevel@tonic-gate expected("id", "(/0-9", cp); 5480Sstevel@tonic-gate } 5490Sstevel@tonic-gate return (cp); 5500Sstevel@tonic-gate } 5510Sstevel@tonic-gate 5520Sstevel@tonic-gate static int 5530Sstevel@tonic-gate tagadd(char *w, int h, tdesc_t *tdp) 5540Sstevel@tonic-gate { 5550Sstevel@tonic-gate tdesc_t *otdp; 5560Sstevel@tonic-gate 5570Sstevel@tonic-gate tdp->t_name = w; 5580Sstevel@tonic-gate if (!(otdp = lookup(h))) 5590Sstevel@tonic-gate addhash(tdp, h); 5600Sstevel@tonic-gate else if (otdp != tdp) { 5610Sstevel@tonic-gate warning("duplicate entry\n"); 562*1882Sjohnlev warning(" old: %s %d (%d,%d)\n", tdesc_name(otdp), 5630Sstevel@tonic-gate otdp->t_type, TYPEFILE(otdp->t_id), TYPENUM(otdp->t_id)); 564*1882Sjohnlev warning(" new: %s %d (%d,%d)\n", tdesc_name(tdp), 5650Sstevel@tonic-gate tdp->t_type, TYPEFILE(tdp->t_id), TYPENUM(tdp->t_id)); 5660Sstevel@tonic-gate return (-1); 5670Sstevel@tonic-gate } 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate return (0); 5700Sstevel@tonic-gate } 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate static char * 5730Sstevel@tonic-gate tdefdecl(char *cp, int h, tdesc_t **rtdp) 5740Sstevel@tonic-gate { 5750Sstevel@tonic-gate tdesc_t *ntdp; 5760Sstevel@tonic-gate char *w; 5770Sstevel@tonic-gate int c, h2; 5780Sstevel@tonic-gate char type; 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate parse_debug(3, cp, "tdefdecl h=%d", h); 5810Sstevel@tonic-gate 5820Sstevel@tonic-gate /* Type codes */ 5830Sstevel@tonic-gate switch (type = *cp) { 5840Sstevel@tonic-gate case 'b': /* integer */ 5850Sstevel@tonic-gate case 'R': /* fp */ 5860Sstevel@tonic-gate cp = intrinsic(cp, rtdp); 5870Sstevel@tonic-gate break; 5880Sstevel@tonic-gate case '(': /* equiv to another type */ 5890Sstevel@tonic-gate cp = id(cp, &h2); 5900Sstevel@tonic-gate ntdp = lookup(h2); 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate if (ntdp != NULL && *cp == '=') { 5930Sstevel@tonic-gate if (ntdp->t_type == FORWARD && *(cp + 1) == 'x') { 5940Sstevel@tonic-gate /* 5950Sstevel@tonic-gate * The 6.2 compiler, and possibly others, will 5960Sstevel@tonic-gate * sometimes emit the same stab for a forward 5970Sstevel@tonic-gate * declaration twice. That is, "(1,2)=xsfoo:" 5980Sstevel@tonic-gate * will sometimes show up in two different 5990Sstevel@tonic-gate * places. This is, of course, quite fun. We 6000Sstevel@tonic-gate * want CTF to work in spite of the compiler, 6010Sstevel@tonic-gate * so we'll let this one through. 6020Sstevel@tonic-gate */ 6030Sstevel@tonic-gate char *c2 = cp + 2; 6040Sstevel@tonic-gate char *nm; 6050Sstevel@tonic-gate 6060Sstevel@tonic-gate if (!strchr("sue", *c2++)) { 6070Sstevel@tonic-gate expected("tdefdecl/x-redefine", "[sue]", 6080Sstevel@tonic-gate c2 - 1); 6090Sstevel@tonic-gate } 6100Sstevel@tonic-gate 6110Sstevel@tonic-gate c2 = name(c2, &nm); 6120Sstevel@tonic-gate if (strcmp(nm, ntdp->t_name) != 0) { 6130Sstevel@tonic-gate terminate("Stabs error: Attempt to " 6140Sstevel@tonic-gate "redefine type (%d,%d) as " 6150Sstevel@tonic-gate "something else: %s\n", 6160Sstevel@tonic-gate TYPEFILE(h2), TYPENUM(h2), 6170Sstevel@tonic-gate c2 - 1); 6180Sstevel@tonic-gate } 6190Sstevel@tonic-gate free(nm); 6200Sstevel@tonic-gate 6210Sstevel@tonic-gate h2 = faketypenumber++; 6220Sstevel@tonic-gate ntdp = NULL; 6230Sstevel@tonic-gate } else { 6240Sstevel@tonic-gate terminate("Stabs error: Attempting to " 6250Sstevel@tonic-gate "redefine type (%d,%d)\n", TYPEFILE(h2), 6260Sstevel@tonic-gate TYPENUM(h2)); 6270Sstevel@tonic-gate } 6280Sstevel@tonic-gate } 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate if (ntdp == NULL) { /* if that type isn't defined yet */ 6310Sstevel@tonic-gate if (*cp != '=') { 6320Sstevel@tonic-gate /* record it as unresolved */ 6330Sstevel@tonic-gate parse_debug(3, NULL, "tdefdecl unres type %d", 6340Sstevel@tonic-gate h2); 6350Sstevel@tonic-gate *rtdp = calloc(sizeof (**rtdp), 1); 6360Sstevel@tonic-gate (*rtdp)->t_type = TYPEDEF_UNRES; 6370Sstevel@tonic-gate (*rtdp)->t_id = h2; 6380Sstevel@tonic-gate break; 6390Sstevel@tonic-gate } else 6400Sstevel@tonic-gate cp++; 6410Sstevel@tonic-gate 6420Sstevel@tonic-gate /* define a new type */ 6430Sstevel@tonic-gate cp = tdefdecl(cp, h2, rtdp); 6440Sstevel@tonic-gate if ((*rtdp)->t_id && (*rtdp)->t_id != h2) { 6450Sstevel@tonic-gate ntdp = calloc(sizeof (*ntdp), 1); 6460Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 6470Sstevel@tonic-gate ntdp->t_tdesc = *rtdp; 6480Sstevel@tonic-gate *rtdp = ntdp; 6490Sstevel@tonic-gate } 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate addhash(*rtdp, h2); 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate } else { /* that type is already defined */ 6540Sstevel@tonic-gate if (ntdp->t_type != TYPEDEF || ntdp->t_name != NULL) { 6550Sstevel@tonic-gate *rtdp = ntdp; 6560Sstevel@tonic-gate } else { 6570Sstevel@tonic-gate parse_debug(3, NULL, 6580Sstevel@tonic-gate "No duplicate typedef anon for ref"); 6590Sstevel@tonic-gate *rtdp = ntdp; 6600Sstevel@tonic-gate } 6610Sstevel@tonic-gate } 6620Sstevel@tonic-gate break; 6630Sstevel@tonic-gate case '*': 6640Sstevel@tonic-gate ntdp = NULL; 6650Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 6660Sstevel@tonic-gate if (ntdp == NULL) 6670Sstevel@tonic-gate expected("tdefdecl/*", "id", cp); 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate if (!ntdp->t_id) 6700Sstevel@tonic-gate ntdp->t_id = faketypenumber++; 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 6730Sstevel@tonic-gate (*rtdp)->t_type = POINTER; 6740Sstevel@tonic-gate (*rtdp)->t_size = 0; 6750Sstevel@tonic-gate (*rtdp)->t_id = h; 6760Sstevel@tonic-gate (*rtdp)->t_tdesc = ntdp; 6770Sstevel@tonic-gate break; 6780Sstevel@tonic-gate case 'f': 6790Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 6800Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 6810Sstevel@tonic-gate (*rtdp)->t_type = FUNCTION; 6820Sstevel@tonic-gate (*rtdp)->t_size = 0; 6830Sstevel@tonic-gate (*rtdp)->t_id = h; 6840Sstevel@tonic-gate (*rtdp)->t_fndef = xcalloc(sizeof (fndef_t)); 6850Sstevel@tonic-gate /* 6860Sstevel@tonic-gate * The 6.1 compiler will sometimes generate incorrect stabs for 6870Sstevel@tonic-gate * function pointers (it'll get the return type wrong). This 6880Sstevel@tonic-gate * causes merges to fail. We therefore treat function pointers 6890Sstevel@tonic-gate * as if they all point to functions that return int. When 6900Sstevel@tonic-gate * 4432549 is fixed, the lookupname() call below should be 6910Sstevel@tonic-gate * replaced with `ntdp'. 6920Sstevel@tonic-gate */ 6930Sstevel@tonic-gate (*rtdp)->t_fndef->fn_ret = lookupname("int"); 6940Sstevel@tonic-gate break; 6950Sstevel@tonic-gate case 'a': 6960Sstevel@tonic-gate case 'z': 6970Sstevel@tonic-gate cp++; 6980Sstevel@tonic-gate if (*cp++ != 'r') 6990Sstevel@tonic-gate expected("tdefdecl/[az]", "r", cp - 1); 7000Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7010Sstevel@tonic-gate (*rtdp)->t_type = ARRAY; 7020Sstevel@tonic-gate (*rtdp)->t_id = h; 7030Sstevel@tonic-gate cp = arraydef(cp, rtdp); 7040Sstevel@tonic-gate break; 7050Sstevel@tonic-gate case 'x': 7060Sstevel@tonic-gate c = *++cp; 7070Sstevel@tonic-gate if (c != 's' && c != 'u' && c != 'e') 7080Sstevel@tonic-gate expected("tdefdecl/x", "[sue]", cp - 1); 7090Sstevel@tonic-gate cp = name(cp + 1, &w); 7100Sstevel@tonic-gate 7110Sstevel@tonic-gate ntdp = xcalloc(sizeof (*ntdp)); 7120Sstevel@tonic-gate ntdp->t_type = FORWARD; 7130Sstevel@tonic-gate ntdp->t_name = w; 7140Sstevel@tonic-gate /* 7150Sstevel@tonic-gate * We explicitly don't set t_id here - the caller will do it. 7160Sstevel@tonic-gate * The caller may want to use a real type ID, or they may 7170Sstevel@tonic-gate * choose to make one up. 7180Sstevel@tonic-gate */ 7190Sstevel@tonic-gate 7200Sstevel@tonic-gate *rtdp = ntdp; 7210Sstevel@tonic-gate break; 7220Sstevel@tonic-gate 7230Sstevel@tonic-gate case 'B': /* volatile */ 7240Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 7250Sstevel@tonic-gate 7260Sstevel@tonic-gate if (!ntdp->t_id) 7270Sstevel@tonic-gate ntdp->t_id = faketypenumber++; 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7300Sstevel@tonic-gate (*rtdp)->t_type = VOLATILE; 7310Sstevel@tonic-gate (*rtdp)->t_size = 0; 7320Sstevel@tonic-gate (*rtdp)->t_tdesc = ntdp; 7330Sstevel@tonic-gate (*rtdp)->t_id = h; 7340Sstevel@tonic-gate break; 7350Sstevel@tonic-gate 7360Sstevel@tonic-gate case 'k': /* const */ 7370Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate if (!ntdp->t_id) 7400Sstevel@tonic-gate ntdp->t_id = faketypenumber++; 7410Sstevel@tonic-gate 7420Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7430Sstevel@tonic-gate (*rtdp)->t_type = CONST; 7440Sstevel@tonic-gate (*rtdp)->t_size = 0; 7450Sstevel@tonic-gate (*rtdp)->t_tdesc = ntdp; 7460Sstevel@tonic-gate (*rtdp)->t_id = h; 7470Sstevel@tonic-gate break; 7480Sstevel@tonic-gate 7490Sstevel@tonic-gate case 'K': /* restricted */ 7500Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 7510Sstevel@tonic-gate 7520Sstevel@tonic-gate if (!ntdp->t_id) 7530Sstevel@tonic-gate ntdp->t_id = faketypenumber++; 7540Sstevel@tonic-gate 7550Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7560Sstevel@tonic-gate (*rtdp)->t_type = RESTRICT; 7570Sstevel@tonic-gate (*rtdp)->t_size = 0; 7580Sstevel@tonic-gate (*rtdp)->t_tdesc = ntdp; 7590Sstevel@tonic-gate (*rtdp)->t_id = h; 7600Sstevel@tonic-gate break; 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate case 'u': 7630Sstevel@tonic-gate case 's': 7640Sstevel@tonic-gate cp++; 7650Sstevel@tonic-gate 7660Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7670Sstevel@tonic-gate (*rtdp)->t_name = NULL; 7680Sstevel@tonic-gate cp = soudef(cp, (type == 'u') ? UNION : STRUCT, rtdp); 7690Sstevel@tonic-gate break; 7700Sstevel@tonic-gate default: 7710Sstevel@tonic-gate expected("tdefdecl", "<type code>", cp); 7720Sstevel@tonic-gate } 7730Sstevel@tonic-gate return (cp); 7740Sstevel@tonic-gate } 7750Sstevel@tonic-gate 7760Sstevel@tonic-gate static char * 7770Sstevel@tonic-gate intrinsic(char *cp, tdesc_t **rtdp) 7780Sstevel@tonic-gate { 7790Sstevel@tonic-gate intr_t *intr = xcalloc(sizeof (intr_t)); 7800Sstevel@tonic-gate tdesc_t *tdp; 7810Sstevel@tonic-gate int width, fmt, i; 7820Sstevel@tonic-gate 7830Sstevel@tonic-gate switch (*cp++) { 7840Sstevel@tonic-gate case 'b': 7850Sstevel@tonic-gate intr->intr_type = INTR_INT; 7860Sstevel@tonic-gate if (*cp == 's') 7870Sstevel@tonic-gate intr->intr_signed = 1; 7880Sstevel@tonic-gate else if (*cp != 'u') 7890Sstevel@tonic-gate expected("intrinsic/b", "[su]", cp); 7900Sstevel@tonic-gate cp++; 7910Sstevel@tonic-gate 7920Sstevel@tonic-gate if (strchr("cbv", *cp)) 7930Sstevel@tonic-gate intr->intr_iformat = *cp++; 7940Sstevel@tonic-gate 7950Sstevel@tonic-gate cp = number(cp, &width); 7960Sstevel@tonic-gate if (*cp++ != ';') 7970Sstevel@tonic-gate expected("intrinsic/b", "; (post-width)", cp - 1); 7980Sstevel@tonic-gate 7990Sstevel@tonic-gate cp = number(cp, &intr->intr_offset); 8000Sstevel@tonic-gate if (*cp++ != ';') 8010Sstevel@tonic-gate expected("intrinsic/b", "; (post-offset)", cp - 1); 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate cp = number(cp, &intr->intr_nbits); 8040Sstevel@tonic-gate break; 8050Sstevel@tonic-gate 8060Sstevel@tonic-gate case 'R': 8070Sstevel@tonic-gate intr->intr_type = INTR_REAL; 8080Sstevel@tonic-gate for (fmt = 0, i = 0; isdigit(*(cp + i)); i++) 8090Sstevel@tonic-gate fmt = fmt * 10 + (*(cp + i) - '0'); 8100Sstevel@tonic-gate 8110Sstevel@tonic-gate if (fmt < 1 || fmt > CTF_FP_MAX) 8120Sstevel@tonic-gate expected("intrinsic/R", "number <= CTF_FP_MAX", cp); 8130Sstevel@tonic-gate 8140Sstevel@tonic-gate intr->intr_fformat = fmt; 8150Sstevel@tonic-gate cp += i; 8160Sstevel@tonic-gate 8170Sstevel@tonic-gate if (*cp++ != ';') 8180Sstevel@tonic-gate expected("intrinsic/R", ";", cp - 1); 8190Sstevel@tonic-gate cp = number(cp, &width); 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate intr->intr_nbits = width * 8; 8220Sstevel@tonic-gate break; 8230Sstevel@tonic-gate } 8240Sstevel@tonic-gate 8250Sstevel@tonic-gate tdp = xcalloc(sizeof (*tdp)); 8260Sstevel@tonic-gate tdp->t_type = INTRINSIC; 8270Sstevel@tonic-gate tdp->t_size = width; 8280Sstevel@tonic-gate tdp->t_name = NULL; 8290Sstevel@tonic-gate tdp->t_intr = intr; 8300Sstevel@tonic-gate parse_debug(3, NULL, "intrinsic: size=%d", width); 8310Sstevel@tonic-gate *rtdp = tdp; 8320Sstevel@tonic-gate 8330Sstevel@tonic-gate return (cp); 8340Sstevel@tonic-gate } 8350Sstevel@tonic-gate 8360Sstevel@tonic-gate static tdesc_t * 8370Sstevel@tonic-gate bitintrinsic(tdesc_t *template, int nbits) 8380Sstevel@tonic-gate { 8390Sstevel@tonic-gate tdesc_t *newtdp = xcalloc(sizeof (tdesc_t)); 8400Sstevel@tonic-gate 8410Sstevel@tonic-gate newtdp->t_name = xstrdup(template->t_name); 8420Sstevel@tonic-gate newtdp->t_id = faketypenumber++; 8430Sstevel@tonic-gate newtdp->t_type = INTRINSIC; 8440Sstevel@tonic-gate newtdp->t_size = template->t_size; 8450Sstevel@tonic-gate newtdp->t_intr = xmalloc(sizeof (intr_t)); 8460Sstevel@tonic-gate bcopy(template->t_intr, newtdp->t_intr, sizeof (intr_t)); 8470Sstevel@tonic-gate newtdp->t_intr->intr_nbits = nbits; 8480Sstevel@tonic-gate 8490Sstevel@tonic-gate return (newtdp); 8500Sstevel@tonic-gate } 8510Sstevel@tonic-gate 8520Sstevel@tonic-gate static char * 8530Sstevel@tonic-gate offsize(char *cp, mlist_t *mlp) 8540Sstevel@tonic-gate { 8550Sstevel@tonic-gate int offset, size; 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate if (*cp == ',') 8580Sstevel@tonic-gate cp++; 8590Sstevel@tonic-gate cp = number(cp, &offset); 8600Sstevel@tonic-gate if (*cp++ != ',') 8610Sstevel@tonic-gate expected("offsize/2", ",", cp - 1); 8620Sstevel@tonic-gate cp = number(cp, &size); 8630Sstevel@tonic-gate if (*cp++ != ';') 8640Sstevel@tonic-gate expected("offsize/3", ";", cp - 1); 8650Sstevel@tonic-gate mlp->ml_offset = offset; 8660Sstevel@tonic-gate mlp->ml_size = size; 8670Sstevel@tonic-gate return (cp); 8680Sstevel@tonic-gate } 8690Sstevel@tonic-gate 8700Sstevel@tonic-gate static tdesc_t * 8710Sstevel@tonic-gate find_intrinsic(tdesc_t *tdp) 8720Sstevel@tonic-gate { 8730Sstevel@tonic-gate for (;;) { 8740Sstevel@tonic-gate switch (tdp->t_type) { 8750Sstevel@tonic-gate case TYPEDEF: 8760Sstevel@tonic-gate case VOLATILE: 8770Sstevel@tonic-gate case CONST: 8780Sstevel@tonic-gate case RESTRICT: 8790Sstevel@tonic-gate tdp = tdp->t_tdesc; 8800Sstevel@tonic-gate break; 8810Sstevel@tonic-gate 8820Sstevel@tonic-gate default: 8830Sstevel@tonic-gate return (tdp); 8840Sstevel@tonic-gate } 8850Sstevel@tonic-gate } 8860Sstevel@tonic-gate } 8870Sstevel@tonic-gate 8880Sstevel@tonic-gate static char * 8890Sstevel@tonic-gate soudef(char *cp, stabtype_t type, tdesc_t **rtdp) 8900Sstevel@tonic-gate { 8910Sstevel@tonic-gate mlist_t *mlp, **prev; 8920Sstevel@tonic-gate char *w; 8930Sstevel@tonic-gate int h; 8940Sstevel@tonic-gate int size; 8950Sstevel@tonic-gate tdesc_t *tdp, *itdp; 8960Sstevel@tonic-gate 8970Sstevel@tonic-gate cp = number(cp, &size); 8980Sstevel@tonic-gate (*rtdp)->t_size = size; 8990Sstevel@tonic-gate (*rtdp)->t_type = type; /* s or u */ 9000Sstevel@tonic-gate 9010Sstevel@tonic-gate /* 9020Sstevel@tonic-gate * An '@' here indicates a bitmask follows. This is so the 9030Sstevel@tonic-gate * compiler can pass information to debuggers about how structures 9040Sstevel@tonic-gate * are passed in the v9 world. We don't need this information 9050Sstevel@tonic-gate * so we skip over it. 9060Sstevel@tonic-gate */ 9070Sstevel@tonic-gate if (cp[0] == '@') { 9080Sstevel@tonic-gate cp += 3; 9090Sstevel@tonic-gate } 9100Sstevel@tonic-gate 911*1882Sjohnlev parse_debug(3, cp, "soudef: %s size=%d", tdesc_name(*rtdp), 9120Sstevel@tonic-gate (*rtdp)->t_size); 9130Sstevel@tonic-gate 9140Sstevel@tonic-gate prev = &((*rtdp)->t_members); 9150Sstevel@tonic-gate /* now fill up the fields */ 9160Sstevel@tonic-gate while ((*cp != '\0') && (*cp != ';')) { /* signifies end of fields */ 9170Sstevel@tonic-gate mlp = xcalloc(sizeof (*mlp)); 9180Sstevel@tonic-gate *prev = mlp; 9190Sstevel@tonic-gate cp = name(cp, &w); 9200Sstevel@tonic-gate mlp->ml_name = w; 9210Sstevel@tonic-gate cp = id(cp, &h); 9220Sstevel@tonic-gate /* 9230Sstevel@tonic-gate * find the tdesc struct in the hash table for this type 9240Sstevel@tonic-gate * and stick a ptr in here 9250Sstevel@tonic-gate */ 9260Sstevel@tonic-gate tdp = lookup(h); 9270Sstevel@tonic-gate if (tdp == NULL) { /* not in hash list */ 9280Sstevel@tonic-gate parse_debug(3, NULL, " defines %s (%d)", w, h); 9290Sstevel@tonic-gate if (*cp++ != '=') { 9300Sstevel@tonic-gate tdp = unres_new(h); 9310Sstevel@tonic-gate parse_debug(3, NULL, 9320Sstevel@tonic-gate " refers to %s (unresolved %d)", 9330Sstevel@tonic-gate (w ? w : "anon"), h); 9340Sstevel@tonic-gate } else { 9350Sstevel@tonic-gate cp = tdefdecl(cp, h, &tdp); 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate if (tdp->t_id && tdp->t_id != h) { 9380Sstevel@tonic-gate tdesc_t *ntdp = xcalloc(sizeof (*ntdp)); 9390Sstevel@tonic-gate 9400Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 9410Sstevel@tonic-gate ntdp->t_tdesc = tdp; 9420Sstevel@tonic-gate tdp = ntdp; 9430Sstevel@tonic-gate } 9440Sstevel@tonic-gate 9450Sstevel@tonic-gate addhash(tdp, h); 9460Sstevel@tonic-gate parse_debug(4, cp, 9470Sstevel@tonic-gate " soudef now looking at "); 9480Sstevel@tonic-gate cp++; 9490Sstevel@tonic-gate } 9500Sstevel@tonic-gate } else { 9510Sstevel@tonic-gate parse_debug(3, NULL, " refers to %s (%d, %s)", 952*1882Sjohnlev w ? w : "anon", h, tdesc_name(tdp)); 9530Sstevel@tonic-gate } 9540Sstevel@tonic-gate 9550Sstevel@tonic-gate cp = offsize(cp, mlp); 9560Sstevel@tonic-gate 9570Sstevel@tonic-gate itdp = find_intrinsic(tdp); 9580Sstevel@tonic-gate if (itdp->t_type == INTRINSIC) { 9590Sstevel@tonic-gate if (mlp->ml_size != itdp->t_intr->intr_nbits) { 9600Sstevel@tonic-gate parse_debug(4, cp, "making %d bit intrinsic " 961*1882Sjohnlev "from %s", mlp->ml_size, tdesc_name(itdp)); 9620Sstevel@tonic-gate mlp->ml_type = bitintrinsic(itdp, mlp->ml_size); 9630Sstevel@tonic-gate } else 9640Sstevel@tonic-gate mlp->ml_type = tdp; 9650Sstevel@tonic-gate } else if (itdp->t_type == TYPEDEF_UNRES) { 9660Sstevel@tonic-gate list_add(&typedbitfldmems, mlp); 9670Sstevel@tonic-gate mlp->ml_type = tdp; 9680Sstevel@tonic-gate } else { 9690Sstevel@tonic-gate mlp->ml_type = tdp; 9700Sstevel@tonic-gate } 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate /* cp is now pointing to next field */ 9730Sstevel@tonic-gate prev = &mlp->ml_next; 9740Sstevel@tonic-gate } 9750Sstevel@tonic-gate return (cp); 9760Sstevel@tonic-gate } 9770Sstevel@tonic-gate 9780Sstevel@tonic-gate static char * 9790Sstevel@tonic-gate arraydef(char *cp, tdesc_t **rtdp) 9800Sstevel@tonic-gate { 9810Sstevel@tonic-gate int start, end, h; 9820Sstevel@tonic-gate 9830Sstevel@tonic-gate cp = id(cp, &h); 9840Sstevel@tonic-gate if (*cp++ != ';') 9850Sstevel@tonic-gate expected("arraydef/1", ";", cp - 1); 9860Sstevel@tonic-gate 9870Sstevel@tonic-gate (*rtdp)->t_ardef = xcalloc(sizeof (ardef_t)); 9880Sstevel@tonic-gate (*rtdp)->t_ardef->ad_idxtype = lookup(h); 9890Sstevel@tonic-gate 9900Sstevel@tonic-gate cp = number(cp, &start); /* lower */ 9910Sstevel@tonic-gate if (*cp++ != ';') 9920Sstevel@tonic-gate expected("arraydef/2", ";", cp - 1); 9930Sstevel@tonic-gate 9940Sstevel@tonic-gate if (*cp == 'S') { 9950Sstevel@tonic-gate /* variable length array - treat as null dimensioned */ 9960Sstevel@tonic-gate cp++; 9970Sstevel@tonic-gate if (*cp++ != '-') 9980Sstevel@tonic-gate expected("arraydef/fpoff-sep", "-", cp - 1); 9990Sstevel@tonic-gate cp = number(cp, &end); 10000Sstevel@tonic-gate end = start; 10010Sstevel@tonic-gate } else { 10020Sstevel@tonic-gate /* normal fixed-dimension array */ 10030Sstevel@tonic-gate cp = number(cp, &end); /* upper */ 10040Sstevel@tonic-gate } 10050Sstevel@tonic-gate 10060Sstevel@tonic-gate if (*cp++ != ';') 10070Sstevel@tonic-gate expected("arraydef/3", ";", cp - 1); 10080Sstevel@tonic-gate (*rtdp)->t_ardef->ad_nelems = end - start + 1; 10090Sstevel@tonic-gate cp = tdefdecl(cp, h, &((*rtdp)->t_ardef->ad_contents)); 10100Sstevel@tonic-gate 10110Sstevel@tonic-gate parse_debug(3, cp, "defined array idx type %d %d-%d next ", 10120Sstevel@tonic-gate h, start, end); 10130Sstevel@tonic-gate 10140Sstevel@tonic-gate return (cp); 10150Sstevel@tonic-gate } 10160Sstevel@tonic-gate 10170Sstevel@tonic-gate static void 10180Sstevel@tonic-gate enumdef(char *cp, tdesc_t **rtdp) 10190Sstevel@tonic-gate { 10200Sstevel@tonic-gate elist_t *elp, **prev; 10210Sstevel@tonic-gate char *w; 10220Sstevel@tonic-gate 10230Sstevel@tonic-gate (*rtdp)->t_type = ENUM; 10240Sstevel@tonic-gate (*rtdp)->t_emem = NULL; 10250Sstevel@tonic-gate 10260Sstevel@tonic-gate prev = &((*rtdp)->t_emem); 10270Sstevel@tonic-gate while (*cp != ';') { 10280Sstevel@tonic-gate elp = xcalloc(sizeof (*elp)); 10290Sstevel@tonic-gate elp->el_next = NULL; 10300Sstevel@tonic-gate *prev = elp; 10310Sstevel@tonic-gate cp = name(cp, &w); 10320Sstevel@tonic-gate elp->el_name = w; 10330Sstevel@tonic-gate cp = number(cp, &elp->el_number); 1034*1882Sjohnlev parse_debug(3, NULL, "enum %s: %s=%d", tdesc_name(*rtdp), 10350Sstevel@tonic-gate elp->el_name, elp->el_number); 10360Sstevel@tonic-gate prev = &elp->el_next; 10370Sstevel@tonic-gate if (*cp++ != ',') 10380Sstevel@tonic-gate expected("enumdef", ",", cp - 1); 10390Sstevel@tonic-gate } 10400Sstevel@tonic-gate } 10410Sstevel@tonic-gate 10420Sstevel@tonic-gate tdesc_t * 10430Sstevel@tonic-gate lookup_name(tdesc_t **hash, char *name) 10440Sstevel@tonic-gate { 10450Sstevel@tonic-gate int bucket = compute_sum(name); 10460Sstevel@tonic-gate tdesc_t *tdp, *ttdp = NULL; 10470Sstevel@tonic-gate 10480Sstevel@tonic-gate for (tdp = hash[bucket]; tdp != NULL; tdp = tdp->t_next) { 10490Sstevel@tonic-gate if (tdp->t_name != NULL && strcmp(tdp->t_name, name) == 0) { 10500Sstevel@tonic-gate if (tdp->t_type == STRUCT || tdp->t_type == UNION || 10510Sstevel@tonic-gate tdp->t_type == ENUM || tdp->t_type == INTRINSIC) 10520Sstevel@tonic-gate return (tdp); 10530Sstevel@tonic-gate if (tdp->t_type == TYPEDEF) 10540Sstevel@tonic-gate ttdp = tdp; 10550Sstevel@tonic-gate } 10560Sstevel@tonic-gate } 10570Sstevel@tonic-gate return (ttdp); 10580Sstevel@tonic-gate } 10590Sstevel@tonic-gate 10600Sstevel@tonic-gate tdesc_t * 10610Sstevel@tonic-gate lookupname(char *name) 10620Sstevel@tonic-gate { 10630Sstevel@tonic-gate return (lookup_name(name_table, name)); 10640Sstevel@tonic-gate } 10650Sstevel@tonic-gate 10660Sstevel@tonic-gate /* 10670Sstevel@tonic-gate * Add a node to the hash queues. 10680Sstevel@tonic-gate */ 10690Sstevel@tonic-gate static void 10700Sstevel@tonic-gate addhash(tdesc_t *tdp, int num) 10710Sstevel@tonic-gate { 10720Sstevel@tonic-gate int hash = HASH(num); 10730Sstevel@tonic-gate tdesc_t *ttdp; 10740Sstevel@tonic-gate char added_num = 0, added_name = 0; 10750Sstevel@tonic-gate 10760Sstevel@tonic-gate /* 10770Sstevel@tonic-gate * If it already exists in the hash table don't add it again 10780Sstevel@tonic-gate * (but still check to see if the name should be hashed). 10790Sstevel@tonic-gate */ 10800Sstevel@tonic-gate ttdp = lookup(num); 10810Sstevel@tonic-gate 10820Sstevel@tonic-gate if (ttdp == NULL) { 10830Sstevel@tonic-gate tdp->t_id = num; 10840Sstevel@tonic-gate tdp->t_hash = hash_table[hash]; 10850Sstevel@tonic-gate hash_table[hash] = tdp; 10860Sstevel@tonic-gate added_num = 1; 10870Sstevel@tonic-gate } 10880Sstevel@tonic-gate 10890Sstevel@tonic-gate if (tdp->t_name != NULL) { 10900Sstevel@tonic-gate ttdp = lookupname(tdp->t_name); 10910Sstevel@tonic-gate if (ttdp == NULL) { 10920Sstevel@tonic-gate hash = compute_sum(tdp->t_name); 10930Sstevel@tonic-gate tdp->t_next = name_table[hash]; 10940Sstevel@tonic-gate name_table[hash] = tdp; 10950Sstevel@tonic-gate added_name = 1; 10960Sstevel@tonic-gate } 10970Sstevel@tonic-gate } 10980Sstevel@tonic-gate if (!added_num && !added_name) { 10990Sstevel@tonic-gate terminate("stabs: broken hash\n"); 11000Sstevel@tonic-gate } 11010Sstevel@tonic-gate } 11020Sstevel@tonic-gate 11030Sstevel@tonic-gate static int 11040Sstevel@tonic-gate compute_sum(char *w) 11050Sstevel@tonic-gate { 11060Sstevel@tonic-gate char c; 11070Sstevel@tonic-gate int sum; 11080Sstevel@tonic-gate 11090Sstevel@tonic-gate for (sum = 0; (c = *w) != '\0'; sum += c, w++) 11100Sstevel@tonic-gate ; 11110Sstevel@tonic-gate return (HASH(sum)); 11120Sstevel@tonic-gate } 11130Sstevel@tonic-gate 11140Sstevel@tonic-gate static void 11150Sstevel@tonic-gate reset(void) 11160Sstevel@tonic-gate { 11170Sstevel@tonic-gate longjmp(resetbuf, 1); 11180Sstevel@tonic-gate } 11190Sstevel@tonic-gate 11200Sstevel@tonic-gate void 11210Sstevel@tonic-gate check_hash(void) 11220Sstevel@tonic-gate { 11230Sstevel@tonic-gate tdesc_t *tdp; 11240Sstevel@tonic-gate int i; 11250Sstevel@tonic-gate 11260Sstevel@tonic-gate printf("checking hash\n"); 11270Sstevel@tonic-gate for (i = 0; i < BUCKETS; i++) { 11280Sstevel@tonic-gate if (hash_table[i]) { 11290Sstevel@tonic-gate for (tdp = hash_table[i]->t_hash; 11300Sstevel@tonic-gate tdp && tdp != hash_table[i]; 11310Sstevel@tonic-gate tdp = tdp->t_hash) 11320Sstevel@tonic-gate continue; 11330Sstevel@tonic-gate if (tdp) { 11340Sstevel@tonic-gate terminate("cycle in hash bucket %d\n", i); 11350Sstevel@tonic-gate return; 11360Sstevel@tonic-gate } 11370Sstevel@tonic-gate } 11380Sstevel@tonic-gate 11390Sstevel@tonic-gate if (name_table[i]) { 11400Sstevel@tonic-gate for (tdp = name_table[i]->t_next; 11410Sstevel@tonic-gate tdp && tdp != name_table[i]; 11420Sstevel@tonic-gate tdp = tdp->t_next) 11430Sstevel@tonic-gate continue; 11440Sstevel@tonic-gate if (tdp) { 11450Sstevel@tonic-gate terminate("cycle in name bucket %d\n", i); 11460Sstevel@tonic-gate return; 11470Sstevel@tonic-gate } 11480Sstevel@tonic-gate } 11490Sstevel@tonic-gate } 11500Sstevel@tonic-gate printf("done\n"); 11510Sstevel@tonic-gate } 11520Sstevel@tonic-gate 11530Sstevel@tonic-gate /*ARGSUSED1*/ 11540Sstevel@tonic-gate static int 11550Sstevel@tonic-gate resolve_typed_bitfields_cb(mlist_t *ml, void *private) 11560Sstevel@tonic-gate { 11570Sstevel@tonic-gate tdesc_t *tdp = ml->ml_type; 11580Sstevel@tonic-gate 11590Sstevel@tonic-gate debug(3, "Resolving typed bitfields (member %s)\n", 11600Sstevel@tonic-gate (ml->ml_name ? ml->ml_name : "(anon)")); 11610Sstevel@tonic-gate 11620Sstevel@tonic-gate while (tdp) { 11630Sstevel@tonic-gate switch (tdp->t_type) { 11640Sstevel@tonic-gate case INTRINSIC: 11650Sstevel@tonic-gate if (ml->ml_size != tdp->t_intr->intr_nbits) { 11660Sstevel@tonic-gate debug(3, "making %d bit intrinsic from %s", 1167*1882Sjohnlev ml->ml_size, tdesc_name(tdp)); 11680Sstevel@tonic-gate ml->ml_type = bitintrinsic(tdp, ml->ml_size); 11690Sstevel@tonic-gate } else { 11700Sstevel@tonic-gate debug(3, "using existing %d bit %s intrinsic", 1171*1882Sjohnlev ml->ml_size, tdesc_name(tdp)); 11720Sstevel@tonic-gate ml->ml_type = tdp; 11730Sstevel@tonic-gate } 11740Sstevel@tonic-gate return (1); 11750Sstevel@tonic-gate 11760Sstevel@tonic-gate case POINTER: 11770Sstevel@tonic-gate case TYPEDEF: 11780Sstevel@tonic-gate case VOLATILE: 11790Sstevel@tonic-gate case CONST: 11800Sstevel@tonic-gate case RESTRICT: 11810Sstevel@tonic-gate tdp = tdp->t_tdesc; 11820Sstevel@tonic-gate break; 11830Sstevel@tonic-gate 11840Sstevel@tonic-gate default: 11850Sstevel@tonic-gate return (1); 11860Sstevel@tonic-gate } 11870Sstevel@tonic-gate } 11880Sstevel@tonic-gate 11890Sstevel@tonic-gate terminate("type chain for bitfield member %s has a NULL", ml->ml_name); 11900Sstevel@tonic-gate /*NOTREACHED*/ 11910Sstevel@tonic-gate return (0); 11920Sstevel@tonic-gate } 11930Sstevel@tonic-gate 11940Sstevel@tonic-gate void 11950Sstevel@tonic-gate resolve_typed_bitfields(void) 11960Sstevel@tonic-gate { 11970Sstevel@tonic-gate (void) list_iter(typedbitfldmems, 11980Sstevel@tonic-gate (int (*)())resolve_typed_bitfields_cb, NULL); 11990Sstevel@tonic-gate } 1200