aboutsummaryrefslogtreecommitdiff
path: root/cddl/contrib/opensolaris/tools/ctf
diff options
context:
space:
mode:
Diffstat (limited to 'cddl/contrib/opensolaris/tools/ctf')
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/compare.c92
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c3
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h16
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/fixup_tdescs.c119
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c1214
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/stabs.c381
6 files changed, 0 insertions, 1825 deletions
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/compare.c b/cddl/contrib/opensolaris/tools/ctf/cvt/compare.c
deleted file mode 100644
index 26037f8a537a..000000000000
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/compare.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * This is a test program designed to catch mismerges and mistranslations from
- * stabs to CTF.
- *
- * Given a file with stabs data and a file with CTF data, determine whether
- * or not all of the data structures and objects described by the stabs data
- * are present in the CTF data.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "ctftools.h"
-
-char *progname;
-int debug_level = DEBUG_LEVEL;
-
-static void
-usage(void)
-{
- fprintf(stderr, "Usage: %s ctf_file stab_file\n", progname);
-}
-
-int
-main(int argc, char **argv)
-{
- tdata_t *ctftd, *stabrtd, *stabtd, *difftd;
- char *ctfname, *stabname;
- int new;
-
- progname = argv[0];
-
- if (argc != 3) {
- usage();
- exit(2);
- }
-
- ctfname = argv[1];
- stabname = argv[2];
-
- stabrtd = tdata_new();
- stabtd = tdata_new();
- difftd = tdata_new();
-
- if (read_stabs(stabrtd, stabname, 0) != 0)
- merge_into_master(stabrtd, stabtd, NULL, 1);
- else if (read_ctf(&stabname, 1, NULL, read_ctf_save_cb, &stabtd, 0)
- == 0)
- terminate("%s doesn't have stabs or CTF\n", stabname);
-
- if (read_ctf(&ctfname, 1, NULL, read_ctf_save_cb, &ctftd, 0) == 0)
- terminate("%s doesn't contain CTF data\n", ctfname);
-
- merge_into_master(stabtd, ctftd, difftd, 0);
-
- if ((new = hash_count(difftd->td_iihash)) != 0) {
- (void) hash_iter(difftd->td_iihash, (int (*)())iidesc_dump,
- NULL);
- terminate("%s grew by %d\n", stabname, new);
- }
-
- return (0);
-}
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c b/cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c
index d40be25da27f..68969356e75e 100644
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c
+++ b/cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c
@@ -83,7 +83,6 @@ file_read(tdata_t *td, char *filename, int ignore_non_c)
{
typedef int (*reader_f)(tdata_t *, Elf *, char *);
static reader_f readers[] = {
- stabs_read,
dw_read,
NULL
};
@@ -165,8 +164,6 @@ main(int argc, char **argv)
if (getenv("CTFCONVERT_DEBUG_LEVEL"))
debug_level = atoi(getenv("CTFCONVERT_DEBUG_LEVEL"));
- if (getenv("CTFCONVERT_DEBUG_PARSE"))
- debug_parse = atoi(getenv("CTFCONVERT_DEBUG_PARSE"));
while ((c = getopt(argc, argv, ":l:L:o:givs")) != EOF) {
switch (c) {
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h b/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h
index b7da16ac3ddd..974d22459991 100644
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h
+++ b/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h
@@ -50,9 +50,6 @@ extern "C" {
#ifndef DEBUG_LEVEL
#define DEBUG_LEVEL 0
#endif
-#ifndef DEBUG_PARSE
-#define DEBUG_PARSE 0
-#endif
#ifndef DEBUG_STREAM
#define DEBUG_STREAM stderr
@@ -100,7 +97,6 @@ extern "C" {
extern const char *progname;
extern int debug_level;
-extern int debug_parse;
extern char *curhdr;
/*
@@ -405,18 +401,6 @@ void merge_into_master(tdata_t *, tdata_t *, tdata_t *, int);
void write_ctf(tdata_t *, const char *, const char *, int);
-/* parse.c */
-void parse_init(tdata_t *);
-void parse_finish(tdata_t *);
-int parse_stab(stab_t *, char *, iidesc_t **);
-tdesc_t *lookup(int);
-tdesc_t *lookupname(const char *);
-void check_hash(void);
-void resolve_typed_bitfields(void);
-
-/* stabs.c */
-int stabs_read(tdata_t *, Elf *, char *);
-
/* dwarf.c */
int dw_read(tdata_t *, Elf *, char *);
const char *dw_tag2str(uint_t);
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/fixup_tdescs.c b/cddl/contrib/opensolaris/tools/ctf/cvt/fixup_tdescs.c
index b239a62dc53b..ea4f4ee64625 100644
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/fixup_tdescs.c
+++ b/cddl/contrib/opensolaris/tools/ctf/cvt/fixup_tdescs.c
@@ -38,125 +38,6 @@
#include "hash.h"
#include "memory.h"
-/*
- * Due to 4432619, the 6.1 compiler will sometimes incorrectly generate pointer
- * stabs. Given a struct foo, and a corresponding typedef struct foo foo_t.
- * In some cases, when faced with a pointer to a foo_t, the compiler will
- * sometimes generate a stab that describes a pointer to a struct foo.
- * Regardless of correctness, this breaks merges, as it occurs inconsistently
- * by file. The following two routines know how to recognize and repair foo_t *
- * and foo_t ** bugs in a specific set of cases. There is no general way to
- * solve this problem without a fix to the compiler. In general, cases should
- * only be added to these routines to fix merging problems in genunix.
- */
-static void
-fix_ptrptr_to_struct(tdata_t *td)
-{
- const char *strs[2] = { "as", "fdbuffer" };
- const char *mems[2] = { "a_objectdir", "fd_shadow" };
- const char *acts[2] = { "vnode", "page" };
- const char *tgts[2] = { "vnode_t", "page_t" };
- tdesc_t *str;
- tdesc_t *act, *tgt;
- tdesc_t *p1, *p2;
- mlist_t *ml;
- int i;
-
- for (i = 0; i < (int) (sizeof (strs) / sizeof (strs[0])); i++) {
- if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
- continue;
-
- for (ml = str->t_members; ml; ml = ml->ml_next) {
- if (streq(ml->ml_name, mems[i]))
- break;
- }
- if (!ml)
- continue;
-
- if (ml->ml_type->t_type != POINTER || ml->ml_type->t_name ||
- ml->ml_type->t_tdesc->t_type != POINTER ||
- ml->ml_type->t_tdesc->t_name)
- continue;
-
- act = ml->ml_type->t_tdesc->t_tdesc;
- if (act->t_type != STRUCT || !streq(act->t_name, acts[i]))
- continue;
-
- if (!(tgt = lookupname(tgts[i])) || tgt->t_type != TYPEDEF)
- continue;
-
- /* We have an instance of the bug */
- p2 = xcalloc(sizeof (*p2));
- p2->t_type = POINTER;
- p2->t_id = td->td_nextid++;
- p2->t_tdesc = tgt;
-
- p1 = xcalloc(sizeof (*p1));
- p1->t_type = POINTER;
- p1->t_id = td->td_nextid++;
- p1->t_tdesc = p2;
-
- ml->ml_type = p1;
-
- debug(3, "Fixed %s->%s => ptrptr struct %s bug\n",
- strs[i], mems[i], acts[i]);
- }
-}
-
-static void
-fix_ptr_to_struct(tdata_t *td)
-{
- const char *strs[2] = { "vmem", "id_space" };
- const char *mems[2] = { NULL, "is_vmem" };
- tdesc_t *ptr = NULL;
- tdesc_t *str, *vmt;
- mlist_t *ml;
- int i;
-
- if ((vmt = lookupname("vmem_t")) == NULL || vmt->t_type != TYPEDEF)
- return;
-
- for (i = 0; i < (int) (sizeof (strs) / sizeof (strs[0])); i++) {
- if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
- continue;
-
- for (ml = str->t_members; ml; ml = ml->ml_next) {
- if (mems[i] && !streq(ml->ml_name, mems[i]))
- continue;
-
- if (ml->ml_type->t_type != POINTER ||
- ml->ml_type->t_name ||
- (ml->ml_type->t_tdesc->t_type != STRUCT &&
- ml->ml_type->t_tdesc->t_type != FORWARD) ||
- !streq(ml->ml_type->t_tdesc->t_name, "vmem"))
- continue;
-
- debug(3, "Fixed %s->%s => ptr struct vmem bug\n",
- strs[i], ml->ml_name);
-
- if (!ptr) {
- ptr = xcalloc(sizeof (*ptr));
- ptr->t_type = POINTER;
- ptr->t_id = td->td_nextid++;
- ptr->t_tdesc = vmt;
- }
-
- ml->ml_type = ptr;
- }
- }
-}
-
-/*
- * Fix stabs generation bugs. These routines must be run before the
- * post-conversion merge
- */
-void
-cvt_fixstabs(tdata_t *td)
-{
- fix_ptrptr_to_struct(td);
- fix_ptr_to_struct(td);
-}
-
struct match {
tdesc_t *m_ret;
const char *m_name;
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c b/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c
deleted file mode 100644
index a452ca5960a7..000000000000
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c
+++ /dev/null
@@ -1,1214 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-/*
- * This file is a sewer.
- */
-
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <assert.h>
-#include <strings.h>
-#include <setjmp.h>
-#include <ctype.h>
-#include <uts/common/sys/ctf.h>
-
-#include "ctftools.h"
-#include "memory.h"
-#include "list.h"
-
-#define HASH(NUM) ((int)(NUM & (BUCKETS - 1)))
-#define BUCKETS 128
-
-#define TYPEPAIRMULT 10000
-#define MAKETYPEID(file, num) ((file) * TYPEPAIRMULT + num)
-#define TYPEFILE(tid) ((tid) / TYPEPAIRMULT)
-#define TYPENUM(tid) ((tid) % TYPEPAIRMULT)
-
-#define expected(a, b, c) _expected(a, b, c, __LINE__)
-
-static int faketypenumber = 100000000;
-
-static tdesc_t *hash_table[BUCKETS];
-static tdesc_t *name_table[BUCKETS];
-
-static list_t *typedbitfldmems;
-
-static void reset(void);
-static jmp_buf resetbuf;
-
-static char *soudef(char *cp, stabtype_t type, tdesc_t **rtdp);
-static void enumdef(char *cp, tdesc_t **rtdp);
-static int compute_sum(const char *w);
-
-static char *number(char *cp, int *n);
-static char *name(char *cp, char **w);
-static char *id(char *cp, int *h);
-static char *whitesp(char *cp);
-static void addhash(tdesc_t *tdp, int num);
-static int tagadd(char *w, int h, tdesc_t *tdp);
-static char *tdefdecl(char *cp, int h, tdesc_t **rtdp);
-static char *intrinsic(char *cp, tdesc_t **rtdp);
-static char *arraydef(char *cp, tdesc_t **rtdp);
-
-int debug_parse = DEBUG_PARSE;
-
-/*PRINTFLIKE3*/
-static void
-parse_debug(int level, char *cp, const char *fmt, ...)
-{
- va_list ap;
- char buf[1024];
- char tmp[32];
- int i;
-
- if (level > debug_level || !debug_parse)
- return;
-
- if (cp != NULL) {
- for (i = 0; i < 30; i++) {
- if (cp[i] == '\0')
- break;
- if (!iscntrl(cp[i]))
- tmp[i] = cp[i];
- }
- tmp[i] = '\0';
- (void) snprintf(buf, sizeof (buf), "%s [cp='%s']\n", fmt, tmp);
- } else {
- strcpy(buf, fmt);
- strcat(buf, "\n");
- }
-
- va_start(ap, fmt);
- vadebug(level, buf, ap);
- va_end(ap);
-}
-
-/* Report unexpected syntax in stabs. */
-static void
-_expected(
- const char *who, /* what function, or part thereof, is reporting */
- const char *what, /* what was expected */
- const char *where, /* where we were in the line of input */
- int line)
-{
- fprintf(stderr, "%s, expecting \"%s\" at \"%s\"\n", who, what, where);
- fprintf(stderr, "code line: %d, file %s\n", line,
- (curhdr ? curhdr : "NO FILE"));
- reset();
-}
-
-/*ARGSUSED*/
-void
-parse_init(tdata_t *td __unused)
-{
- int i;
-
- for (i = 0; i < BUCKETS; i++) {
- hash_table[i] = NULL;
- name_table[i] = NULL;
- }
-
- if (typedbitfldmems != NULL) {
- list_free(typedbitfldmems, NULL, NULL);
- typedbitfldmems = NULL;
- }
-}
-
-void
-parse_finish(tdata_t *td)
-{
- td->td_nextid = ++faketypenumber;
-}
-
-static tdesc_t *
-unres_new(int tid)
-{
- tdesc_t *tdp;
-
- tdp = xcalloc(sizeof (*tdp));
- tdp->t_type = TYPEDEF_UNRES;
- tdp->t_id = tid;
-
- return (tdp);
-}
-
-static char *
-read_tid(char *cp, tdesc_t **tdpp)
-{
- tdesc_t *tdp;
- int tid;
-
- cp = id(cp, &tid);
-
- assert(tid != 0);
-
- if (*cp == '=') {
- if (!(cp = tdefdecl(cp + 1, tid, &tdp)))
- return (NULL);
- if (tdp->t_id && tdp->t_id != tid) {
- tdesc_t *ntdp = xcalloc(sizeof (*ntdp));
-
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp = ntdp;
- }
- addhash(tdp, tid);
- } else if ((tdp = lookup(tid)) == NULL)
- tdp = unres_new(tid);
-
- *tdpp = tdp;
- return (cp);
-}
-
-static iitype_t
-parse_fun(char *cp, iidesc_t *ii)
-{
- iitype_t iitype = 0;
- tdesc_t *tdp;
- tdesc_t **args = NULL;
- int nargs = 0;
- int va = 0;
-
- /*
- * name:P prototype
- * name:F global function
- * name:f static function
- */
- switch (*cp++) {
- case 'P':
- iitype = II_NOT; /* not interesting */
- break;
-
- case 'F':
- iitype = II_GFUN;
- break;
-
- case 'f':
- iitype = II_SFUN;
- break;
-
- default:
- expected("parse_nfun", "[PfF]", cp - 1);
- }
-
- if (!(cp = read_tid(cp, &tdp)))
- return (-1);
-
- if (*cp)
- args = xmalloc(sizeof (tdesc_t *) * FUNCARG_DEF);
-
- while (*cp && *++cp) {
- if (*cp == '0') {
- va = 1;
- continue;
- }
-
- nargs++;
- if (nargs > FUNCARG_DEF)
- args = xrealloc(args, sizeof (tdesc_t *) * nargs);
- if (!(cp = read_tid(cp, &args[nargs - 1]))) {
- if (tdp->t_type == TYPEDEF_UNRES)
- free(tdp);
- free(args);
- return (-1);
- }
- }
-
- ii->ii_type = iitype;
- ii->ii_dtype = tdp;
- ii->ii_nargs = nargs;
- ii->ii_args = args;
- ii->ii_vargs = va;
-
- return (iitype);
-}
-
-static iitype_t
-parse_sym(char *cp, iidesc_t *ii)
-{
- tdesc_t *tdp;
- iitype_t iitype = 0;
-
- /*
- * name:G global variable
- * name:S static variable
- */
- switch (*cp++) {
- case 'G':
- iitype = II_GVAR;
- break;
- case 'S':
- iitype = II_SVAR;
- break;
- case 'p':
- iitype = II_PSYM;
- break;
- case '(':
- cp--;
- /*FALLTHROUGH*/
- case 'r':
- case 'V':
- iitype = II_NOT; /* not interesting */
- break;
- default:
- expected("parse_sym", "[GprSV(]", cp - 1);
- }
-
- if (!(cp = read_tid(cp, &tdp)))
- return (-1);
-
- ii->ii_type = iitype;
- ii->ii_dtype = tdp;
-
- return (iitype);
-}
-
-static iitype_t
-parse_type(char *cp, iidesc_t *ii)
-{
- tdesc_t *tdp, *ntdp;
- int tid;
-
- if (*cp++ != 't')
- expected("parse_type", "t (type)", cp - 1);
-
- cp = id(cp, &tid);
- if ((tdp = lookup(tid)) == NULL) {
- if (*cp++ != '=')
- expected("parse_type", "= (definition)", cp - 1);
-
- (void) tdefdecl(cp, tid, &tdp);
-
- if (tdp->t_id == tid) {
- assert(tdp->t_type != TYPEDEF);
- assert(!lookup(tdp->t_id));
-
- if (!streq(tdp->t_name, ii->ii_name)) {
- ntdp = xcalloc(sizeof (*ntdp));
- ntdp->t_name = xstrdup(ii->ii_name);
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp->t_id = faketypenumber++;
- tdp = ntdp;
- }
- } else if (tdp->t_id == 0) {
- assert(tdp->t_type == FORWARD ||
- tdp->t_type == INTRINSIC);
-
- if (tdp->t_name && !streq(tdp->t_name, ii->ii_name)) {
- ntdp = xcalloc(sizeof (*ntdp));
- ntdp->t_name = xstrdup(ii->ii_name);
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp->t_id = faketypenumber++;
- tdp = ntdp;
- }
- } else if (tdp->t_id != tid) {
- ntdp = xcalloc(sizeof (*ntdp));
- ntdp->t_name = xstrdup(ii->ii_name);
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp = ntdp;
- }
-
- if (tagadd(ii->ii_name, tid, tdp) < 0)
- return (-1);
- }
-
- ii->ii_type = II_TYPE;
- ii->ii_dtype = tdp;
- return (II_TYPE);
-}
-
-static iitype_t
-parse_sou(char *cp, iidesc_t *idp)
-{
- tdesc_t *rtdp;
- int tid;
-
- if (*cp++ != 'T')
- expected("parse_sou", "T (sou)", cp - 1);
-
- cp = id(cp, &tid);
- if (*cp++ != '=')
- expected("parse_sou", "= (definition)", cp - 1);
-
- parse_debug(1, NULL, "parse_sou: declaring '%s'", idp->ii_name ?
- idp->ii_name : "(anon)");
- if ((rtdp = lookup(tid)) != NULL) {
- if (idp->ii_name != NULL) {
- if (rtdp->t_name != NULL &&
- strcmp(rtdp->t_name, idp->ii_name) != 0) {
- tdesc_t *tdp;
-
- tdp = xcalloc(sizeof (*tdp));
- tdp->t_name = xstrdup(idp->ii_name);
- tdp->t_type = TYPEDEF;
- tdp->t_tdesc = rtdp;
- addhash(tdp, tid); /* for *(x,y) types */
- parse_debug(3, NULL, " %s defined as %s(%d)",
- idp->ii_name, tdesc_name(rtdp), tid);
- } else if (rtdp->t_name == NULL) {
- rtdp->t_name = xstrdup(idp->ii_name);
- addhash(rtdp, tid);
- }
- }
- } else {
- rtdp = xcalloc(sizeof (*rtdp));
- rtdp->t_name = idp->ii_name ? xstrdup(idp->ii_name) : NULL;
- addhash(rtdp, tid);
- }
-
- switch (*cp++) {
- case 's':
- (void) soudef(cp, STRUCT, &rtdp);
- break;
- case 'u':
- (void) soudef(cp, UNION, &rtdp);
- break;
- case 'e':
- enumdef(cp, &rtdp);
- break;
- default:
- expected("parse_sou", "<tag type s/u/e>", cp - 1);
- break;
- }
-
- idp->ii_type = II_SOU;
- idp->ii_dtype = rtdp;
- return (II_SOU);
-}
-
-int
-parse_stab(stab_t *stab, char *cp, iidesc_t **iidescp)
-{
- iidesc_t *ii = NULL;
- iitype_t (*parse)(char *, iidesc_t *);
- int rc;
-
- /*
- * set up for reset()
- */
- if (setjmp(resetbuf))
- return (-1);
-
- cp = whitesp(cp);
- ii = iidesc_new(NULL);
- cp = name(cp, &ii->ii_name);
-
- switch (stab->n_type) {
- case N_FUN:
- parse = parse_fun;
- break;
-
- case N_LSYM:
- if (*cp == 't')
- parse = parse_type;
- else if (*cp == 'T')
- parse = parse_sou;
- else
- parse = parse_sym;
- break;
-
- case N_GSYM:
- case N_LCSYM:
- case N_PSYM:
- case N_ROSYM:
- case N_RSYM:
- case N_STSYM:
- parse = parse_sym;
- break;
- default:
- parse_debug(1, cp, "Unknown stab type %#x", stab->n_type);
- bzero(&resetbuf, sizeof (resetbuf));
- return (-1);
- }
-
- rc = parse(cp, ii);
- bzero(&resetbuf, sizeof (resetbuf));
-
- if (rc < 0 || ii->ii_type == II_NOT) {
- iidesc_free(ii, NULL);
- return (rc);
- }
-
- *iidescp = ii;
-
- return (1);
-}
-
-/*
- * Check if we have this node in the hash table already
- */
-tdesc_t *
-lookup(int h)
-{
- int bucket = HASH(h);
- tdesc_t *tdp = hash_table[bucket];
-
- while (tdp != NULL) {
- if (tdp->t_id == h)
- return (tdp);
- tdp = tdp->t_hash;
- }
- return (NULL);
-}
-
-static char *
-whitesp(char *cp)
-{
- char c;
-
- for (c = *cp++; isspace(c); c = *cp++)
- ;
- --cp;
- return (cp);
-}
-
-static char *
-name(char *cp, char **w)
-{
- char *new, *orig, c;
- int len;
-
- orig = cp;
- c = *cp++;
- if (c == ':')
- *w = NULL;
- else if (isalpha(c) || strchr("_.$#", c)) {
- for (c = *cp++; isalnum(c) || strchr(" _.$#", c); c = *cp++)
- ;
- if (c != ':')
- reset();
- len = cp - orig;
- new = xmalloc(len);
- while (orig < cp - 1)
- *new++ = *orig++;
- *new = '\0';
- *w = new - (len - 1);
- } else
- reset();
-
- return (cp);
-}
-
-static char *
-number(char *cp, int *n)
-{
- char *next;
-
- *n = (int)strtol(cp, &next, 10);
- if (next == cp)
- expected("number", "<number>", cp);
- return (next);
-}
-
-static char *
-id(char *cp, int *h)
-{
- int n1, n2;
-
- if (*cp == '(') { /* SunPro style */
- cp++;
- cp = number(cp, &n1);
- if (*cp++ != ',')
- expected("id", ",", cp - 1);
- cp = number(cp, &n2);
- if (*cp++ != ')')
- expected("id", ")", cp - 1);
- *h = MAKETYPEID(n1, n2);
- } else if (isdigit(*cp)) { /* gcc style */
- cp = number(cp, &n1);
- *h = n1;
- } else {
- expected("id", "(/0-9", cp);
- }
- return (cp);
-}
-
-static int
-tagadd(char *w, int h, tdesc_t *tdp)
-{
- tdesc_t *otdp;
-
- tdp->t_name = w;
- if (!(otdp = lookup(h)))
- addhash(tdp, h);
- else if (otdp != tdp) {
- warning("duplicate entry\n");
- warning(" old: %s %d (%d,%d)\n", tdesc_name(otdp),
- otdp->t_type, TYPEFILE(otdp->t_id), TYPENUM(otdp->t_id));
- warning(" new: %s %d (%d,%d)\n", tdesc_name(tdp),
- tdp->t_type, TYPEFILE(tdp->t_id), TYPENUM(tdp->t_id));
- return (-1);
- }
-
- return (0);
-}
-
-static char *
-tdefdecl(char *cp, int h, tdesc_t **rtdp)
-{
- tdesc_t *ntdp;
- char *w;
- int c, h2;
- char type;
-
- parse_debug(3, cp, "tdefdecl h=%d", h);
-
- /* Type codes */
- switch (type = *cp) {
- case 'b': /* integer */
- case 'R': /* fp */
- cp = intrinsic(cp, rtdp);
- break;
- case '(': /* equiv to another type */
- cp = id(cp, &h2);
- ntdp = lookup(h2);
-
- if (ntdp != NULL && *cp == '=') {
- if (ntdp->t_type == FORWARD && *(cp + 1) == 'x') {
- /*
- * The 6.2 compiler, and possibly others, will
- * sometimes emit the same stab for a forward
- * declaration twice. That is, "(1,2)=xsfoo:"
- * will sometimes show up in two different
- * places. This is, of course, quite fun. We
- * want CTF to work in spite of the compiler,
- * so we'll let this one through.
- */
- char *c2 = cp + 2;
- char *nm;
-
- if (!strchr("sue", *c2++)) {
- expected("tdefdecl/x-redefine", "[sue]",
- c2 - 1);
- }
-
- c2 = name(c2, &nm);
- if (strcmp(nm, ntdp->t_name) != 0) {
- terminate("Stabs error: Attempt to "
- "redefine type (%d,%d) as "
- "something else: %s\n",
- TYPEFILE(h2), TYPENUM(h2),
- c2 - 1);
- }
- free(nm);
-
- h2 = faketypenumber++;
- ntdp = NULL;
- } else {
- terminate("Stabs error: Attempting to "
- "redefine type (%d,%d)\n", TYPEFILE(h2),
- TYPENUM(h2));
- }
- }
-
- if (ntdp == NULL) { /* if that type isn't defined yet */
- if (*cp != '=') {
- /* record it as unresolved */
- parse_debug(3, NULL, "tdefdecl unres type %d",
- h2);
- *rtdp = calloc(sizeof (**rtdp), 1);
- (*rtdp)->t_type = TYPEDEF_UNRES;
- (*rtdp)->t_id = h2;
- break;
- } else
- cp++;
-
- /* define a new type */
- cp = tdefdecl(cp, h2, rtdp);
- if ((*rtdp)->t_id && (*rtdp)->t_id != h2) {
- ntdp = calloc(sizeof (*ntdp), 1);
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = *rtdp;
- *rtdp = ntdp;
- }
-
- addhash(*rtdp, h2);
-
- } else { /* that type is already defined */
- if (ntdp->t_type != TYPEDEF || ntdp->t_name != NULL) {
- *rtdp = ntdp;
- } else {
- parse_debug(3, NULL,
- "No duplicate typedef anon for ref");
- *rtdp = ntdp;
- }
- }
- break;
- case '*':
- ntdp = NULL;
- cp = tdefdecl(cp + 1, h, &ntdp);
- if (ntdp == NULL)
- expected("tdefdecl/*", "id", cp);
-
- if (!ntdp->t_id)
- ntdp->t_id = faketypenumber++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = POINTER;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_id = h;
- (*rtdp)->t_tdesc = ntdp;
- break;
- case 'f':
- cp = tdefdecl(cp + 1, h, &ntdp);
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = FUNCTION;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_id = h;
- (*rtdp)->t_fndef = xcalloc(sizeof (fndef_t));
- /*
- * The 6.1 compiler will sometimes generate incorrect stabs for
- * function pointers (it'll get the return type wrong). This
- * causes merges to fail. We therefore treat function pointers
- * as if they all point to functions that return int. When
- * 4432549 is fixed, the lookupname() call below should be
- * replaced with `ntdp'.
- */
- (*rtdp)->t_fndef->fn_ret = lookupname("int");
- break;
- case 'a':
- case 'z':
- cp++;
- if (*cp++ != 'r')
- expected("tdefdecl/[az]", "r", cp - 1);
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = ARRAY;
- (*rtdp)->t_id = h;
- cp = arraydef(cp, rtdp);
- break;
- case 'x':
- c = *++cp;
- if (c != 's' && c != 'u' && c != 'e')
- expected("tdefdecl/x", "[sue]", cp - 1);
- cp = name(cp + 1, &w);
-
- ntdp = xcalloc(sizeof (*ntdp));
- ntdp->t_type = FORWARD;
- ntdp->t_name = w;
- /*
- * We explicitly don't set t_id here - the caller will do it.
- * The caller may want to use a real type ID, or they may
- * choose to make one up.
- */
-
- *rtdp = ntdp;
- break;
-
- case 'B': /* volatile */
- cp = tdefdecl(cp + 1, h, &ntdp);
-
- if (!ntdp->t_id)
- ntdp->t_id = faketypenumber++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = VOLATILE;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_tdesc = ntdp;
- (*rtdp)->t_id = h;
- break;
-
- case 'k': /* const */
- cp = tdefdecl(cp + 1, h, &ntdp);
-
- if (!ntdp->t_id)
- ntdp->t_id = faketypenumber++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = CONST;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_tdesc = ntdp;
- (*rtdp)->t_id = h;
- break;
-
- case 'K': /* restricted */
- cp = tdefdecl(cp + 1, h, &ntdp);
-
- if (!ntdp->t_id)
- ntdp->t_id = faketypenumber++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = RESTRICT;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_tdesc = ntdp;
- (*rtdp)->t_id = h;
- break;
-
- case 'u':
- case 's':
- cp++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_name = NULL;
- cp = soudef(cp, (type == 'u') ? UNION : STRUCT, rtdp);
- break;
- default:
- expected("tdefdecl", "<type code>", cp);
- }
- return (cp);
-}
-
-static char *
-intrinsic(char *cp, tdesc_t **rtdp)
-{
- intr_t *intr = xcalloc(sizeof (intr_t));
- tdesc_t *tdp;
- int width, fmt, i;
-
- switch (*cp++) {
- case 'b':
- intr->intr_type = INTR_INT;
- if (*cp == 's')
- intr->intr_signed = 1;
- else if (*cp != 'u')
- expected("intrinsic/b", "[su]", cp);
- cp++;
-
- if (strchr("cbv", *cp))
- intr->intr_iformat = *cp++;
-
- cp = number(cp, &width);
- if (*cp++ != ';')
- expected("intrinsic/b", "; (post-width)", cp - 1);
-
- cp = number(cp, &intr->intr_offset);
- if (*cp++ != ';')
- expected("intrinsic/b", "; (post-offset)", cp - 1);
-
- cp = number(cp, &intr->intr_nbits);
- break;
-
- case 'R':
- intr->intr_type = INTR_REAL;
- for (fmt = 0, i = 0; isdigit(*(cp + i)); i++)
- fmt = fmt * 10 + (*(cp + i) - '0');
-
- if (fmt < 1 || fmt > CTF_FP_MAX)
- expected("intrinsic/R", "number <= CTF_FP_MAX", cp);
-
- intr->intr_fformat = fmt;
- cp += i;
-
- if (*cp++ != ';')
- expected("intrinsic/R", ";", cp - 1);
- cp = number(cp, &width);
-
- intr->intr_nbits = width * 8;
- break;
- }
-
- tdp = xcalloc(sizeof (*tdp));
- tdp->t_type = INTRINSIC;
- tdp->t_size = width;
- tdp->t_name = NULL;
- tdp->t_intr = intr;
- parse_debug(3, NULL, "intrinsic: size=%d", width);
- *rtdp = tdp;
-
- return (cp);
-}
-
-static tdesc_t *
-bitintrinsic(tdesc_t *template, int nbits)
-{
- tdesc_t *newtdp = xcalloc(sizeof (tdesc_t));
-
- newtdp->t_name = xstrdup(template->t_name);
- newtdp->t_id = faketypenumber++;
- newtdp->t_type = INTRINSIC;
- newtdp->t_size = template->t_size;
- newtdp->t_intr = xmalloc(sizeof (intr_t));
- bcopy(template->t_intr, newtdp->t_intr, sizeof (intr_t));
- newtdp->t_intr->intr_nbits = nbits;
-
- return (newtdp);
-}
-
-static char *
-offsize(char *cp, mlist_t *mlp)
-{
- int offset, size;
-
- if (*cp == ',')
- cp++;
- cp = number(cp, &offset);
- if (*cp++ != ',')
- expected("offsize/2", ",", cp - 1);
- cp = number(cp, &size);
- if (*cp++ != ';')
- expected("offsize/3", ";", cp - 1);
- mlp->ml_offset = offset;
- mlp->ml_size = size;
- return (cp);
-}
-
-static tdesc_t *
-find_intrinsic(tdesc_t *tdp)
-{
- for (;;) {
- switch (tdp->t_type) {
- case TYPEDEF:
- case VOLATILE:
- case CONST:
- case RESTRICT:
- tdp = tdp->t_tdesc;
- break;
-
- default:
- return (tdp);
- }
- }
-}
-
-static char *
-soudef(char *cp, stabtype_t type, tdesc_t **rtdp)
-{
- mlist_t *mlp, **prev;
- char *w;
- int h;
- int size;
- tdesc_t *tdp, *itdp;
-
- cp = number(cp, &size);
- (*rtdp)->t_size = size;
- (*rtdp)->t_type = type; /* s or u */
-
- /*
- * An '@' here indicates a bitmask follows. This is so the
- * compiler can pass information to debuggers about how structures
- * are passed in the v9 world. We don't need this information
- * so we skip over it.
- */
- if (cp[0] == '@') {
- cp += 3;
- }
-
- parse_debug(3, cp, "soudef: %s size=%d", tdesc_name(*rtdp),
- (*rtdp)->t_size);
-
- prev = &((*rtdp)->t_members);
- /* now fill up the fields */
- while ((*cp != '\0') && (*cp != ';')) { /* signifies end of fields */
- mlp = xcalloc(sizeof (*mlp));
- *prev = mlp;
- cp = name(cp, &w);
- mlp->ml_name = w;
- cp = id(cp, &h);
- /*
- * find the tdesc struct in the hash table for this type
- * and stick a ptr in here
- */
- tdp = lookup(h);
- if (tdp == NULL) { /* not in hash list */
- parse_debug(3, NULL, " defines %s (%d)", w, h);
- if (*cp++ != '=') {
- tdp = unres_new(h);
- parse_debug(3, NULL,
- " refers to %s (unresolved %d)",
- (w ? w : "anon"), h);
- } else {
- cp = tdefdecl(cp, h, &tdp);
-
- if (tdp->t_id && tdp->t_id != h) {
- tdesc_t *ntdp = xcalloc(sizeof (*ntdp));
-
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp = ntdp;
- }
-
- addhash(tdp, h);
- parse_debug(4, cp,
- " soudef now looking at ");
- cp++;
- }
- } else {
- parse_debug(3, NULL, " refers to %s (%d, %s)",
- w ? w : "anon", h, tdesc_name(tdp));
- }
-
- cp = offsize(cp, mlp);
-
- itdp = find_intrinsic(tdp);
- if (itdp->t_type == INTRINSIC) {
- if (mlp->ml_size != itdp->t_intr->intr_nbits) {
- parse_debug(4, cp, "making %d bit intrinsic "
- "from %s", mlp->ml_size, tdesc_name(itdp));
- mlp->ml_type = bitintrinsic(itdp, mlp->ml_size);
- } else
- mlp->ml_type = tdp;
- } else if (itdp->t_type == TYPEDEF_UNRES) {
- list_add(&typedbitfldmems, mlp);
- mlp->ml_type = tdp;
- } else {
- mlp->ml_type = tdp;
- }
-
- /* cp is now pointing to next field */
- prev = &mlp->ml_next;
- }
- return (cp);
-}
-
-static char *
-arraydef(char *cp, tdesc_t **rtdp)
-{
- int start, end, h;
-
- cp = id(cp, &h);
- if (*cp++ != ';')
- expected("arraydef/1", ";", cp - 1);
-
- (*rtdp)->t_ardef = xcalloc(sizeof (ardef_t));
- (*rtdp)->t_ardef->ad_idxtype = lookup(h);
-
- cp = number(cp, &start); /* lower */
- if (*cp++ != ';')
- expected("arraydef/2", ";", cp - 1);
-
- if (*cp == 'S') {
- /*
- * variable length array - treat as null dimensioned
- *
- * For VLA variables on sparc, SS12 generated stab entry
- * looks as follows:
- * .stabs "buf:(0,28)=zr(0,4);0;S-12;(0,1)", 0x80, 0, 0, -16
- * Whereas SS12u1 generated stab entry looks like this:
- * .stabs "buf:(0,28)=zr(0,4);0;S0;(0,1)", 0x80, 0, 0, 0
- * On x86, both versions generate the first type of entry.
- * We should be able to parse both.
- */
- cp++;
- if (*cp == '-')
- cp++;
- cp = number(cp, &end);
- end = start;
- } else {
- /*
- * normal fixed-dimension array
- * Stab entry for this looks as follows :
- * .stabs "x:(0,28)=ar(0,4);0;9;(0,3)", 0x80, 0, 40, 0
- */
- cp = number(cp, &end); /* upper */
- }
-
- if (*cp++ != ';')
- expected("arraydef/3", ";", cp - 1);
- (*rtdp)->t_ardef->ad_nelems = end - start + 1;
- cp = tdefdecl(cp, h, &((*rtdp)->t_ardef->ad_contents));
-
- parse_debug(3, cp, "defined array idx type %d %d-%d next ",
- h, start, end);
-
- return (cp);
-}
-
-static void
-enumdef(char *cp, tdesc_t **rtdp)
-{
- elist_t *elp, **prev;
- char *w;
-
- (*rtdp)->t_type = ENUM;
- (*rtdp)->t_emem = NULL;
-
- prev = &((*rtdp)->t_emem);
- while (*cp != ';') {
- elp = xcalloc(sizeof (*elp));
- elp->el_next = NULL;
- *prev = elp;
- cp = name(cp, &w);
- elp->el_name = w;
- cp = number(cp, &elp->el_number);
- parse_debug(3, NULL, "enum %s: %s=%d", tdesc_name(*rtdp),
- elp->el_name, elp->el_number);
- prev = &elp->el_next;
- if (*cp++ != ',')
- expected("enumdef", ",", cp - 1);
- }
-}
-
-static tdesc_t *
-lookup_name(tdesc_t **hash, const char *name1)
-{
- int bucket = compute_sum(name1);
- tdesc_t *tdp, *ttdp = NULL;
-
- for (tdp = hash[bucket]; tdp != NULL; tdp = tdp->t_next) {
- if (tdp->t_name != NULL && strcmp(tdp->t_name, name1) == 0) {
- if (tdp->t_type == STRUCT || tdp->t_type == UNION ||
- tdp->t_type == ENUM || tdp->t_type == INTRINSIC)
- return (tdp);
- if (tdp->t_type == TYPEDEF)
- ttdp = tdp;
- }
- }
- return (ttdp);
-}
-
-tdesc_t *
-lookupname(const char *name1)
-{
- return (lookup_name(name_table, name1));
-}
-
-/*
- * Add a node to the hash queues.
- */
-static void
-addhash(tdesc_t *tdp, int num)
-{
- int hash = HASH(num);
- tdesc_t *ttdp;
- char added_num = 0, added_name = 0;
-
- /*
- * If it already exists in the hash table don't add it again
- * (but still check to see if the name should be hashed).
- */
- ttdp = lookup(num);
-
- if (ttdp == NULL) {
- tdp->t_id = num;
- tdp->t_hash = hash_table[hash];
- hash_table[hash] = tdp;
- added_num = 1;
- }
-
- if (tdp->t_name != NULL) {
- ttdp = lookupname(tdp->t_name);
- if (ttdp == NULL) {
- hash = compute_sum(tdp->t_name);
- tdp->t_next = name_table[hash];
- name_table[hash] = tdp;
- added_name = 1;
- }
- }
- if (!added_num && !added_name) {
- terminate("stabs: broken hash\n");
- }
-}
-
-static int
-compute_sum(const char *w)
-{
- char c;
- int sum;
-
- for (sum = 0; (c = *w) != '\0'; sum += c, w++)
- ;
- return (HASH(sum));
-}
-
-static void
-reset(void)
-{
- longjmp(resetbuf, 1);
-}
-
-void
-check_hash(void)
-{
- tdesc_t *tdp;
- int i;
-
- printf("checking hash\n");
- for (i = 0; i < BUCKETS; i++) {
- if (hash_table[i]) {
- for (tdp = hash_table[i]->t_hash;
- tdp && tdp != hash_table[i];
- tdp = tdp->t_hash)
- continue;
- if (tdp) {
- terminate("cycle in hash bucket %d\n", i);
- return;
- }
- }
-
- if (name_table[i]) {
- for (tdp = name_table[i]->t_next;
- tdp && tdp != name_table[i];
- tdp = tdp->t_next)
- continue;
- if (tdp) {
- terminate("cycle in name bucket %d\n", i);
- return;
- }
- }
- }
- printf("done\n");
-}
-
-/*ARGSUSED1*/
-static int
-resolve_typed_bitfields_cb(void *arg, void *private __unused)
-{
- mlist_t *ml = arg;
- tdesc_t *tdp = ml->ml_type;
-
- debug(3, "Resolving typed bitfields (member %s)\n",
- (ml->ml_name ? ml->ml_name : "(anon)"));
-
- while (tdp) {
- switch (tdp->t_type) {
- case INTRINSIC:
- if (ml->ml_size != tdp->t_intr->intr_nbits) {
- debug(3, "making %d bit intrinsic from %s",
- ml->ml_size, tdesc_name(tdp));
- ml->ml_type = bitintrinsic(tdp, ml->ml_size);
- } else {
- debug(3, "using existing %d bit %s intrinsic",
- ml->ml_size, tdesc_name(tdp));
- ml->ml_type = tdp;
- }
- return (1);
-
- case POINTER:
- case TYPEDEF:
- case VOLATILE:
- case CONST:
- case RESTRICT:
- tdp = tdp->t_tdesc;
- break;
-
- default:
- return (1);
- }
- }
-
- terminate("type chain for bitfield member %s has a NULL", ml->ml_name);
- /*NOTREACHED*/
- return (0);
-}
-
-void
-resolve_typed_bitfields(void)
-{
- (void) list_iter(typedbitfldmems,
- resolve_typed_bitfields_cb, NULL);
-}
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/stabs.c b/cddl/contrib/opensolaris/tools/ctf/cvt/stabs.c
deleted file mode 100644
index c0c68b53e030..000000000000
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/stabs.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Routines used to read stabs data from a file, and to build a tdata structure
- * based on the interesting parts of that data.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <assert.h>
-#include <string.h>
-#include <libgen.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/param.h>
-
-#include "ctftools.h"
-#include "list.h"
-#include "stack.h"
-#include "memory.h"
-#include "traverse.h"
-
-char *curhdr;
-
-/*
- * The stabs generator will sometimes reference types before they've been
- * defined. If this is the case, a TYPEDEF_UNRES tdesc will be generated.
- * Note that this is different from a forward declaration, in which the
- * stab is defined, but is defined as something that doesn't exist yet.
- * When we have read all of the stabs from the file, we can go back and
- * fix up all of the unresolved types. We should be able to fix all of them.
- */
-/*ARGSUSED2*/
-static int
-resolve_tou_node(tdesc_t *node, tdesc_t **nodep, void *private __unused)
-{
- tdesc_t *new;
-
- debug(3, "Trying to resolve %s (%d)\n", tdesc_name(node), node->t_id);
- new = lookup(node->t_id);
-
- if (new == NULL) {
- terminate("Couldn't resolve type %d\n", node->t_id);
- }
-
- debug(3, " Resolving to %d\n", new->t_id);
-
- *nodep = new;
-
- return (1);
-}
-
-/*ARGSUSED*/
-static int
-resolve_fwd_node(tdesc_t *node, tdesc_t **nodep, void *private __unused)
-{
- tdesc_t *new = lookupname(node->t_name);
-
- debug(3, "Trying to unforward %s (%d)\n", tdesc_name(node), node->t_id);
-
- if (!new || (new->t_type != STRUCT && new->t_type != UNION))
- return (0);
-
- debug(3, " Unforwarded to %d\n", new->t_id);
-
- *nodep = new;
-
- return (1);
-}
-
-static tdtrav_cb_f resolve_cbs[] = {
- NULL,
- NULL, /* intrinsic */
- NULL, /* pointer */
- NULL, /* array */
- NULL, /* function */
- NULL, /* struct */
- NULL, /* union */
- NULL, /* enum */
- resolve_fwd_node, /* forward */
- NULL, /* typedef */
- resolve_tou_node, /* typedef unres */
- NULL, /* volatile */
- NULL, /* const */
- NULL, /* restrict */
-};
-
-static void
-resolve_nodes(tdata_t *td)
-{
- debug(2, "Resolving unresolved stabs\n");
-
- (void) iitraverse_hash(td->td_iihash, &td->td_curvgen, resolve_cbs,
- NULL, NULL, td);
-}
-
-static char *
-concat(char *s1, char *s2, int s2strip)
-{
- int savelen = strlen(s2) - s2strip;
- int newlen = (s1 ? strlen(s1) : 0) + savelen + 1;
- char *out;
-
- out = xrealloc(s1, newlen);
- if (s1)
- strncpy(out + strlen(out), s2, savelen);
- else
- strncpy(out, s2, savelen);
-
- out[newlen - 1] = '\0';
-
- return (out);
-}
-
-/*
- * N_FUN stabs come with their arguments in promoted form. In order to get the
- * actual arguments, we need to wait for the N_PSYM stabs that will come towards
- * the end of the function. These routines free the arguments (fnarg_free) we
- * got from the N_FUN stab and add (fnarg_add) the ones from the N_PSYM stabs.
- */
-static void
-fnarg_add(iidesc_t *curfun, iidesc_t *arg)
-{
- curfun->ii_nargs++;
-
- if (curfun->ii_nargs == 1)
- curfun->ii_args = xmalloc(sizeof (tdesc_t *) * FUNCARG_DEF);
- else if (curfun->ii_nargs > FUNCARG_DEF) {
- curfun->ii_args = xrealloc(curfun->ii_args,
- sizeof (tdesc_t *) * curfun->ii_nargs);
- }
-
- curfun->ii_args[curfun->ii_nargs - 1] = arg->ii_dtype;
- arg->ii_dtype = NULL;
-}
-
-static void
-fnarg_free(iidesc_t *ii)
-{
- ii->ii_nargs = 0;
- free(ii->ii_args);
- ii->ii_args = NULL;
-}
-
-/*
- * Read the stabs from the stab ELF section, and turn them into a tdesc tree,
- * assembled under an iidesc list.
- */
-int
-stabs_read(tdata_t *td, Elf *elf, char *file)
-{
- Elf_Scn *scn;
- Elf_Data *data;
- stab_t *stab;
- stk_t *file_stack;
- iidesc_t *iidescp;
- iidesc_t *curfun = NULL;
- char curpath[MAXPATHLEN];
- char *curfile = NULL;
- char *str;
- char *fstr = NULL, *ofstr = NULL;
- int stabidx, stabstridx;
- int nstabs, rc, i;
- int scope = 0;
-
- if (!((stabidx = findelfsecidx(elf, file, ".stab.excl")) >= 0 &&
- (stabstridx = findelfsecidx(elf, file, ".stab.exclstr")) >= 0) &&
- !((stabidx = findelfsecidx(elf, file, ".stab")) >= 0 &&
- (stabstridx = findelfsecidx(elf, file, ".stabstr")) >= 0)) {
- errno = ENOENT;
- return (-1);
- }
-
- file_stack = stack_new(free);
-
- stack_push(file_stack, file);
- curhdr = file;
-
- debug(3, "Found stabs in %d, strings in %d\n", stabidx, stabstridx);
-
- scn = elf_getscn(elf, stabidx);
- data = elf_rawdata(scn, NULL);
- nstabs = data->d_size / sizeof (stab_t);
-
- parse_init(td);
- for (i = 0; i < nstabs; i++) {
- stab = &((stab_t *)data->d_buf)[i];
-
- /* We don't want any local definitions */
- if (stab->n_type == N_LBRAC) {
- scope++;
- debug(3, "stab %d: opening scope (%d)\n", i + 1, scope);
- continue;
- } else if (stab->n_type == N_RBRAC) {
- scope--;
- debug(3, "stab %d: closing scope (%d)\n", i + 1, scope);
- continue;
- } else if (stab->n_type == N_EINCL) {
- /*
- * There's a bug in the 5.2 (Taz) compilers that causes
- * them to emit an extra N_EINCL if there's no actual
- * text in the file being compiled. To work around this
- * bug, we explicitly check to make sure we're not
- * trying to pop a stack that only has the outer scope
- * on it.
- */
- if (stack_level(file_stack) != 1) {
- str = (char *)stack_pop(file_stack);
- free(str);
- curhdr = (char *)stack_peek(file_stack);
- }
- }
-
- /* We only care about a subset of the stabs */
- if (!(stab->n_type == N_FUN || stab->n_type == N_GSYM ||
- stab->n_type == N_LCSYM || stab->n_type == N_LSYM ||
- stab->n_type == N_PSYM || stab->n_type == N_ROSYM ||
- stab->n_type == N_RSYM ||
- stab->n_type == N_STSYM || stab->n_type == N_BINCL ||
- stab->n_type == N_SO || stab->n_type == N_OPT))
- continue;
-
- if ((str = elf_strptr(elf, stabstridx,
- (size_t)stab->n_strx)) == NULL) {
- terminate("%s: Can't find string at %u for stab %d\n",
- file, stab->n_strx, i);
- }
-
- if (stab->n_type == N_BINCL) {
- curhdr = xstrdup(str);
- stack_push(file_stack, curhdr);
- continue;
- } else if (stab->n_type == N_SO) {
- if (str[strlen(str) - 1] != '/') {
- strcpy(curpath, str);
- curfile = basename(curpath);
- }
- continue;
- } else if (stab->n_type == N_OPT) {
- if (strcmp(str, "gcc2_compiled.") == 0) {
- terminate("%s: GCC-generated stabs are "
- "unsupported. Use DWARF instead.\n", file);
- }
- continue;
- }
-
- if (str[strlen(str) - 1] == '\\') {
- int offset = 1;
- /*
- * There's a bug in the compilers that causes them to
- * generate \ for continuations with just -g (this is
- * ok), and \\ for continuations with -g -O (this is
- * broken). This bug is "fixed" in the 6.2 compilers
- * via the elimination of continuation stabs.
- */
- if (str[strlen(str) - 2] == '\\')
- offset = 2;
- fstr = concat(fstr, str, offset);
- continue;
- } else
- fstr = concat(fstr, str, 0);
-
- debug(3, "%4d: .stabs \"%s\", %#x, %d, %hd, %d (from %s)\n", i,
- fstr, stab->n_type, 0, stab->n_desc,
- stab->n_value, curhdr);
-
- if (debug_level >= 3)
- check_hash();
-
- /*
- * Sometimes the compiler stutters, and emits the same stab
- * twice. This is bad for the parser, which will attempt to
- * redefine the type IDs indicated in the stabs. This is
- * compiler bug 4433511.
- */
- if (ofstr && strcmp(fstr, ofstr) == 0) {
- debug(3, "Stutter stab\n");
- free(fstr);
- fstr = NULL;
- continue;
- }
-
- if (ofstr)
- free(ofstr);
- ofstr = fstr;
-
- iidescp = NULL;
-
- if ((rc = parse_stab(stab, fstr, &iidescp)) < 0) {
- terminate("%s: Couldn't parse stab \"%s\" "
- "(source file %s)\n", file, str, curhdr);
- }
-
- if (rc == 0)
- goto parse_loop_end;
-
- /* Make sure the scope tracking is working correctly */
- assert(stab->n_type != N_FUN || (iidescp->ii_type != II_GFUN &&
- iidescp->ii_type != II_SFUN) || scope == 0);
-
- /*
- * The only things we care about that are in local scope are
- * the N_PSYM stabs.
- */
- if (scope && stab->n_type != N_PSYM) {
- if (iidescp)
- iidesc_free(iidescp, NULL);
- goto parse_loop_end;
- }
-
- switch (iidescp->ii_type) {
- case II_SFUN:
- iidescp->ii_owner = xstrdup(curfile);
- /*FALLTHROUGH*/
- case II_GFUN:
- curfun = iidescp;
- fnarg_free(iidescp);
- iidesc_add(td->td_iihash, iidescp);
- break;
-
- case II_SVAR:
- iidescp->ii_owner = xstrdup(curfile);
- /*FALLTHROUGH*/
- case II_GVAR:
- case II_TYPE:
- case II_SOU:
- iidesc_add(td->td_iihash, iidescp);
- break;
-
- case II_PSYM:
- fnarg_add(curfun, iidescp);
- iidesc_free(iidescp, NULL);
- break;
- default:
- aborterr("invalid ii_type %d for stab type %d",
- iidescp->ii_type, stab->n_type);
- }
-
-parse_loop_end:
- fstr = NULL;
- }
-
- if (ofstr)
- free(ofstr);
-
- resolve_nodes(td);
- resolve_typed_bitfields();
- parse_finish(td);
-
- cvt_fixstabs(td);
- cvt_fixups(td, elf_ptrsz(elf));
-
- return (0);
-}