xref: /onnv-gate/usr/src/tools/ctf/cvt/input.c (revision 1951)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51882Sjohnlev  * Common Development and Distribution License (the "License").
61882Sjohnlev  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
221882Sjohnlev  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * Routines for retrieving CTF data from a .SUNW_ctf ELF section
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <stdio.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <fcntl.h>
350Sstevel@tonic-gate #include <unistd.h>
360Sstevel@tonic-gate #include <gelf.h>
370Sstevel@tonic-gate #include <strings.h>
380Sstevel@tonic-gate #include <sys/types.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #include "ctftools.h"
410Sstevel@tonic-gate #include "memory.h"
421882Sjohnlev #include "symbol.h"
430Sstevel@tonic-gate 
440Sstevel@tonic-gate typedef int read_cb_f(tdata_t *, char *, void *);
450Sstevel@tonic-gate 
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate  * Return the source types that the object was generated from.
480Sstevel@tonic-gate  */
490Sstevel@tonic-gate source_types_t
500Sstevel@tonic-gate built_source_types(Elf *elf, char const *file)
510Sstevel@tonic-gate {
520Sstevel@tonic-gate 	source_types_t types = SOURCE_NONE;
530Sstevel@tonic-gate 	symit_data_t *si;
540Sstevel@tonic-gate 
550Sstevel@tonic-gate 	if ((si = symit_new(elf, file)) == NULL)
560Sstevel@tonic-gate 		return (SOURCE_NONE);
570Sstevel@tonic-gate 
580Sstevel@tonic-gate 	while (symit_next(si, STT_FILE) != NULL) {
590Sstevel@tonic-gate 		char *name = symit_name(si);
600Sstevel@tonic-gate 		size_t len = strlen(name);
610Sstevel@tonic-gate 		if (len < 2 || name[len - 2] != '.') {
620Sstevel@tonic-gate 			types |= SOURCE_UNKNOWN;
630Sstevel@tonic-gate 			continue;
640Sstevel@tonic-gate 		}
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 		switch (name[len - 1]) {
670Sstevel@tonic-gate 		case 'c':
680Sstevel@tonic-gate 			types |= SOURCE_C;
690Sstevel@tonic-gate 			break;
700Sstevel@tonic-gate 		case 'h':
710Sstevel@tonic-gate 			/* ignore */
720Sstevel@tonic-gate 			break;
730Sstevel@tonic-gate 		case 's':
740Sstevel@tonic-gate 			types |= SOURCE_S;
750Sstevel@tonic-gate 			break;
760Sstevel@tonic-gate 		default:
770Sstevel@tonic-gate 			types |= SOURCE_UNKNOWN;
780Sstevel@tonic-gate 		}
790Sstevel@tonic-gate 	}
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 	symit_free(si);
820Sstevel@tonic-gate 	return (types);
830Sstevel@tonic-gate }
840Sstevel@tonic-gate 
850Sstevel@tonic-gate static int
860Sstevel@tonic-gate read_file(Elf *elf, char *file, char *label, read_cb_f *func, void *arg,
870Sstevel@tonic-gate     int require_ctf)
880Sstevel@tonic-gate {
890Sstevel@tonic-gate 	Elf_Scn *ctfscn;
900Sstevel@tonic-gate 	Elf_Data *ctfdata;
910Sstevel@tonic-gate 	symit_data_t *si = NULL;
920Sstevel@tonic-gate 	int ctfscnidx;
930Sstevel@tonic-gate 	tdata_t *td;
940Sstevel@tonic-gate 
95*1951Sjohnlev 	if ((ctfscnidx = findelfsecidx(elf, file, ".SUNW_ctf")) < 0) {
960Sstevel@tonic-gate 		if (require_ctf &&
970Sstevel@tonic-gate 		    (built_source_types(elf, file) & SOURCE_C)) {
980Sstevel@tonic-gate 			terminate("Input file %s was partially built from "
990Sstevel@tonic-gate 			    "C sources, but no CTF data was present\n", file);
1000Sstevel@tonic-gate 		}
1010Sstevel@tonic-gate 		return (0);
1020Sstevel@tonic-gate 	}
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	if ((ctfscn = elf_getscn(elf, ctfscnidx)) == NULL ||
1050Sstevel@tonic-gate 	    (ctfdata = elf_getdata(ctfscn, NULL)) == NULL)
1060Sstevel@tonic-gate 		elfterminate(file, "Cannot read CTF section");
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 	/* Reconstruction of type tree */
1090Sstevel@tonic-gate 	if ((si = symit_new(elf, file)) == NULL) {
1100Sstevel@tonic-gate 		warning("%s has no symbol table - skipping", file);
1110Sstevel@tonic-gate 		return (0);
1120Sstevel@tonic-gate 	}
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	td = ctf_load(file, ctfdata->d_buf, ctfdata->d_size, si, label);
1150Sstevel@tonic-gate 	tdata_build_hashes(td);
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	symit_free(si);
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	if (td != NULL) {
1200Sstevel@tonic-gate 		if (func(td, file, arg) < 0)
1210Sstevel@tonic-gate 			return (-1);
1220Sstevel@tonic-gate 		else
1230Sstevel@tonic-gate 			return (1);
1240Sstevel@tonic-gate 	}
1250Sstevel@tonic-gate 	return (0);
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate static int
1290Sstevel@tonic-gate read_archive(int fd, Elf *elf, char *file, char *label, read_cb_f *func,
1300Sstevel@tonic-gate     void *arg, int require_ctf)
1310Sstevel@tonic-gate {
1320Sstevel@tonic-gate 	Elf *melf;
1330Sstevel@tonic-gate 	Elf_Cmd cmd = ELF_C_READ;
1340Sstevel@tonic-gate 	Elf_Arhdr *arh;
1350Sstevel@tonic-gate 	int secnum = 1, found = 0;
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 	while ((melf = elf_begin(fd, cmd, elf)) != NULL) {
1380Sstevel@tonic-gate 		int rc = 0;
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 		if ((arh = elf_getarhdr(melf)) == NULL) {
1410Sstevel@tonic-gate 			elfterminate(file, "Can't get archive header for "
1420Sstevel@tonic-gate 			    "member %d", secnum);
1430Sstevel@tonic-gate 		}
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 		/* skip special sections - their names begin with "/" */
1460Sstevel@tonic-gate 		if (*arh->ar_name != '/') {
1470Sstevel@tonic-gate 			size_t memlen = strlen(file) + 1 +
1480Sstevel@tonic-gate 			    strlen(arh->ar_name) + 1 + 1;
1490Sstevel@tonic-gate 			char *memname = xmalloc(memlen);
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 			snprintf(memname, memlen, "%s(%s)", file, arh->ar_name);
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 			switch (elf_kind(melf)) {
1540Sstevel@tonic-gate 			case ELF_K_AR:
1550Sstevel@tonic-gate 				rc = read_archive(fd, melf, memname, label,
1560Sstevel@tonic-gate 				    func, arg, require_ctf);
1570Sstevel@tonic-gate 				break;
1580Sstevel@tonic-gate 			case ELF_K_ELF:
1590Sstevel@tonic-gate 				rc = read_file(melf, memname, label,
1600Sstevel@tonic-gate 				    func, arg, require_ctf);
1610Sstevel@tonic-gate 				break;
1620Sstevel@tonic-gate 			default:
1630Sstevel@tonic-gate 				terminate("%s: Unknown elf kind %d\n",
1640Sstevel@tonic-gate 				    memname, elf_kind(melf));
1650Sstevel@tonic-gate 			}
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 			free(memname);
1680Sstevel@tonic-gate 		}
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 		cmd = elf_next(melf);
1710Sstevel@tonic-gate 		(void) elf_end(melf);
1720Sstevel@tonic-gate 		secnum++;
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 		if (rc < 0)
1750Sstevel@tonic-gate 			return (rc);
1760Sstevel@tonic-gate 		else
1770Sstevel@tonic-gate 			found += rc;
1780Sstevel@tonic-gate 	}
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 	return (found);
1810Sstevel@tonic-gate }
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate static int
1840Sstevel@tonic-gate read_ctf_common(char *file, char *label, read_cb_f *func, void *arg,
1850Sstevel@tonic-gate     int require_ctf)
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate 	Elf *elf;
1880Sstevel@tonic-gate 	int found = 0;
1890Sstevel@tonic-gate 	int fd;
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 	debug(3, "Reading %s (label %s)\n", file, (label ? label : "NONE"));
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	(void) elf_version(EV_CURRENT);
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 	if ((fd = open(file, O_RDONLY)) < 0)
1960Sstevel@tonic-gate 		terminate("%s: Cannot open for reading", file);
1970Sstevel@tonic-gate 	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
1980Sstevel@tonic-gate 		elfterminate(file, "Cannot read");
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	switch (elf_kind(elf)) {
2010Sstevel@tonic-gate 	case ELF_K_AR:
2020Sstevel@tonic-gate 		found = read_archive(fd, elf, file, label,
2030Sstevel@tonic-gate 		    func, arg, require_ctf);
2040Sstevel@tonic-gate 		break;
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	case ELF_K_ELF:
2070Sstevel@tonic-gate 		found = read_file(elf, file, label,
2080Sstevel@tonic-gate 		    func, arg, require_ctf);
2090Sstevel@tonic-gate 		break;
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	default:
2120Sstevel@tonic-gate 		terminate("%s: Unknown elf kind %d\n", file, elf_kind(elf));
2130Sstevel@tonic-gate 	}
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	(void) elf_end(elf);
2160Sstevel@tonic-gate 	(void) close(fd);
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	return (found);
2190Sstevel@tonic-gate }
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate /*ARGSUSED*/
2220Sstevel@tonic-gate int
2230Sstevel@tonic-gate read_ctf_save_cb(tdata_t *td, char *name, void *retp)
2240Sstevel@tonic-gate {
2250Sstevel@tonic-gate 	tdata_t **tdp = retp;
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	*tdp = td;
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 	return (1);
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate int
2330Sstevel@tonic-gate read_ctf(char **files, int n, char *label, read_cb_f *func, void *private,
2340Sstevel@tonic-gate     int require_ctf)
2350Sstevel@tonic-gate {
2360Sstevel@tonic-gate 	int found;
2370Sstevel@tonic-gate 	int i, rc;
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 	for (i = 0, found = 0; i < n; i++) {
2400Sstevel@tonic-gate 		if ((rc = read_ctf_common(files[i], label, func,
2410Sstevel@tonic-gate 		    private, require_ctf)) < 0)
2420Sstevel@tonic-gate 			return (rc);
2430Sstevel@tonic-gate 		found += rc;
2440Sstevel@tonic-gate 	}
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	return (found);
2470Sstevel@tonic-gate }
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate static int
2500Sstevel@tonic-gate count_archive(int fd, Elf *elf, char *file)
2510Sstevel@tonic-gate {
2520Sstevel@tonic-gate 	Elf *melf;
2530Sstevel@tonic-gate 	Elf_Cmd cmd = ELF_C_READ;
2540Sstevel@tonic-gate 	Elf_Arhdr *arh;
2550Sstevel@tonic-gate 	int nfiles = 0, err = 0;
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 	while ((melf = elf_begin(fd, cmd, elf)) != NULL) {
2580Sstevel@tonic-gate 		if ((arh = elf_getarhdr(melf)) == NULL) {
2590Sstevel@tonic-gate 			warning("Can't process input archive %s\n",
2600Sstevel@tonic-gate 			    file);
2610Sstevel@tonic-gate 			err++;
2620Sstevel@tonic-gate 		}
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 		if (*arh->ar_name != '/')
2650Sstevel@tonic-gate 			nfiles++;
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 		cmd = elf_next(melf);
2680Sstevel@tonic-gate 		(void) elf_end(melf);
2690Sstevel@tonic-gate 	}
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 	if (err > 0)
2720Sstevel@tonic-gate 		return (-1);
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	return (nfiles);
2750Sstevel@tonic-gate }
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate int
2780Sstevel@tonic-gate count_files(char **files, int n)
2790Sstevel@tonic-gate {
2800Sstevel@tonic-gate 	int nfiles = 0, err = 0;
2810Sstevel@tonic-gate 	Elf *elf;
2820Sstevel@tonic-gate 	int fd, rc, i;
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 	(void) elf_version(EV_CURRENT);
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
2870Sstevel@tonic-gate 		char *file = files[i];
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 		if ((fd = open(file, O_RDONLY)) < 0) {
2900Sstevel@tonic-gate 			warning("Can't read input file %s", file);
2910Sstevel@tonic-gate 			err++;
2920Sstevel@tonic-gate 			continue;
2930Sstevel@tonic-gate 		}
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 		if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
2960Sstevel@tonic-gate 			warning("Can't open input file %s: %s\n", file,
297*1951Sjohnlev 			    elf_errmsg(-1));
2980Sstevel@tonic-gate 			err++;
2990Sstevel@tonic-gate 			(void) close(fd);
3000Sstevel@tonic-gate 			continue;
3010Sstevel@tonic-gate 		}
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 		switch (elf_kind(elf)) {
3040Sstevel@tonic-gate 		case ELF_K_AR:
3050Sstevel@tonic-gate 			if ((rc = count_archive(fd, elf, file)) < 0)
3060Sstevel@tonic-gate 				err++;
3070Sstevel@tonic-gate 			else
3080Sstevel@tonic-gate 				nfiles += rc;
3090Sstevel@tonic-gate 			break;
3100Sstevel@tonic-gate 		case ELF_K_ELF:
3110Sstevel@tonic-gate 			nfiles++;
3120Sstevel@tonic-gate 			break;
3130Sstevel@tonic-gate 		default:
3140Sstevel@tonic-gate 			warning("Input file %s is corrupt\n", file);
3150Sstevel@tonic-gate 			err++;
3160Sstevel@tonic-gate 		}
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 		(void) elf_end(elf);
3190Sstevel@tonic-gate 		(void) close(fd);
3200Sstevel@tonic-gate 	}
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	if (err > 0)
3230Sstevel@tonic-gate 		return (-1);
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	debug(2, "Found %d files in %d input files\n", nfiles, n);
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 	return (nfiles);
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate struct symit_data {
3310Sstevel@tonic-gate 	GElf_Shdr si_shdr;
3320Sstevel@tonic-gate 	Elf_Data *si_symd;
3330Sstevel@tonic-gate 	Elf_Data *si_strd;
3340Sstevel@tonic-gate 	GElf_Sym si_cursym;
3350Sstevel@tonic-gate 	char *si_curname;
3360Sstevel@tonic-gate 	char *si_curfile;
3370Sstevel@tonic-gate 	int si_nument;
3380Sstevel@tonic-gate 	int si_next;
3390Sstevel@tonic-gate };
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate symit_data_t *
3420Sstevel@tonic-gate symit_new(Elf *elf, const char *file)
3430Sstevel@tonic-gate {
3440Sstevel@tonic-gate 	symit_data_t *si;
3450Sstevel@tonic-gate 	Elf_Scn *scn;
3460Sstevel@tonic-gate 	int symtabidx;
3470Sstevel@tonic-gate 
348*1951Sjohnlev 	if ((symtabidx = findelfsecidx(elf, file, ".symtab")) < 0)
3490Sstevel@tonic-gate 		return (NULL);
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 	si = xcalloc(sizeof (symit_data_t));
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	if ((scn = elf_getscn(elf, symtabidx)) == NULL ||
3540Sstevel@tonic-gate 	    gelf_getshdr(scn, &si->si_shdr) == NULL ||
3550Sstevel@tonic-gate 	    (si->si_symd = elf_getdata(scn, NULL)) == NULL)
3560Sstevel@tonic-gate 		elfterminate(file, "Cannot read .symtab");
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 	if ((scn = elf_getscn(elf, si->si_shdr.sh_link)) == NULL ||
3590Sstevel@tonic-gate 	    (si->si_strd = elf_getdata(scn, NULL)) == NULL)
3600Sstevel@tonic-gate 		elfterminate(file, "Cannot read strings for .symtab");
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	si->si_nument = si->si_shdr.sh_size / si->si_shdr.sh_entsize;
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 	return (si);
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate void
3680Sstevel@tonic-gate symit_free(symit_data_t *si)
3690Sstevel@tonic-gate {
3700Sstevel@tonic-gate 	free(si);
3710Sstevel@tonic-gate }
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate void
3740Sstevel@tonic-gate symit_reset(symit_data_t *si)
3750Sstevel@tonic-gate {
3760Sstevel@tonic-gate 	si->si_next = 0;
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate char *
3800Sstevel@tonic-gate symit_curfile(symit_data_t *si)
3810Sstevel@tonic-gate {
3820Sstevel@tonic-gate 	return (si->si_curfile);
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate GElf_Sym *
3860Sstevel@tonic-gate symit_next(symit_data_t *si, int type)
3870Sstevel@tonic-gate {
3880Sstevel@tonic-gate 	GElf_Sym sym;
3891882Sjohnlev 	int check_sym = (type == STT_OBJECT || type == STT_FUNC);
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 	for (; si->si_next < si->si_nument; si->si_next++) {
3920Sstevel@tonic-gate 		gelf_getsym(si->si_symd, si->si_next, &si->si_cursym);
3930Sstevel@tonic-gate 		gelf_getsym(si->si_symd, si->si_next, &sym);
3940Sstevel@tonic-gate 		si->si_curname = (caddr_t)si->si_strd->d_buf + sym.st_name;
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 		if (GELF_ST_TYPE(sym.st_info) == STT_FILE)
3970Sstevel@tonic-gate 			si->si_curfile = si->si_curname;
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 		if (GELF_ST_TYPE(sym.st_info) != type ||
4000Sstevel@tonic-gate 		    sym.st_shndx == SHN_UNDEF)
4010Sstevel@tonic-gate 			continue;
4020Sstevel@tonic-gate 
4031882Sjohnlev 		if (check_sym && ignore_symbol(&sym, si->si_curname))
4041882Sjohnlev 			continue;
4051882Sjohnlev 
4060Sstevel@tonic-gate 		si->si_next++;
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 		return (&si->si_cursym);
4090Sstevel@tonic-gate 	}
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 	return (NULL);
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate char *
4150Sstevel@tonic-gate symit_name(symit_data_t *si)
4160Sstevel@tonic-gate {
4170Sstevel@tonic-gate 	return (si->si_curname);
4180Sstevel@tonic-gate }
419