xref: /freebsd/cddl/contrib/opensolaris/tools/ctf/cvt/input.c (revision 40f65a4df509c6b29b9e72407c7afefe28838844)
11673e404SJohn Birrell /*
21673e404SJohn Birrell  * CDDL HEADER START
31673e404SJohn Birrell  *
41673e404SJohn Birrell  * The contents of this file are subject to the terms of the
51673e404SJohn Birrell  * Common Development and Distribution License (the "License").
61673e404SJohn Birrell  * You may not use this file except in compliance with the License.
71673e404SJohn Birrell  *
81673e404SJohn Birrell  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91673e404SJohn Birrell  * or http://www.opensolaris.org/os/licensing.
101673e404SJohn Birrell  * See the License for the specific language governing permissions
111673e404SJohn Birrell  * and limitations under the License.
121673e404SJohn Birrell  *
131673e404SJohn Birrell  * When distributing Covered Code, include this CDDL HEADER in each
141673e404SJohn Birrell  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151673e404SJohn Birrell  * If applicable, add the following below this CDDL HEADER, with the
161673e404SJohn Birrell  * fields enclosed by brackets "[]" replaced with your own identifying
171673e404SJohn Birrell  * information: Portions Copyright [yyyy] [name of copyright owner]
181673e404SJohn Birrell  *
191673e404SJohn Birrell  * CDDL HEADER END
201673e404SJohn Birrell  */
211673e404SJohn Birrell /*
221673e404SJohn Birrell  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
231673e404SJohn Birrell  * Use is subject to license terms.
241673e404SJohn Birrell  */
251673e404SJohn Birrell 
261673e404SJohn Birrell #pragma ident	"%Z%%M%	%I%	%E% SMI"
271673e404SJohn Birrell 
281673e404SJohn Birrell /*
291673e404SJohn Birrell  * Routines for retrieving CTF data from a .SUNW_ctf ELF section
301673e404SJohn Birrell  */
311673e404SJohn Birrell 
321673e404SJohn Birrell #include <stdio.h>
331673e404SJohn Birrell #include <stdlib.h>
341673e404SJohn Birrell #include <fcntl.h>
351673e404SJohn Birrell #include <unistd.h>
361673e404SJohn Birrell #include <gelf.h>
371673e404SJohn Birrell #include <strings.h>
381673e404SJohn Birrell #include <sys/types.h>
391673e404SJohn Birrell 
401673e404SJohn Birrell #include "ctftools.h"
411673e404SJohn Birrell #include "memory.h"
421673e404SJohn Birrell #include "symbol.h"
431673e404SJohn Birrell 
441673e404SJohn Birrell typedef int read_cb_f(tdata_t *, char *, void *);
451673e404SJohn Birrell 
461673e404SJohn Birrell /*
471673e404SJohn Birrell  * Return the source types that the object was generated from.
481673e404SJohn Birrell  */
491673e404SJohn Birrell source_types_t
built_source_types(Elf * elf,char const * file)501673e404SJohn Birrell built_source_types(Elf *elf, char const *file)
511673e404SJohn Birrell {
521673e404SJohn Birrell 	source_types_t types = SOURCE_NONE;
531673e404SJohn Birrell 	symit_data_t *si;
541673e404SJohn Birrell 
551673e404SJohn Birrell 	if ((si = symit_new(elf, file)) == NULL)
561673e404SJohn Birrell 		return (SOURCE_NONE);
571673e404SJohn Birrell 
581673e404SJohn Birrell 	while (symit_next(si, STT_FILE) != NULL) {
591673e404SJohn Birrell 		char *name = symit_name(si);
601673e404SJohn Birrell 		size_t len = strlen(name);
611673e404SJohn Birrell 		if (len < 2 || name[len - 2] != '.') {
621673e404SJohn Birrell 			types |= SOURCE_UNKNOWN;
631673e404SJohn Birrell 			continue;
641673e404SJohn Birrell 		}
651673e404SJohn Birrell 
661673e404SJohn Birrell 		switch (name[len - 1]) {
671673e404SJohn Birrell 		case 'c':
681673e404SJohn Birrell 			types |= SOURCE_C;
691673e404SJohn Birrell 			break;
701673e404SJohn Birrell 		case 'h':
711673e404SJohn Birrell 			/* ignore */
721673e404SJohn Birrell 			break;
731673e404SJohn Birrell 		case 's':
744cc75139SJohn Birrell 		case 'S':
751673e404SJohn Birrell 			types |= SOURCE_S;
761673e404SJohn Birrell 			break;
771673e404SJohn Birrell 		default:
781673e404SJohn Birrell 			types |= SOURCE_UNKNOWN;
791673e404SJohn Birrell 		}
801673e404SJohn Birrell 	}
811673e404SJohn Birrell 
821673e404SJohn Birrell 	symit_free(si);
831673e404SJohn Birrell 	return (types);
841673e404SJohn Birrell }
851673e404SJohn Birrell 
861673e404SJohn Birrell static int
read_file(Elf * elf,char * file,char * label,read_cb_f * func,void * arg,int require_ctf)871673e404SJohn Birrell read_file(Elf *elf, char *file, char *label, read_cb_f *func, void *arg,
881673e404SJohn Birrell     int require_ctf)
891673e404SJohn Birrell {
901673e404SJohn Birrell 	Elf_Scn *ctfscn;
914cc75139SJohn Birrell 	Elf_Data *ctfdata = NULL;
921673e404SJohn Birrell 	symit_data_t *si = NULL;
931673e404SJohn Birrell 	int ctfscnidx;
941673e404SJohn Birrell 	tdata_t *td;
951673e404SJohn Birrell 
961673e404SJohn Birrell 	if ((ctfscnidx = findelfsecidx(elf, file, ".SUNW_ctf")) < 0) {
971673e404SJohn Birrell 		if (require_ctf &&
981673e404SJohn Birrell 		    (built_source_types(elf, file) & SOURCE_C)) {
991673e404SJohn Birrell 			terminate("Input file %s was partially built from "
1001673e404SJohn Birrell 			    "C sources, but no CTF data was present\n", file);
1011673e404SJohn Birrell 		}
1021673e404SJohn Birrell 		return (0);
1031673e404SJohn Birrell 	}
1041673e404SJohn Birrell 
1051673e404SJohn Birrell 	if ((ctfscn = elf_getscn(elf, ctfscnidx)) == NULL ||
1061673e404SJohn Birrell 	    (ctfdata = elf_getdata(ctfscn, NULL)) == NULL)
1071673e404SJohn Birrell 		elfterminate(file, "Cannot read CTF section");
1081673e404SJohn Birrell 
1091673e404SJohn Birrell 	/* Reconstruction of type tree */
1101673e404SJohn Birrell 	if ((si = symit_new(elf, file)) == NULL) {
1111673e404SJohn Birrell 		warning("%s has no symbol table - skipping", file);
1121673e404SJohn Birrell 		return (0);
1131673e404SJohn Birrell 	}
1141673e404SJohn Birrell 
1151673e404SJohn Birrell 	td = ctf_load(file, ctfdata->d_buf, ctfdata->d_size, si, label);
1161673e404SJohn Birrell 	tdata_build_hashes(td);
1171673e404SJohn Birrell 
1181673e404SJohn Birrell 	symit_free(si);
1191673e404SJohn Birrell 
1201673e404SJohn Birrell 	if (td != NULL) {
1211673e404SJohn Birrell 		if (func(td, file, arg) < 0)
1221673e404SJohn Birrell 			return (-1);
1231673e404SJohn Birrell 		else
1241673e404SJohn Birrell 			return (1);
1251673e404SJohn Birrell 	}
1261673e404SJohn Birrell 	return (0);
1271673e404SJohn Birrell }
1281673e404SJohn Birrell 
1291673e404SJohn Birrell static int
read_archive(int fd,Elf * elf,char * file,char * label,read_cb_f * func,void * arg,int require_ctf)1301673e404SJohn Birrell read_archive(int fd, Elf *elf, char *file, char *label, read_cb_f *func,
1311673e404SJohn Birrell     void *arg, int require_ctf)
1321673e404SJohn Birrell {
1331673e404SJohn Birrell 	Elf *melf;
1341673e404SJohn Birrell 	Elf_Cmd cmd = ELF_C_READ;
1351673e404SJohn Birrell 	Elf_Arhdr *arh;
1361673e404SJohn Birrell 	int secnum = 1, found = 0;
1371673e404SJohn Birrell 
1381673e404SJohn Birrell 	while ((melf = elf_begin(fd, cmd, elf)) != NULL) {
1391673e404SJohn Birrell 		int rc = 0;
1401673e404SJohn Birrell 
1411673e404SJohn Birrell 		if ((arh = elf_getarhdr(melf)) == NULL) {
1421673e404SJohn Birrell 			elfterminate(file, "Can't get archive header for "
1431673e404SJohn Birrell 			    "member %d", secnum);
1441673e404SJohn Birrell 		}
1451673e404SJohn Birrell 
1461673e404SJohn Birrell 		/* skip special sections - their names begin with "/" */
1471673e404SJohn Birrell 		if (*arh->ar_name != '/') {
1481673e404SJohn Birrell 			size_t memlen = strlen(file) + 1 +
1491673e404SJohn Birrell 			    strlen(arh->ar_name) + 1 + 1;
1501673e404SJohn Birrell 			char *memname = xmalloc(memlen);
1511673e404SJohn Birrell 
1521673e404SJohn Birrell 			snprintf(memname, memlen, "%s(%s)", file, arh->ar_name);
1531673e404SJohn Birrell 
1541673e404SJohn Birrell 			switch (elf_kind(melf)) {
1551673e404SJohn Birrell 			case ELF_K_AR:
1561673e404SJohn Birrell 				rc = read_archive(fd, melf, memname, label,
1571673e404SJohn Birrell 				    func, arg, require_ctf);
1581673e404SJohn Birrell 				break;
1591673e404SJohn Birrell 			case ELF_K_ELF:
1601673e404SJohn Birrell 				rc = read_file(melf, memname, label,
1611673e404SJohn Birrell 				    func, arg, require_ctf);
1621673e404SJohn Birrell 				break;
1631673e404SJohn Birrell 			default:
1641673e404SJohn Birrell 				terminate("%s: Unknown elf kind %d\n",
1651673e404SJohn Birrell 				    memname, elf_kind(melf));
1661673e404SJohn Birrell 			}
1671673e404SJohn Birrell 
1681673e404SJohn Birrell 			free(memname);
1691673e404SJohn Birrell 		}
1701673e404SJohn Birrell 
1711673e404SJohn Birrell 		cmd = elf_next(melf);
1721673e404SJohn Birrell 		(void) elf_end(melf);
1731673e404SJohn Birrell 		secnum++;
1741673e404SJohn Birrell 
1751673e404SJohn Birrell 		if (rc < 0)
1761673e404SJohn Birrell 			return (rc);
1771673e404SJohn Birrell 		else
1781673e404SJohn Birrell 			found += rc;
1791673e404SJohn Birrell 	}
1801673e404SJohn Birrell 
1811673e404SJohn Birrell 	return (found);
1821673e404SJohn Birrell }
1831673e404SJohn Birrell 
1841673e404SJohn Birrell static int
read_ctf_common(char * file,char * label,read_cb_f * func,void * arg,int require_ctf)1851673e404SJohn Birrell read_ctf_common(char *file, char *label, read_cb_f *func, void *arg,
1861673e404SJohn Birrell     int require_ctf)
1871673e404SJohn Birrell {
1881673e404SJohn Birrell 	Elf *elf;
1891673e404SJohn Birrell 	int found = 0;
1901673e404SJohn Birrell 	int fd;
1911673e404SJohn Birrell 
1921673e404SJohn Birrell 	debug(3, "Reading %s (label %s)\n", file, (label ? label : "NONE"));
1931673e404SJohn Birrell 
1941673e404SJohn Birrell 	(void) elf_version(EV_CURRENT);
1951673e404SJohn Birrell 
1961673e404SJohn Birrell 	if ((fd = open(file, O_RDONLY)) < 0)
1971673e404SJohn Birrell 		terminate("%s: Cannot open for reading", file);
1981673e404SJohn Birrell 	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
1991673e404SJohn Birrell 		elfterminate(file, "Cannot read");
2001673e404SJohn Birrell 
2011673e404SJohn Birrell 	switch (elf_kind(elf)) {
2021673e404SJohn Birrell 	case ELF_K_AR:
2031673e404SJohn Birrell 		found = read_archive(fd, elf, file, label,
2041673e404SJohn Birrell 		    func, arg, require_ctf);
2051673e404SJohn Birrell 		break;
2061673e404SJohn Birrell 
2071673e404SJohn Birrell 	case ELF_K_ELF:
2081673e404SJohn Birrell 		found = read_file(elf, file, label,
2091673e404SJohn Birrell 		    func, arg, require_ctf);
2101673e404SJohn Birrell 		break;
2111673e404SJohn Birrell 
2121673e404SJohn Birrell 	default:
2131673e404SJohn Birrell 		terminate("%s: Unknown elf kind %d\n", file, elf_kind(elf));
2141673e404SJohn Birrell 	}
2151673e404SJohn Birrell 
2161673e404SJohn Birrell 	(void) elf_end(elf);
2171673e404SJohn Birrell 	(void) close(fd);
2181673e404SJohn Birrell 
2191673e404SJohn Birrell 	return (found);
2201673e404SJohn Birrell }
2211673e404SJohn Birrell 
2221673e404SJohn Birrell /*ARGSUSED*/
2231673e404SJohn Birrell int
read_ctf_save_cb(tdata_t * td,char * name __unused,void * retp)2244cc75139SJohn Birrell read_ctf_save_cb(tdata_t *td, char *name __unused, void *retp)
2251673e404SJohn Birrell {
2261673e404SJohn Birrell 	tdata_t **tdp = retp;
2271673e404SJohn Birrell 
2281673e404SJohn Birrell 	*tdp = td;
2291673e404SJohn Birrell 
2301673e404SJohn Birrell 	return (1);
2311673e404SJohn Birrell }
2321673e404SJohn Birrell 
2331673e404SJohn Birrell int
read_ctf(char ** files,int n,char * label,read_cb_f * func,void * private,int require_ctf)2341673e404SJohn Birrell read_ctf(char **files, int n, char *label, read_cb_f *func, void *private,
2351673e404SJohn Birrell     int require_ctf)
2361673e404SJohn Birrell {
2371673e404SJohn Birrell 	int found;
2381673e404SJohn Birrell 	int i, rc;
2391673e404SJohn Birrell 
2401673e404SJohn Birrell 	for (i = 0, found = 0; i < n; i++) {
2411673e404SJohn Birrell 		if ((rc = read_ctf_common(files[i], label, func,
2421673e404SJohn Birrell 		    private, require_ctf)) < 0)
2431673e404SJohn Birrell 			return (rc);
2441673e404SJohn Birrell 		found += rc;
2451673e404SJohn Birrell 	}
2461673e404SJohn Birrell 
2471673e404SJohn Birrell 	return (found);
2481673e404SJohn Birrell }
2491673e404SJohn Birrell 
2501673e404SJohn Birrell static int
count_archive(int fd,Elf * elf,char * file)2511673e404SJohn Birrell count_archive(int fd, Elf *elf, char *file)
2521673e404SJohn Birrell {
2531673e404SJohn Birrell 	Elf *melf;
2541673e404SJohn Birrell 	Elf_Cmd cmd = ELF_C_READ;
2551673e404SJohn Birrell 	Elf_Arhdr *arh;
2561673e404SJohn Birrell 	int nfiles = 0, err = 0;
2571673e404SJohn Birrell 
2581673e404SJohn Birrell 	while ((melf = elf_begin(fd, cmd, elf)) != NULL) {
2591673e404SJohn Birrell 		if ((arh = elf_getarhdr(melf)) == NULL) {
2601673e404SJohn Birrell 			warning("Can't process input archive %s\n",
2611673e404SJohn Birrell 			    file);
2621673e404SJohn Birrell 			err++;
2631673e404SJohn Birrell 		}
2641673e404SJohn Birrell 
2651673e404SJohn Birrell 		if (*arh->ar_name != '/')
2661673e404SJohn Birrell 			nfiles++;
2671673e404SJohn Birrell 
2681673e404SJohn Birrell 		cmd = elf_next(melf);
2691673e404SJohn Birrell 		(void) elf_end(melf);
2701673e404SJohn Birrell 	}
2711673e404SJohn Birrell 
2721673e404SJohn Birrell 	if (err > 0)
2731673e404SJohn Birrell 		return (-1);
2741673e404SJohn Birrell 
2751673e404SJohn Birrell 	return (nfiles);
2761673e404SJohn Birrell }
2771673e404SJohn Birrell 
2781673e404SJohn Birrell int
count_files(char ** files,int n)2791673e404SJohn Birrell count_files(char **files, int n)
2801673e404SJohn Birrell {
2811673e404SJohn Birrell 	int nfiles = 0, err = 0;
2821673e404SJohn Birrell 	Elf *elf;
2831673e404SJohn Birrell 	int fd, rc, i;
2841673e404SJohn Birrell 
2851673e404SJohn Birrell 	(void) elf_version(EV_CURRENT);
2861673e404SJohn Birrell 
2871673e404SJohn Birrell 	for (i = 0; i < n; i++) {
2881673e404SJohn Birrell 		char *file = files[i];
2891673e404SJohn Birrell 
2901673e404SJohn Birrell 		if ((fd = open(file, O_RDONLY)) < 0) {
2911673e404SJohn Birrell 			warning("Can't read input file %s", file);
2921673e404SJohn Birrell 			err++;
2931673e404SJohn Birrell 			continue;
2941673e404SJohn Birrell 		}
2951673e404SJohn Birrell 
2961673e404SJohn Birrell 		if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
2971673e404SJohn Birrell 			warning("Can't open input file %s: %s\n", file,
2981673e404SJohn Birrell 			    elf_errmsg(-1));
2991673e404SJohn Birrell 			err++;
3001673e404SJohn Birrell 			(void) close(fd);
3011673e404SJohn Birrell 			continue;
3021673e404SJohn Birrell 		}
3031673e404SJohn Birrell 
3041673e404SJohn Birrell 		switch (elf_kind(elf)) {
3051673e404SJohn Birrell 		case ELF_K_AR:
3061673e404SJohn Birrell 			if ((rc = count_archive(fd, elf, file)) < 0)
3071673e404SJohn Birrell 				err++;
3081673e404SJohn Birrell 			else
3091673e404SJohn Birrell 				nfiles += rc;
3101673e404SJohn Birrell 			break;
3111673e404SJohn Birrell 		case ELF_K_ELF:
3121673e404SJohn Birrell 			nfiles++;
3131673e404SJohn Birrell 			break;
3141673e404SJohn Birrell 		default:
3151673e404SJohn Birrell 			warning("Input file %s is corrupt\n", file);
3161673e404SJohn Birrell 			err++;
3171673e404SJohn Birrell 		}
3181673e404SJohn Birrell 
3191673e404SJohn Birrell 		(void) elf_end(elf);
3201673e404SJohn Birrell 		(void) close(fd);
3211673e404SJohn Birrell 	}
3221673e404SJohn Birrell 
3231673e404SJohn Birrell 	if (err > 0)
3241673e404SJohn Birrell 		return (-1);
3251673e404SJohn Birrell 
3261673e404SJohn Birrell 	debug(2, "Found %d files in %d input files\n", nfiles, n);
3271673e404SJohn Birrell 
3281673e404SJohn Birrell 	return (nfiles);
3291673e404SJohn Birrell }
3301673e404SJohn Birrell 
3311673e404SJohn Birrell struct symit_data {
3321673e404SJohn Birrell 	GElf_Shdr si_shdr;
3331673e404SJohn Birrell 	Elf_Data *si_symd;
3341673e404SJohn Birrell 	Elf_Data *si_strd;
3351673e404SJohn Birrell 	GElf_Sym si_cursym;
3361673e404SJohn Birrell 	char *si_curname;
3371673e404SJohn Birrell 	char *si_curfile;
3381673e404SJohn Birrell 	int si_nument;
3391673e404SJohn Birrell 	int si_next;
3401673e404SJohn Birrell };
3411673e404SJohn Birrell 
3421673e404SJohn Birrell symit_data_t *
symit_new(Elf * elf,const char * file)3431673e404SJohn Birrell symit_new(Elf *elf, const char *file)
3441673e404SJohn Birrell {
3451673e404SJohn Birrell 	symit_data_t *si;
3461673e404SJohn Birrell 	Elf_Scn *scn;
3471673e404SJohn Birrell 	int symtabidx;
3481673e404SJohn Birrell 
3491673e404SJohn Birrell 	if ((symtabidx = findelfsecidx(elf, file, ".symtab")) < 0)
3501673e404SJohn Birrell 		return (NULL);
3511673e404SJohn Birrell 
3521673e404SJohn Birrell 	si = xcalloc(sizeof (symit_data_t));
3531673e404SJohn Birrell 
3541673e404SJohn Birrell 	if ((scn = elf_getscn(elf, symtabidx)) == NULL ||
3551673e404SJohn Birrell 	    gelf_getshdr(scn, &si->si_shdr) == NULL ||
3561673e404SJohn Birrell 	    (si->si_symd = elf_getdata(scn, NULL)) == NULL)
3571673e404SJohn Birrell 		elfterminate(file, "Cannot read .symtab");
3581673e404SJohn Birrell 
3591673e404SJohn Birrell 	if ((scn = elf_getscn(elf, si->si_shdr.sh_link)) == NULL ||
3601673e404SJohn Birrell 	    (si->si_strd = elf_getdata(scn, NULL)) == NULL)
3611673e404SJohn Birrell 		elfterminate(file, "Cannot read strings for .symtab");
3621673e404SJohn Birrell 
3631673e404SJohn Birrell 	si->si_nument = si->si_shdr.sh_size / si->si_shdr.sh_entsize;
3641673e404SJohn Birrell 
3651673e404SJohn Birrell 	return (si);
3661673e404SJohn Birrell }
3671673e404SJohn Birrell 
3681673e404SJohn Birrell void
symit_free(symit_data_t * si)3691673e404SJohn Birrell symit_free(symit_data_t *si)
3701673e404SJohn Birrell {
3711673e404SJohn Birrell 	free(si);
3721673e404SJohn Birrell }
3731673e404SJohn Birrell 
3741673e404SJohn Birrell void
symit_reset(symit_data_t * si)3751673e404SJohn Birrell symit_reset(symit_data_t *si)
3761673e404SJohn Birrell {
3771673e404SJohn Birrell 	si->si_next = 0;
3781673e404SJohn Birrell }
3791673e404SJohn Birrell 
3801673e404SJohn Birrell char *
symit_curfile(symit_data_t * si)3811673e404SJohn Birrell symit_curfile(symit_data_t *si)
3821673e404SJohn Birrell {
3831673e404SJohn Birrell 	return (si->si_curfile);
3841673e404SJohn Birrell }
3851673e404SJohn Birrell 
3861673e404SJohn Birrell GElf_Sym *
symit_next(symit_data_t * si,int type)3871673e404SJohn Birrell symit_next(symit_data_t *si, int type)
3881673e404SJohn Birrell {
3891673e404SJohn Birrell 	GElf_Sym sym;
390*51ff6adcSDimitry Andric 	char *bname;
3911673e404SJohn Birrell 	int check_sym = (type == STT_OBJECT || type == STT_FUNC);
3921673e404SJohn Birrell 
3931673e404SJohn Birrell 	for (; si->si_next < si->si_nument; si->si_next++) {
3941673e404SJohn Birrell 		gelf_getsym(si->si_symd, si->si_next, &si->si_cursym);
3951673e404SJohn Birrell 		gelf_getsym(si->si_symd, si->si_next, &sym);
3961673e404SJohn Birrell 		si->si_curname = (caddr_t)si->si_strd->d_buf + sym.st_name;
3971673e404SJohn Birrell 
398*51ff6adcSDimitry Andric 		if (GELF_ST_TYPE(sym.st_info) == STT_FILE) {
399*51ff6adcSDimitry Andric 			bname = strrchr(si->si_curname, '/');
400*51ff6adcSDimitry Andric 			si->si_curfile = bname == NULL ? si->si_curname : bname + 1;
401*51ff6adcSDimitry Andric 		}
4021673e404SJohn Birrell 
4031673e404SJohn Birrell 		if (GELF_ST_TYPE(sym.st_info) != type ||
4041673e404SJohn Birrell 		    sym.st_shndx == SHN_UNDEF)
4051673e404SJohn Birrell 			continue;
4061673e404SJohn Birrell 
4071673e404SJohn Birrell 		if (check_sym && ignore_symbol(&sym, si->si_curname))
4081673e404SJohn Birrell 			continue;
4091673e404SJohn Birrell 
4101673e404SJohn Birrell 		si->si_next++;
4111673e404SJohn Birrell 
4121673e404SJohn Birrell 		return (&si->si_cursym);
4131673e404SJohn Birrell 	}
4141673e404SJohn Birrell 
4151673e404SJohn Birrell 	return (NULL);
4161673e404SJohn Birrell }
4171673e404SJohn Birrell 
4181673e404SJohn Birrell char *
symit_name(symit_data_t * si)4191673e404SJohn Birrell symit_name(symit_data_t *si)
4201673e404SJohn Birrell {
4211673e404SJohn Birrell 	return (si->si_curname);
4221673e404SJohn Birrell }
423