xref: /onnv-gate/usr/src/cmd/abi/appcert/static_prof/static_prof.c (revision 71:d82f85a1a592)
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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
22*71Scraigm 
230Sstevel@tonic-gate /*
240Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
250Sstevel@tonic-gate  * Use is subject to license terms.
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T */
290Sstevel@tonic-gate /*	  All Rights Reserved	*/
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
320Sstevel@tonic-gate 
330Sstevel@tonic-gate 
340Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
350Sstevel@tonic-gate /* include headers */
360Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
370Sstevel@tonic-gate 
380Sstevel@tonic-gate #include "static_prof.h"
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /* ========== elf_hash ==================================================== */
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate  * DESCRIPTION:
430Sstevel@tonic-gate  * The hash function copied from libelf.so.1
440Sstevel@tonic-gate  */
450Sstevel@tonic-gate /* ======================================================================== */
460Sstevel@tonic-gate 
470Sstevel@tonic-gate static unsigned long
my_elf_hash(const char * name)480Sstevel@tonic-gate my_elf_hash(const char *name)
490Sstevel@tonic-gate {
500Sstevel@tonic-gate 	unsigned long g, h = 0;
510Sstevel@tonic-gate 	const unsigned char *nm = (unsigned char *) name;
520Sstevel@tonic-gate 
530Sstevel@tonic-gate 	while (*nm != '\0') {
540Sstevel@tonic-gate 		h = (h << 4) + *nm++;
550Sstevel@tonic-gate 		if ((g = h & MASK) != 0)
560Sstevel@tonic-gate 			h ^= g >> 24;
570Sstevel@tonic-gate 		h &= ~MASK;
580Sstevel@tonic-gate 	}
590Sstevel@tonic-gate 	return (h);
600Sstevel@tonic-gate }
610Sstevel@tonic-gate 
620Sstevel@tonic-gate /* ========== output_dtneeded ============================================= */
630Sstevel@tonic-gate /*
640Sstevel@tonic-gate  * DESCRIPTION:
650Sstevel@tonic-gate  * Outputs all the dt_needed entries if any.
660Sstevel@tonic-gate  */
670Sstevel@tonic-gate /* ======================================================================== */
680Sstevel@tonic-gate 
690Sstevel@tonic-gate static void
output_dtneeded(dt_list * list)700Sstevel@tonic-gate output_dtneeded(dt_list * list)
710Sstevel@tonic-gate {
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 	dt_list		*p = list;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	(void) fprintf(OUTPUT_FD, "#dtneeded:");
760Sstevel@tonic-gate 	if (!p) {
770Sstevel@tonic-gate 		(void) fprintf(OUTPUT_FD, "\n");
780Sstevel@tonic-gate 		return;
790Sstevel@tonic-gate 	} else {
800Sstevel@tonic-gate 		while (p != NULL) {
810Sstevel@tonic-gate 			(void) fprintf(OUTPUT_FD,
820Sstevel@tonic-gate 			    " %s",
830Sstevel@tonic-gate 			    p->libname);
840Sstevel@tonic-gate 			p = p->next;
850Sstevel@tonic-gate 		}
860Sstevel@tonic-gate 		(void) fprintf(OUTPUT_FD, "\n");
870Sstevel@tonic-gate 	}
880Sstevel@tonic-gate }
890Sstevel@tonic-gate 
900Sstevel@tonic-gate /* ========== store_binding =============================================== */
910Sstevel@tonic-gate /*
920Sstevel@tonic-gate  * DESCRIPTION:
930Sstevel@tonic-gate  * Read in the symbol binding information from the symbol table and
940Sstevel@tonic-gate  * store them into the hash table of buckets.
950Sstevel@tonic-gate  */
960Sstevel@tonic-gate /* ======================================================================== */
970Sstevel@tonic-gate 
980Sstevel@tonic-gate static void
store_binding(binding_bucket * bind)990Sstevel@tonic-gate store_binding(binding_bucket * bind)
1000Sstevel@tonic-gate {
1010Sstevel@tonic-gate 	unsigned long   bktno;
1020Sstevel@tonic-gate 	unsigned long   orig_bktno;
1030Sstevel@tonic-gate 	int		table_full = FALSE;
1040Sstevel@tonic-gate 	int		i;
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	bktno = my_elf_hash(bind->sym) % DEFBKTS;
1070Sstevel@tonic-gate 	orig_bktno = bktno;
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	if (!bkts[bktno].sym) {
1100Sstevel@tonic-gate 		bkts[bktno].sym = bind->sym;
1110Sstevel@tonic-gate 		bkts[bktno].obj = bind->obj;
1120Sstevel@tonic-gate 		bkts[bktno].ref_lib = bind->ref_lib;
1130Sstevel@tonic-gate 		bkts[bktno].def_lib = bind->def_lib;
1140Sstevel@tonic-gate 		bkts[bktno].section = bind->section;
1150Sstevel@tonic-gate 		bkts[bktno].stbind = bind->stbind;
1160Sstevel@tonic-gate 		bkts[bktno].sttype = bind->sttype;
1170Sstevel@tonic-gate 	} else {
1180Sstevel@tonic-gate 		bktno = (bktno + 1) % DEFBKTS;
1190Sstevel@tonic-gate 		for (i = bktno; i < DEFBKTS; i = (i + 1) % DEFBKTS) {
1200Sstevel@tonic-gate 			if (i == orig_bktno) {
1210Sstevel@tonic-gate 				table_full = TRUE;
1220Sstevel@tonic-gate 				exit(1);
1230Sstevel@tonic-gate 			}
1240Sstevel@tonic-gate 			if (!bkts[i].sym)
1250Sstevel@tonic-gate 				break;
1260Sstevel@tonic-gate 		}
1270Sstevel@tonic-gate 		if ((!bkts[i].sym) && (table_full != TRUE)) {
1280Sstevel@tonic-gate 			bkts[i].sym = bind->sym;
1290Sstevel@tonic-gate 			bkts[i].obj = bind->obj;
1300Sstevel@tonic-gate 			bkts[i].ref_lib = bind->ref_lib;
1310Sstevel@tonic-gate 			bkts[i].def_lib = bind->def_lib;
1320Sstevel@tonic-gate 			bkts[i].section = bind->section;
1330Sstevel@tonic-gate 			bkts[i].stbind = bind->stbind;
1340Sstevel@tonic-gate 			bkts[i].sttype = bind->sttype;
1350Sstevel@tonic-gate 		}
1360Sstevel@tonic-gate 	}
1370Sstevel@tonic-gate }
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate /* ========== check_store_binding ========================================= */
1400Sstevel@tonic-gate /*
1410Sstevel@tonic-gate  * DESCRIPTION:
1420Sstevel@tonic-gate  * Check what's already on the hash table with the new symbol binding
1430Sstevel@tonic-gate  * information from the dependencies and record it into the bucket.
1440Sstevel@tonic-gate  */
1450Sstevel@tonic-gate /* ======================================================================== */
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate static void
check_store_binding(binding_bucket * bind)1480Sstevel@tonic-gate check_store_binding(binding_bucket * bind)
1490Sstevel@tonic-gate {
1500Sstevel@tonic-gate 	unsigned long   bktno;
1510Sstevel@tonic-gate 	unsigned long   orig_bktno;
1520Sstevel@tonic-gate 	unsigned long   i;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	bktno = my_elf_hash(bind->sym) % DEFBKTS;
1550Sstevel@tonic-gate 	orig_bktno = bktno;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	if (!bkts[bktno].sym)
1580Sstevel@tonic-gate 		return;
1590Sstevel@tonic-gate 	if (bkts[bktno].sym && (strcmp(bkts[bktno].sym, bind->sym)) == 0) {
1600Sstevel@tonic-gate 		if (strcmp(bkts[bktno].ref_lib, "<Unknown>") == 0)
1610Sstevel@tonic-gate 			if (strcmp(bkts[bktno].obj, bind->obj))
1620Sstevel@tonic-gate 				bkts[bktno].ref_lib = bind->obj;
1630Sstevel@tonic-gate 	} else {
1640Sstevel@tonic-gate 		bktno = (bktno + 1) % DEFBKTS;
1650Sstevel@tonic-gate 		for (i = bktno; i < DEFBKTS; i = (i + 1) % DEFBKTS) {
1660Sstevel@tonic-gate 			if (i == orig_bktno)
1670Sstevel@tonic-gate 				break;
1680Sstevel@tonic-gate 			if (!bkts[i].sym)
1690Sstevel@tonic-gate 				continue;
1700Sstevel@tonic-gate 			if (bkts[i].sym &&
1710Sstevel@tonic-gate 			    (strcmp(bkts[i].sym, bind->sym)) == 0) {
1720Sstevel@tonic-gate 				if (strcmp(bkts[i].ref_lib, "<Unknown>") == 0)
1730Sstevel@tonic-gate 					if (strcmp(bkts[i].obj, bind->obj))
1740Sstevel@tonic-gate 						bkts[i].ref_lib = bind->obj;
1750Sstevel@tonic-gate 				break;
1760Sstevel@tonic-gate 			}
1770Sstevel@tonic-gate 		}
1780Sstevel@tonic-gate 	}
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate /* ========== stringcompare =============================================== */
1820Sstevel@tonic-gate /*
1830Sstevel@tonic-gate  * DESCRIPTION:
1840Sstevel@tonic-gate  * Compares two strings for qsort().
1850Sstevel@tonic-gate  */
1860Sstevel@tonic-gate /* ======================================================================== */
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate static int
stringcompare(binding_bucket * a,binding_bucket * b)1890Sstevel@tonic-gate stringcompare(binding_bucket * a,
1900Sstevel@tonic-gate     binding_bucket * b)
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate 	char		*x = "\0";
1930Sstevel@tonic-gate 	char		*y = "\0";
1940Sstevel@tonic-gate 	int		retcode;
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 	if (a->sym)
1970Sstevel@tonic-gate 		x = a->sym;
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 	if (b->sym)
2000Sstevel@tonic-gate 		y = b->sym;
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	retcode = strcoll(x, y);
2030Sstevel@tonic-gate 	return (retcode);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate /* ========== profile_binding ============================================= */
2070Sstevel@tonic-gate /*
2080Sstevel@tonic-gate  * DESCRIPTION:
2090Sstevel@tonic-gate  * Output the bindings directly to stdout or a file.
2100Sstevel@tonic-gate  */
2110Sstevel@tonic-gate /* ======================================================================== */
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate static void
profile_binding(binding_bucket * bind)2140Sstevel@tonic-gate profile_binding(binding_bucket * bind)
2150Sstevel@tonic-gate {
2160Sstevel@tonic-gate 	char		*ref_lib_ptr;
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	if (bind->sym && strcmp(bind->ref_lib, "<Unknown>")) {
2190Sstevel@tonic-gate 		if (ref_lib_ptr = strrchr(bind->ref_lib, (int)'/')) {
2200Sstevel@tonic-gate 			ref_lib_ptr++;
2210Sstevel@tonic-gate 			if (bind->stbind)
2220Sstevel@tonic-gate 				(void) fprintf(OUTPUT_FD,
2230Sstevel@tonic-gate 				    "%s|%s|%s|%s|%s|%s|%s\n",
2240Sstevel@tonic-gate 				    ref_lib_ptr,
2250Sstevel@tonic-gate 				    bind->section,
2260Sstevel@tonic-gate 				    bind->stbind,
2270Sstevel@tonic-gate 				    bind->sttype,
2280Sstevel@tonic-gate 				    bind->sym,
2290Sstevel@tonic-gate 				    bind->def_lib,
2300Sstevel@tonic-gate 				    bind->obj);
2310Sstevel@tonic-gate 		} else if (bind->stbind)
2320Sstevel@tonic-gate 			(void) fprintf(OUTPUT_FD,
2330Sstevel@tonic-gate 			    "%s|%s|%s|%s|%s|%s|%s\n",
2340Sstevel@tonic-gate 			    bind->ref_lib,
2350Sstevel@tonic-gate 			    bind->section,
2360Sstevel@tonic-gate 			    bind->stbind,
2370Sstevel@tonic-gate 			    bind->sttype,
2380Sstevel@tonic-gate 			    bind->sym,
2390Sstevel@tonic-gate 			    bind->def_lib,
2400Sstevel@tonic-gate 			    bind->obj);
2410Sstevel@tonic-gate 	} else if (bind->sym && bind->stbind)
2420Sstevel@tonic-gate 		(void) fprintf(OUTPUT_FD,
2430Sstevel@tonic-gate 		    "%s|%s|%s|%s|%s\n",
2440Sstevel@tonic-gate 		    bind->obj,
2450Sstevel@tonic-gate 		    bind->section,
2460Sstevel@tonic-gate 		    bind->stbind,
2470Sstevel@tonic-gate 		    bind->sttype,
2480Sstevel@tonic-gate 		    bind->sym);
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate /* ========== output_binding ============================================== */
2520Sstevel@tonic-gate /*
2530Sstevel@tonic-gate  * DESCRIPTION:
2540Sstevel@tonic-gate  * Output the hash table to either stdout or a file.
2550Sstevel@tonic-gate  */
2560Sstevel@tonic-gate /* ======================================================================== */
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate static void
output_binding(char * prog_name,char * target)2590Sstevel@tonic-gate output_binding(char *prog_name,
2600Sstevel@tonic-gate     char *target)
2610Sstevel@tonic-gate {
2620Sstevel@tonic-gate 	int		i;
2630Sstevel@tonic-gate 	char		*ref_lib_ptr;
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	qsort(bkts,
2660Sstevel@tonic-gate 	    DEFBKTS,
2670Sstevel@tonic-gate 	    sizeof (binding_bucket),
2680Sstevel@tonic-gate 	    (int (*) (const void *, const void *)) stringcompare);
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 	if (oflag) {
2710Sstevel@tonic-gate 		if ((OUTPUT_FD = fopen(outputfile, "w")) == NULL) {
2720Sstevel@tonic-gate 			if (sflag)
2730Sstevel@tonic-gate 				(void) fprintf(stderr,
2740Sstevel@tonic-gate 				    "\nfopen failed to open <%s>...\n\n",
2750Sstevel@tonic-gate 				    outputfile);
2760Sstevel@tonic-gate 			exit(1);
2770Sstevel@tonic-gate 		}
2780Sstevel@tonic-gate 	}
2790Sstevel@tonic-gate 	/* generates profile report */
2800Sstevel@tonic-gate 	(void) fprintf(OUTPUT_FD,
2810Sstevel@tonic-gate 	    "#generated by %s\n",
2820Sstevel@tonic-gate 	    prog_name);
2830Sstevel@tonic-gate 	(void) fprintf(OUTPUT_FD,
2840Sstevel@tonic-gate 	    "#profiling symbols in .text section of %s\n",
2850Sstevel@tonic-gate 	    target);
2860Sstevel@tonic-gate 	output_dtneeded(dt_needed);
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate 	for (i = 0; i < DEFBKTS; i++) {
2890Sstevel@tonic-gate 		if (bkts[i].sym && strcmp(bkts[i].ref_lib, "<Unknown>")) {
2900Sstevel@tonic-gate 			if (ref_lib_ptr = strrchr(bkts[i].ref_lib, (int)'/')) {
2910Sstevel@tonic-gate 				ref_lib_ptr++;
2920Sstevel@tonic-gate 				if (bkts[i].stbind)
2930Sstevel@tonic-gate 					(void) fprintf(OUTPUT_FD,
2940Sstevel@tonic-gate 					    "%s|%s|%s|%s|%s|%s|%s\n",
2950Sstevel@tonic-gate 					    ref_lib_ptr,
2960Sstevel@tonic-gate 					    bkts[i].section,
2970Sstevel@tonic-gate 					    bkts[i].stbind,
2980Sstevel@tonic-gate 					    bkts[i].sttype,
2990Sstevel@tonic-gate 					    bkts[i].sym,
3000Sstevel@tonic-gate 					    bkts[i].def_lib,
3010Sstevel@tonic-gate 					    bkts[i].obj);
3020Sstevel@tonic-gate 			} else if (bkts[i].stbind)
3030Sstevel@tonic-gate 				(void) fprintf(OUTPUT_FD,
3040Sstevel@tonic-gate 				    "%s|%s|%s|%s|%s|%s|%s\n",
3050Sstevel@tonic-gate 				    bkts[i].ref_lib,
3060Sstevel@tonic-gate 				    bkts[i].section,
3070Sstevel@tonic-gate 				    bkts[i].stbind,
3080Sstevel@tonic-gate 				    bkts[i].sttype,
3090Sstevel@tonic-gate 				    bkts[i].sym,
3100Sstevel@tonic-gate 				    bkts[i].def_lib,
3110Sstevel@tonic-gate 				    bkts[i].obj);
3120Sstevel@tonic-gate 		} else if (bkts[i].sym && bkts[i].stbind)
3130Sstevel@tonic-gate 			(void) fprintf(OUTPUT_FD,
3140Sstevel@tonic-gate 			    "%s|%s|%s|%s|%s\n",
3150Sstevel@tonic-gate 			    bkts[i].obj,
3160Sstevel@tonic-gate 			    bkts[i].section,
3170Sstevel@tonic-gate 			    bkts[i].stbind,
3180Sstevel@tonic-gate 			    bkts[i].sttype,
3190Sstevel@tonic-gate 			    bkts[i].sym);
3200Sstevel@tonic-gate 	}
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate /* ========== obj_init ==================================================== */
3240Sstevel@tonic-gate /*
3250Sstevel@tonic-gate  * DESCRIPTION:
3260Sstevel@tonic-gate  * Open (object) file, get ELF descriptor, and verify that the file is
3270Sstevel@tonic-gate  * an ELF file.
3280Sstevel@tonic-gate  */
3290Sstevel@tonic-gate /* ======================================================================== */
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate static int
obj_init(obj_list * c)3320Sstevel@tonic-gate obj_init(obj_list * c)
3330Sstevel@tonic-gate {
3340Sstevel@tonic-gate 	int		mode = O_RDONLY;
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	/* open the file */
3370Sstevel@tonic-gate 	if ((c->obj->fd = open(c->obj->ename, mode)) < 0) {
3380Sstevel@tonic-gate 		if (sflag) {
3390Sstevel@tonic-gate 			if (errno == ENOENT)
3400Sstevel@tonic-gate 				(void) fprintf(stderr,
3410Sstevel@tonic-gate 				    "Cannot open <<%s>> : \
3420Sstevel@tonic-gate 				    No such file or directory.\n",
3430Sstevel@tonic-gate 				    c->obj->ename);
3440Sstevel@tonic-gate 			else if (errno == EMFILE)
3450Sstevel@tonic-gate 				(void) fprintf(stderr,
3460Sstevel@tonic-gate 				    "File <<%s>> : Already opened.\n",
3470Sstevel@tonic-gate 				    c->obj->ename);
3480Sstevel@tonic-gate 		}
3490Sstevel@tonic-gate 		c->obj->fd = NULL;
3500Sstevel@tonic-gate 		return (FAIL);
3510Sstevel@tonic-gate 	}
3520Sstevel@tonic-gate 	/*
3530Sstevel@tonic-gate 	 * queries the ELF library's internal version.
3540Sstevel@tonic-gate 	 * Passing ver equal to EV_NONE causes elf_version() to return
3550Sstevel@tonic-gate 	 * the library's internal version, without altering the working
3560Sstevel@tonic-gate 	 * version.  If ver is a version known to the library,
3570Sstevel@tonic-gate 	 * elf_version() returns the previous or initial working
3580Sstevel@tonic-gate 	 * version number.  Otherwise, the working version remains
3590Sstevel@tonic-gate 	 * unchanged and elf_version() returns EV_NONE.
3600Sstevel@tonic-gate 	 */
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	/* check if libelf.so is at the right level */
3630Sstevel@tonic-gate 	if (elf_version(EV_CURRENT) == EV_NONE) {
3640Sstevel@tonic-gate 		if (sflag)
3650Sstevel@tonic-gate 			(void) fprintf(stderr,
3660Sstevel@tonic-gate 			    "Library out of date in ELF access routines.\n");
3670Sstevel@tonic-gate 		return (FAIL);
3680Sstevel@tonic-gate 	}
3690Sstevel@tonic-gate 	/*
3700Sstevel@tonic-gate 	 * Before the first call to elf_begin(), it must call
3710Sstevel@tonic-gate 	 * elf_version() to coordinate versions.
3720Sstevel@tonic-gate 	 */
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 	/*
3750Sstevel@tonic-gate 	 * get elf descriptor just to examine the contents of an existing
3760Sstevel@tonic-gate 	 * file
3770Sstevel@tonic-gate 	 */
3780Sstevel@tonic-gate 	if ((c->obj->elf = elf_begin(c->obj->fd, ELF_C_READ, (Elf *) 0))
3790Sstevel@tonic-gate 	    == (Elf *) 0) {
3800Sstevel@tonic-gate 		if (sflag)
3810Sstevel@tonic-gate 			(void) fprintf(stderr,
3820Sstevel@tonic-gate 			    "File is not in executable and \
3830Sstevel@tonic-gate 			    linking format(ELF).\n");
3840Sstevel@tonic-gate 		return (FAIL);
3850Sstevel@tonic-gate 	}
3860Sstevel@tonic-gate 	/* Rule out COFF, a.out and shell script files */
3870Sstevel@tonic-gate 	if (elf_kind(c->obj->elf) == ELF_K_COFF) {
3880Sstevel@tonic-gate 		if (sflag) {
3890Sstevel@tonic-gate 			(void) fprintf(stderr,
3900Sstevel@tonic-gate 			    "File is not in executable \
3910Sstevel@tonic-gate 			    and linking format(ELF) or archive.\n");
3920Sstevel@tonic-gate 		}
3930Sstevel@tonic-gate 		return (FAIL);
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate 	if (elf_kind(c->obj->elf) != ELF_K_AR &&
3960Sstevel@tonic-gate 	    elf_kind(c->obj->elf) != ELF_K_ELF) {
3970Sstevel@tonic-gate 		if (sflag) {
3980Sstevel@tonic-gate 			(void) fprintf(stderr,
3990Sstevel@tonic-gate 			    "File is not in executable and linking \
4000Sstevel@tonic-gate 			    format(ELF) or archive.\n");
4010Sstevel@tonic-gate 		}
4020Sstevel@tonic-gate 		return (FAIL);
4030Sstevel@tonic-gate 	}
4040Sstevel@tonic-gate 	return (SUCCEED);
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate /* ========== obj_elf_hdr ================================================= */
4080Sstevel@tonic-gate /*
4090Sstevel@tonic-gate  * DESCRIPTION:
4100Sstevel@tonic-gate  * Obtain the elf header, verify elf header information
4110Sstevel@tonic-gate  */
4120Sstevel@tonic-gate /* ======================================================================== */
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate static int
obj_elf_hdr(obj_list * c)4150Sstevel@tonic-gate obj_elf_hdr(obj_list * c)
4160Sstevel@tonic-gate {
4170Sstevel@tonic-gate #if	defined(_LP64)
4180Sstevel@tonic-gate 	Elf64_Ehdr	*ptr;
4190Sstevel@tonic-gate #else
4200Sstevel@tonic-gate 	Elf32_Ehdr	*ptr;
4210Sstevel@tonic-gate #endif
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	/*
4240Sstevel@tonic-gate 	 * get the elf header if one is available for the ELF descriptor
4250Sstevel@tonic-gate 	 * c->elf
4260Sstevel@tonic-gate 	 */
4270Sstevel@tonic-gate #if	defined(_LP64)
4280Sstevel@tonic-gate 	if ((ptr = elf64_getehdr(c->obj->elf)) == (Elf64_Ehdr *) 0) {
4290Sstevel@tonic-gate 		if (sflag)
4300Sstevel@tonic-gate 			(void) fprintf(stderr,
4310Sstevel@tonic-gate 			    "File is not in 64-bit format.\n");
4320Sstevel@tonic-gate 		return (FAIL);
4330Sstevel@tonic-gate 	}
4340Sstevel@tonic-gate #else
4350Sstevel@tonic-gate 	if ((ptr = elf32_getehdr(c->obj->elf)) == (Elf32_Ehdr *) 0) {
4360Sstevel@tonic-gate 		if (sflag)
4370Sstevel@tonic-gate 			(void) fprintf(stderr,
4380Sstevel@tonic-gate 			    "File is not in 32-bit format.\n");
4390Sstevel@tonic-gate 		return (FAIL);
4400Sstevel@tonic-gate 	}
4410Sstevel@tonic-gate #endif
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 	/* if there is elf header, save the pointer */
4440Sstevel@tonic-gate #if defined(_LP64)
4450Sstevel@tonic-gate 	c->obj->ehdr = (Elf64_Ehdr *) ptr;
4460Sstevel@tonic-gate #else
4470Sstevel@tonic-gate 	c->obj->ehdr = (Elf32_Ehdr *) ptr;
4480Sstevel@tonic-gate #endif
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	/* e_ident[] is identification index which holds values */
4510Sstevel@tonic-gate 	/*
4520Sstevel@tonic-gate 	 * we could also use elf_getident() to retrieve file identification
4530Sstevel@tonic-gate 	 * data.
4540Sstevel@tonic-gate 	 */
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	/*
4570Sstevel@tonic-gate 	 * e_ident[EI_CLASS] identifies the file's class:
4580Sstevel@tonic-gate 	 * ELFCLASSNONE - invalid class
4590Sstevel@tonic-gate 	 * ELFCLASS32   - 32-bit objects
4600Sstevel@tonic-gate 	 * ELFCLASS64   - 64-bit objects
4610Sstevel@tonic-gate 	 */
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate #if	defined(_LP64)
4640Sstevel@tonic-gate 	if (ptr->e_ident[EI_CLASS] != ELFCLASS64) {
4650Sstevel@tonic-gate 		if (sflag)
4660Sstevel@tonic-gate 			(void) fprintf(stderr,
4670Sstevel@tonic-gate 			    "File is not in 64-bit format.\n");
4680Sstevel@tonic-gate 		return (FAIL);
4690Sstevel@tonic-gate 	}
4700Sstevel@tonic-gate #else
4710Sstevel@tonic-gate 	if (ptr->e_ident[EI_CLASS] != ELFCLASS32) {
4720Sstevel@tonic-gate 		if (sflag)
4730Sstevel@tonic-gate 			(void) fprintf(stderr,
4740Sstevel@tonic-gate 			    "File is not in 32-bit format.\n");
4750Sstevel@tonic-gate 		return (FAIL);
4760Sstevel@tonic-gate 	}
4770Sstevel@tonic-gate #endif
4780Sstevel@tonic-gate 	/*
4790Sstevel@tonic-gate 	 * e_ident[EI_DATA] specifies the data encoding of the
4800Sstevel@tonic-gate 	 * processor-specific data in the object file:
4810Sstevel@tonic-gate 	 * ELFDATANONE - invalid data encoding
4820Sstevel@tonic-gate 	 * ELFDATA2LSB - specifies 2's complement values, with the least
4830Sstevel@tonic-gate 	 * significant byte occupying the lowest address
4840Sstevel@tonic-gate 	 * ELFDATA2MSB - specifies 2's complement values, with the most
4850Sstevel@tonic-gate 	 * significant byte occupying the lowest address
4860Sstevel@tonic-gate 	 */
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 	/*
4890Sstevel@tonic-gate 	 * e_ident[EI_VERSION] specifies the ELF header version number.
4900Sstevel@tonic-gate 	 * Currently, this value must be EV_CURRENT.
4910Sstevel@tonic-gate 	 */
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate 	if (!(ptr->e_ident[EI_VERSION] == EV_CURRENT) &&
4940Sstevel@tonic-gate 	    (ptr->e_version == EV_CURRENT)) {
4950Sstevel@tonic-gate 		if (sflag)
4960Sstevel@tonic-gate 			(void) fprintf(stderr,
4970Sstevel@tonic-gate 			    "File is recorded in an \
4980Sstevel@tonic-gate 			    incompatible ELF version.\n");
4990Sstevel@tonic-gate 		return (FAIL);
5000Sstevel@tonic-gate 	}
5010Sstevel@tonic-gate 	/* only interested in relocatable, shared object, or executable file */
5020Sstevel@tonic-gate 	switch (ptr->e_type) {
5030Sstevel@tonic-gate 	case ET_REL:
5040Sstevel@tonic-gate 	case ET_EXEC:
5050Sstevel@tonic-gate 	case ET_DYN:
5060Sstevel@tonic-gate 		break;
5070Sstevel@tonic-gate 	default:
5080Sstevel@tonic-gate 		if (sflag) {
5090Sstevel@tonic-gate 			(void) fprintf(stderr,
5100Sstevel@tonic-gate 			    "File is not relocatable, ");
5110Sstevel@tonic-gate 			(void) fprintf(stderr,
5120Sstevel@tonic-gate 			    "executable, or shared object.\n");
5130Sstevel@tonic-gate 		}
5140Sstevel@tonic-gate 		return (FAIL);
5150Sstevel@tonic-gate 	}
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	/*
5180Sstevel@tonic-gate 	 * e_machine's value specifies the required architecture for an
5190Sstevel@tonic-gate 	 * individual file
5200Sstevel@tonic-gate 	 */
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate #if defined(__sparcv9)
5230Sstevel@tonic-gate 	if (ptr->e_machine != EM_SPARCV9) {
5240Sstevel@tonic-gate 		if (sflag)
5250Sstevel@tonic-gate 			(void) fprintf(stderr,
5260Sstevel@tonic-gate 			    "File is not for 64-bit \
5270Sstevel@tonic-gate 			    SPARC machine architecture.\n");
5280Sstevel@tonic-gate 		return (FAIL);
5290Sstevel@tonic-gate 	}
5300Sstevel@tonic-gate #elif defined(__amd64)
5310Sstevel@tonic-gate 	if (ptr->e_machine != EM_AMD64) {
5320Sstevel@tonic-gate 		if (sflag)
5330Sstevel@tonic-gate 			(void) fprintf(stderr,
5340Sstevel@tonic-gate 			    "File is not for 64-bit \
5350Sstevel@tonic-gate 			    amd64 machine architecture.\n");
5360Sstevel@tonic-gate 		return (FAIL);
5370Sstevel@tonic-gate 	}
5380Sstevel@tonic-gate #elif defined(__i386)
5390Sstevel@tonic-gate 	if (ptr->e_machine != EM_386) {
5400Sstevel@tonic-gate 		if (sflag)
5410Sstevel@tonic-gate 			(void) fprintf(stderr,
5420Sstevel@tonic-gate 			    "File is not for 32-bit \
5430Sstevel@tonic-gate 			    i386 machine architecture.\n");
5440Sstevel@tonic-gate 		return (FAIL);
5450Sstevel@tonic-gate 	}
5460Sstevel@tonic-gate #else
5470Sstevel@tonic-gate 	if (ptr->e_machine != EM_SPARC) {
5480Sstevel@tonic-gate 		if (sflag)
5490Sstevel@tonic-gate 			(void) fprintf(stderr,
5500Sstevel@tonic-gate 			    "File is not for 32-bit \
5510Sstevel@tonic-gate 			    SPARC machine architecture.\n");
5520Sstevel@tonic-gate 		return (FAIL);
5530Sstevel@tonic-gate 	}
5540Sstevel@tonic-gate #endif
5550Sstevel@tonic-gate 	return (SUCCEED);
5560Sstevel@tonic-gate }
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate /* ========== obj_prog_hdr ============================================= */
5590Sstevel@tonic-gate /*
5600Sstevel@tonic-gate  * DESCRIPTION:
5610Sstevel@tonic-gate  * For executable files and shared objects only, check if it has
5620Sstevel@tonic-gate  * a program header table.
5630Sstevel@tonic-gate  */
5640Sstevel@tonic-gate /* ===================================================================== */
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate static int
obj_prog_hdr(obj_list * c)5670Sstevel@tonic-gate obj_prog_hdr(obj_list * c)
5680Sstevel@tonic-gate {
5690Sstevel@tonic-gate 	/*
5700Sstevel@tonic-gate 	 * Assume:  the elf header has already been read, and the file
5710Sstevel@tonic-gate 	 * has already been determined to be
5720Sstevel@tonic-gate 	 * executable, shared object, or relocatable
5730Sstevel@tonic-gate 	 */
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	/*
5760Sstevel@tonic-gate 	 * Program headers are meaningful only for executable and shared
5770Sstevel@tonic-gate 	 * object files.  It is an array of structures, each describing a
5780Sstevel@tonic-gate 	 * segment or other information needs to prepare the program for
5790Sstevel@tonic-gate 	 * execution.
5800Sstevel@tonic-gate 	 */
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	/* skip if file is not executable or shared object */
5830Sstevel@tonic-gate 	/* e_type == ET_REL meaning Relocatable file */
5840Sstevel@tonic-gate 	if (c->obj->ehdr->e_type == ET_REL)
5850Sstevel@tonic-gate 		return (SUCCEED);
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 	/*
5880Sstevel@tonic-gate 	 * ehdr->e_phoff holds the program header table's file offset in
5890Sstevel@tonic-gate 	 * bytes.
5900Sstevel@tonic-gate 	 */
5910Sstevel@tonic-gate 	/* If the file has no program header table, this member holds zero. */
5920Sstevel@tonic-gate 	/*
5930Sstevel@tonic-gate 	 * ehdr->e_phnum holds the number of entries in the program header
5940Sstevel@tonic-gate 	 * table.
5950Sstevel@tonic-gate 	 */
5960Sstevel@tonic-gate 	/*
5970Sstevel@tonic-gate 	 * If a file has no program header table, e_phnum holds the value
5980Sstevel@tonic-gate 	 * zero.
5990Sstevel@tonic-gate 	 */
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate 	/* make sure there's a program header table */
6020Sstevel@tonic-gate 	if ((c->obj->ehdr->e_phoff == 0) ||
6030Sstevel@tonic-gate 	    (c->obj->ehdr->e_phnum == 0)) {
6040Sstevel@tonic-gate 		if (sflag)
6050Sstevel@tonic-gate 			(void) fprintf(stderr,
6060Sstevel@tonic-gate 			    "File has no program header table.\n");
6070Sstevel@tonic-gate 		return (FAIL);
6080Sstevel@tonic-gate 	}
6090Sstevel@tonic-gate 	return (SUCCEED);
6100Sstevel@tonic-gate }
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate /* ========== find_dynamic_sect ========================================== */
6130Sstevel@tonic-gate /*
6140Sstevel@tonic-gate  * DESCRIPTION:
6150Sstevel@tonic-gate  * Find the dynamic section.
6160Sstevel@tonic-gate  */
6170Sstevel@tonic-gate /* ======================================================================= */
6180Sstevel@tonic-gate 
6190Sstevel@tonic-gate static int
find_dynamic_sect(obj_list * c)6200Sstevel@tonic-gate find_dynamic_sect(obj_list * c)
6210Sstevel@tonic-gate {
6220Sstevel@tonic-gate #if	defined(_LP64)
6230Sstevel@tonic-gate 	Elf64_Shdr	*scurrent;	/* temp 64 bit section pointer */
6240Sstevel@tonic-gate #else
6250Sstevel@tonic-gate 	Elf32_Shdr	*scurrent;	/* temp 32 bit section pointer */
6260Sstevel@tonic-gate #endif
6270Sstevel@tonic-gate 	Elf_Scn		*scn;	/* temp section header pointer */
6280Sstevel@tonic-gate 	Elf_Data	*ddata;	/* temp data header pointer */
6290Sstevel@tonic-gate 	size_t		index;	/* temp section header table index */
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	c->obj->dynnames = NULL; /* init of dynamic string table ptr */
6320Sstevel@tonic-gate 	c->obj->dynsect = NULL;	/* init of dynamic section ptr */
6330Sstevel@tonic-gate 	c->obj->ddata = NULL;	/* init of dynamic strtab data ptr */
6340Sstevel@tonic-gate 
6350Sstevel@tonic-gate 	/* only process executables and shared objects */
6360Sstevel@tonic-gate 	if (c->obj->ehdr->e_type != ET_EXEC && c->obj->ehdr->e_type != ET_DYN)
6370Sstevel@tonic-gate 		return (SUCCEED);
6380Sstevel@tonic-gate 
6390Sstevel@tonic-gate 	if ((c->obj->ehdr->e_shoff == 0) || (c->obj->ehdr->e_shnum == 0)) {
6400Sstevel@tonic-gate 		/* there are no sections */
6410Sstevel@tonic-gate 		return (SUCCEED);
6420Sstevel@tonic-gate 	}
6430Sstevel@tonic-gate 	/* search the section header table for dynamic section */
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 	/* start with null section; section index = 0 */
6460Sstevel@tonic-gate 	scn = 0;
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate 	while ((scn = elf_nextscn(c->obj->elf, scn)) != 0) {
6490Sstevel@tonic-gate 		/* retrieve the section header */
6500Sstevel@tonic-gate #if	defined(_LP64)
6510Sstevel@tonic-gate 		scurrent = elf64_getshdr(scn);
6520Sstevel@tonic-gate #else
6530Sstevel@tonic-gate 		scurrent = elf32_getshdr(scn);
6540Sstevel@tonic-gate #endif
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 		/* check for dynamic section; (i.e., .dynamic) */
6570Sstevel@tonic-gate 		if (scurrent->sh_type == SHT_DYNAMIC) {
6580Sstevel@tonic-gate 			ddata = 0;
6590Sstevel@tonic-gate 			if ((ddata = elf_getdata(scn, ddata)) == 0 ||
6600Sstevel@tonic-gate 			    (ddata->d_size == 0))
6610Sstevel@tonic-gate 				return (SUCCEED);
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 			/* now, we got data of dynamic section */
6640Sstevel@tonic-gate 			c->obj->dynsect = ddata->d_buf;
6650Sstevel@tonic-gate 
6660Sstevel@tonic-gate 			/* index to section header for dynamic string table */
6670Sstevel@tonic-gate 			index = scurrent->sh_link;
6680Sstevel@tonic-gate 			/* get scn descriptor of dynamic string table */
6690Sstevel@tonic-gate 			scn = elf_getscn(c->obj->elf, index);
6700Sstevel@tonic-gate 			/* get dynamic string table section header */
6710Sstevel@tonic-gate #if	defined(_LP64)
6720Sstevel@tonic-gate 			scurrent = elf64_getshdr(scn);
6730Sstevel@tonic-gate #else
6740Sstevel@tonic-gate 			scurrent = elf32_getshdr(scn);
6750Sstevel@tonic-gate #endif
6760Sstevel@tonic-gate 			/* get the dynamic string table data descriptor */
6770Sstevel@tonic-gate 			c->obj->ddata = elf_getdata(scn, (c->obj->ddata));
6780Sstevel@tonic-gate 			/* save the pointer to dynamic string table data */
6790Sstevel@tonic-gate 			c->obj->dynnames = c->obj->ddata->d_buf;
6800Sstevel@tonic-gate 			/*
6810Sstevel@tonic-gate 			 * now, we got dynamic strtab and dynamic section
6820Sstevel@tonic-gate 			 * information
6830Sstevel@tonic-gate 			 */
6840Sstevel@tonic-gate 			break;
6850Sstevel@tonic-gate 		}
6860Sstevel@tonic-gate 	}
6870Sstevel@tonic-gate 	return (SUCCEED);
6880Sstevel@tonic-gate }
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate /* ========== find_symtabs ================================================ */
6910Sstevel@tonic-gate /*
6920Sstevel@tonic-gate  * DESCRIPTION:
6930Sstevel@tonic-gate  * Find and check symbol tables for an application file
6940Sstevel@tonic-gate  */
6950Sstevel@tonic-gate /* ======================================================================== */
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate static int
find_symtabs(obj_list * c)6980Sstevel@tonic-gate find_symtabs(obj_list * c)
6990Sstevel@tonic-gate {
7000Sstevel@tonic-gate #if	defined(_LP64)
7010Sstevel@tonic-gate 	Elf64_Shdr	*shdr;
7020Sstevel@tonic-gate #else
7030Sstevel@tonic-gate 	Elf32_Shdr	*shdr;
7040Sstevel@tonic-gate #endif
7050Sstevel@tonic-gate 	Elf_Scn		*scn, *scn2;
7060Sstevel@tonic-gate 	Elf_Data	*data;
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 	c->obj->sym_tab = NULL;
7090Sstevel@tonic-gate 	c->obj->sym_num = 0;
7100Sstevel@tonic-gate 	c->obj->sym_names = NULL;
7110Sstevel@tonic-gate 	c->obj->dsym_tab = NULL;
7120Sstevel@tonic-gate 	c->obj->dsym_num = 0;
7130Sstevel@tonic-gate 	c->obj->dsym_names = NULL;
7140Sstevel@tonic-gate 	c->obj->sym_data = NULL;
7150Sstevel@tonic-gate 	c->obj->dsym_data = NULL;
7160Sstevel@tonic-gate 	scn = 0;
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate 	/*
7190Sstevel@tonic-gate 	 * loop through the section header table looking for symbol tables.
7200Sstevel@tonic-gate 	 * There must be one or two:  .symtab and .dynsym
7210Sstevel@tonic-gate 	 * upon finding a symbol table, save its pointer in obj_com.
7220Sstevel@tonic-gate 	 */
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 	/* get section descriptor */
7250Sstevel@tonic-gate 	while ((scn = elf_nextscn(c->obj->elf, scn)) != 0) {
7260Sstevel@tonic-gate #if	defined(_LP64)
7270Sstevel@tonic-gate 		Elf64_Sym	*syms;
7280Sstevel@tonic-gate #else
7290Sstevel@tonic-gate 		Elf32_Sym	*syms;
7300Sstevel@tonic-gate #endif
7310Sstevel@tonic-gate 		int		symn;
7320Sstevel@tonic-gate 		char		*strs;
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 		/* point to section header */
7350Sstevel@tonic-gate #if	defined(_LP64)
7360Sstevel@tonic-gate 		shdr = elf64_getshdr(scn);
7370Sstevel@tonic-gate #else
7380Sstevel@tonic-gate 		shdr = elf32_getshdr(scn);
7390Sstevel@tonic-gate #endif
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 		if (shdr == 0)
7420Sstevel@tonic-gate 			return (FAIL);
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 		/* skip if this section is not a symbol table */
7450Sstevel@tonic-gate 		if ((shdr->sh_type != SHT_DYNSYM) &&
7460Sstevel@tonic-gate 		    (shdr->sh_type != SHT_SYMTAB))
7470Sstevel@tonic-gate 			continue;
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate 		/* get data descriptor for the symbol table itself */
7500Sstevel@tonic-gate 		data = elf_getdata(scn, NULL);
7510Sstevel@tonic-gate 		if (data == NULL)
7520Sstevel@tonic-gate 			continue;
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 		/* save pointer to symbol table */
7550Sstevel@tonic-gate #if	defined(_LP64)
7560Sstevel@tonic-gate 		syms = (Elf64_Sym *) data->d_buf;
7570Sstevel@tonic-gate #else
7580Sstevel@tonic-gate 		syms = (Elf32_Sym *) data->d_buf;
7590Sstevel@tonic-gate #endif
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate 		/*
7620Sstevel@tonic-gate 		 * now start looking for the string table associated with
7630Sstevel@tonic-gate 		 * this symbol table section
7640Sstevel@tonic-gate 		 */
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 		/* get section descriptor first */
7670Sstevel@tonic-gate 		scn2 = elf_getscn(c->obj->elf, shdr->sh_link);
7680Sstevel@tonic-gate 		if (scn2 == NULL)
7690Sstevel@tonic-gate 			continue;
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate 		/* get data descriptor for the string table section */
7720Sstevel@tonic-gate 		data = elf_getdata(scn2, NULL);
7730Sstevel@tonic-gate 		if (data == NULL)
7740Sstevel@tonic-gate 			continue;
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 		/* save pointer to name string table */
7770Sstevel@tonic-gate 		strs = data->d_buf;
7780Sstevel@tonic-gate 		symn = shdr->sh_size / shdr->sh_entsize;
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 		/* save information in obj_com */
7810Sstevel@tonic-gate 		if (shdr->sh_type == SHT_SYMTAB) {
7820Sstevel@tonic-gate 			c->obj->sym_tab = syms;
7830Sstevel@tonic-gate 			c->obj->sym_num = symn;
7840Sstevel@tonic-gate 			c->obj->sym_names = strs;
7850Sstevel@tonic-gate 			c->obj->sym_data = data;
7860Sstevel@tonic-gate 		} else {	/* must be the dynamic linking symbol table */
7870Sstevel@tonic-gate 			c->obj->dsym_tab = syms;
7880Sstevel@tonic-gate 			c->obj->dsym_num = symn;
7890Sstevel@tonic-gate 			c->obj->dsym_names = strs;
7900Sstevel@tonic-gate 			c->obj->dsym_data = data;
7910Sstevel@tonic-gate 		}		/* end if */
7920Sstevel@tonic-gate 	}			/* end while */
7930Sstevel@tonic-gate 	return (SUCCEED);
7940Sstevel@tonic-gate }
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate /* ========== obj_app_symtab ============================================== */
7970Sstevel@tonic-gate /*
7980Sstevel@tonic-gate  * DESCRIPTION:
7990Sstevel@tonic-gate  * Check existence of application's symbol tables.
8000Sstevel@tonic-gate  */
8010Sstevel@tonic-gate /* ======================================================================== */
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate static int
obj_app_symtab(obj_list * c)8040Sstevel@tonic-gate obj_app_symtab(obj_list * c)
8050Sstevel@tonic-gate {
8060Sstevel@tonic-gate 	/* issue error if a relocatable file has no symbol table */
8070Sstevel@tonic-gate 	if (c->obj->sym_tab == NULL) {
8080Sstevel@tonic-gate 		if (c->obj->ehdr->e_type == ET_REL) {
8090Sstevel@tonic-gate 			if (sflag)
8100Sstevel@tonic-gate 				(void) fprintf(stderr,
8110Sstevel@tonic-gate 				    "ELF error: no symbol \
8120Sstevel@tonic-gate 				    table in object file.\n");
8130Sstevel@tonic-gate 			return (FAIL);
8140Sstevel@tonic-gate 		} else {
8150Sstevel@tonic-gate 			if (c->obj->dsym_tab == NULL) {
8160Sstevel@tonic-gate 				if (sflag) {
8170Sstevel@tonic-gate 					(void) fprintf(stderr,
8180Sstevel@tonic-gate 					    "Warning: Binary is \
8190Sstevel@tonic-gate 					    completely statically \
8200Sstevel@tonic-gate 					    linked and stripped.\n");
8210Sstevel@tonic-gate 				}
8220Sstevel@tonic-gate 				return (FAIL);
8230Sstevel@tonic-gate 			}
8240Sstevel@tonic-gate 			if (sflag)
8250Sstevel@tonic-gate 				(void) fprintf(stderr,
8260Sstevel@tonic-gate 				    "Binary is stripped.\n");
8270Sstevel@tonic-gate 		}
8280Sstevel@tonic-gate 	}
8290Sstevel@tonic-gate 	return (SUCCEED);
8300Sstevel@tonic-gate }
8310Sstevel@tonic-gate 
8320Sstevel@tonic-gate /* ========== obj_finis =================================================== */
8330Sstevel@tonic-gate /*
8340Sstevel@tonic-gate  * DESCRIPTION:
8350Sstevel@tonic-gate  * It checks the c->fd and c->elf pointers.  If they are not NULL,
8360Sstevel@tonic-gate  * close the file descriptor and ELF descriptor.
8370Sstevel@tonic-gate  */
8380Sstevel@tonic-gate /* ======================================================================== */
8390Sstevel@tonic-gate 
8400Sstevel@tonic-gate static void
obj_finis(obj_list * c)8410Sstevel@tonic-gate obj_finis(obj_list * c)
8420Sstevel@tonic-gate {
8430Sstevel@tonic-gate 	obj_list	*p;
8440Sstevel@tonic-gate 
8450Sstevel@tonic-gate 	if (c) {
8460Sstevel@tonic-gate 		while (c) {
8470Sstevel@tonic-gate 			if (c->obj->elf != (Elf *) 0)
8480Sstevel@tonic-gate 				(void) elf_end(c->obj->elf);
8490Sstevel@tonic-gate 			if (c->obj->fd != 0)
8500Sstevel@tonic-gate 				(void) close(c->obj->fd);
8510Sstevel@tonic-gate 			p = c;
8520Sstevel@tonic-gate 			c = c->next;
8530Sstevel@tonic-gate 			free(p->obj);
8540Sstevel@tonic-gate 			free(p);
8550Sstevel@tonic-gate 		}
8560Sstevel@tonic-gate 	}
8570Sstevel@tonic-gate }
8580Sstevel@tonic-gate 
8590Sstevel@tonic-gate /* ========= is_text_section ============================================== */
8600Sstevel@tonic-gate /*
8610Sstevel@tonic-gate  * DESCRIPTION:
8620Sstevel@tonic-gate  * Scan through every section and returns TRUE(1) if the given section
8630Sstevel@tonic-gate  * is ".text", otherwise, returns FALSE(0).
8640Sstevel@tonic-gate  * INPUTS:        shndx - section header index
8650Sstevel@tonic-gate  * elf_file - ELF descriptor of the object file under test
8660Sstevel@tonic-gate  * ehdr - ELF header of the object file under test
8670Sstevel@tonic-gate  */
8680Sstevel@tonic-gate /* ======================================================================== */
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate static int
is_text_section(int shndx,Elf * elf_file,Elf64_Ehdr * ehdr)8710Sstevel@tonic-gate is_text_section(int shndx,
8720Sstevel@tonic-gate     Elf * elf_file,
8730Sstevel@tonic-gate #if	defined(_LP64)
8740Sstevel@tonic-gate     Elf64_Ehdr * ehdr)
8750Sstevel@tonic-gate #else
8760Sstevel@tonic-gate     Elf32_Ehdr * ehdr)
8770Sstevel@tonic-gate #endif
8780Sstevel@tonic-gate {
8790Sstevel@tonic-gate 	char		*sym_name;
8800Sstevel@tonic-gate 	Elf_Scn		*scn = elf_getscn(elf_file, shndx);
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate 	if (scn != NULL) {
8830Sstevel@tonic-gate #if	defined(_LP64)
8840Sstevel@tonic-gate 		Elf64_Shdr	*shdr;
8850Sstevel@tonic-gate 		shdr = elf64_getshdr(scn);
8860Sstevel@tonic-gate #else
8870Sstevel@tonic-gate 		Elf32_Shdr	*shdr;
8880Sstevel@tonic-gate 		shdr = elf32_getshdr(scn);
8890Sstevel@tonic-gate #endif
8900Sstevel@tonic-gate 		sym_name = elf_strptr(elf_file,
8910Sstevel@tonic-gate 				    ehdr->e_shstrndx,
8920Sstevel@tonic-gate 				    shdr->sh_name);
8930Sstevel@tonic-gate 		if (strcmp(sym_name, ".text") == 0)
8940Sstevel@tonic-gate 			return (1);
8950Sstevel@tonic-gate 	}
8960Sstevel@tonic-gate 	return (0);
8970Sstevel@tonic-gate }
8980Sstevel@tonic-gate 
8990Sstevel@tonic-gate /* ========== scan_archive_symbols ======================================= */
9000Sstevel@tonic-gate /*
9010Sstevel@tonic-gate  * DESCRIPTION:
9020Sstevel@tonic-gate  * Scan through the archive symbol tables and write them out.
9030Sstevel@tonic-gate  * INPUTS:        syms - pointer to application symbol table
9040Sstevel@tonic-gate  * symn - number of entries in application symbol table
9050Sstevel@tonic-gate  * buf  - first byte of application string table
9060Sstevel@tonic-gate  */
9070Sstevel@tonic-gate /* ======================================================================= */
9080Sstevel@tonic-gate 
9090Sstevel@tonic-gate static void
scan_archive_symbols(obj_list * c,Elf64_Sym * syms,int symn,char * buf,Elf * elf_file,Elf64_Ehdr * ehdr)9100Sstevel@tonic-gate scan_archive_symbols(obj_list * c,
9110Sstevel@tonic-gate #if	defined(_LP64)
9120Sstevel@tonic-gate     Elf64_Sym * syms,
9130Sstevel@tonic-gate #else
9140Sstevel@tonic-gate     Elf32_Sym * syms,
9150Sstevel@tonic-gate #endif
9160Sstevel@tonic-gate     int symn,
9170Sstevel@tonic-gate     char *buf,
9180Sstevel@tonic-gate     Elf * elf_file,
9190Sstevel@tonic-gate #if	defined(_LP64)
9200Sstevel@tonic-gate     Elf64_Ehdr * ehdr)
9210Sstevel@tonic-gate #else
9220Sstevel@tonic-gate     Elf32_Ehdr * ehdr)
9230Sstevel@tonic-gate #endif
9240Sstevel@tonic-gate {
9250Sstevel@tonic-gate #if	defined(_LP64)
9260Sstevel@tonic-gate 	Elf64_Sym	*symtab_entry;
9270Sstevel@tonic-gate #else
9280Sstevel@tonic-gate 	Elf32_Sym	*symtab_entry;
9290Sstevel@tonic-gate #endif
9300Sstevel@tonic-gate 	int		i;
9310Sstevel@tonic-gate 	char		*sym_name;
9320Sstevel@tonic-gate 	int		sttype;
9330Sstevel@tonic-gate 	int		stbind;
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	symtab_entry = syms;
9360Sstevel@tonic-gate 	for (i = 0; i < symn; i++, symtab_entry++) {
9370Sstevel@tonic-gate 		binding_bucket *binding;
9380Sstevel@tonic-gate 		/* look only at .text section symbols */
9390Sstevel@tonic-gate 		if (!is_text_section(symtab_entry->st_shndx, elf_file, ehdr))
9400Sstevel@tonic-gate 			continue;
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate 		/* look only at weak and global symbols */
9430Sstevel@tonic-gate #if	defined(_LP64)
9440Sstevel@tonic-gate 		stbind = ELF64_ST_BIND(symtab_entry->st_info);
9450Sstevel@tonic-gate #else
9460Sstevel@tonic-gate 		stbind = ELF32_ST_BIND(symtab_entry->st_info);
9470Sstevel@tonic-gate #endif
9480Sstevel@tonic-gate 		if (stbind != STB_GLOBAL) {
9490Sstevel@tonic-gate 			if (stbind != STB_WEAK)
9500Sstevel@tonic-gate 				continue;
9510Sstevel@tonic-gate 		}
9520Sstevel@tonic-gate 		/* look only at functions and objects */
9530Sstevel@tonic-gate #if	defined(_LP64)
9540Sstevel@tonic-gate 		sttype = ELF64_ST_TYPE(symtab_entry->st_info);
9550Sstevel@tonic-gate #else
9560Sstevel@tonic-gate 		sttype = ELF32_ST_TYPE(symtab_entry->st_info);
9570Sstevel@tonic-gate #endif
9580Sstevel@tonic-gate 		if (sttype != STT_FUNC) {
9590Sstevel@tonic-gate 			if (sttype != STT_OBJECT)
9600Sstevel@tonic-gate 				continue;
9610Sstevel@tonic-gate 		}
9620Sstevel@tonic-gate 		sym_name = buf + symtab_entry->st_name;
9630Sstevel@tonic-gate 		binding = (struct binding_bucket *)
9640Sstevel@tonic-gate 			    malloc(sizeof (binding_bucket));
9650Sstevel@tonic-gate 		binding->sym = sym_name;
9660Sstevel@tonic-gate 		binding->obj = c->obj->ename;
9670Sstevel@tonic-gate 		binding->section = "TEXT";
9680Sstevel@tonic-gate 		binding->ref_lib = "<Unknown>";
9690Sstevel@tonic-gate 		binding->def_lib = "*DIRECT*";
9700Sstevel@tonic-gate 		if (stbind == STB_GLOBAL)
9710Sstevel@tonic-gate 			binding->stbind = "GLOB";
9720Sstevel@tonic-gate 		else if (stbind == STB_WEAK)
9730Sstevel@tonic-gate 			binding->stbind = "WEAK";
9740Sstevel@tonic-gate 		if (sttype == STT_FUNC)
9750Sstevel@tonic-gate 			binding->sttype = "FUNC";
9760Sstevel@tonic-gate 		else if (sttype == STT_OBJECT)
9770Sstevel@tonic-gate 			binding->sttype = "OBJT";
9780Sstevel@tonic-gate 		if (pflag)
9790Sstevel@tonic-gate 			profile_binding(binding);
9800Sstevel@tonic-gate 		else
9810Sstevel@tonic-gate 			store_binding(binding);
9820Sstevel@tonic-gate 	}			/* end for */
9830Sstevel@tonic-gate }
9840Sstevel@tonic-gate 
9850Sstevel@tonic-gate /* ========== scan_symbols ================================================ */
9860Sstevel@tonic-gate /*
9870Sstevel@tonic-gate  * DESCRIPTION:
9880Sstevel@tonic-gate  * Scan through the symbol table and write them out.
9890Sstevel@tonic-gate  * INPUTS:        syms - pointer to application symbol table
9900Sstevel@tonic-gate  * symn - number of entries in application symbol table
9910Sstevel@tonic-gate  * buf  - first byte of application string table
9920Sstevel@tonic-gate  */
9930Sstevel@tonic-gate /* ======================================================================== */
9940Sstevel@tonic-gate 
9950Sstevel@tonic-gate static void
scan_symbols(obj_list * c,Elf64_Sym * syms,int symn,char * buf)9960Sstevel@tonic-gate scan_symbols(obj_list * c,
9970Sstevel@tonic-gate #if	defined(_LP64)
9980Sstevel@tonic-gate     Elf64_Sym * syms,
9990Sstevel@tonic-gate #else
10000Sstevel@tonic-gate     Elf32_Sym * syms,
10010Sstevel@tonic-gate #endif
10020Sstevel@tonic-gate     int symn,
10030Sstevel@tonic-gate     char *buf)
10040Sstevel@tonic-gate {
10050Sstevel@tonic-gate #if	defined(_LP64)
10060Sstevel@tonic-gate 	Elf64_Sym	*symtab_entry;
10070Sstevel@tonic-gate #else
10080Sstevel@tonic-gate 	Elf32_Sym	*symtab_entry;
10090Sstevel@tonic-gate #endif
10100Sstevel@tonic-gate 	int		i;
10110Sstevel@tonic-gate 	char		*sym_name;
10120Sstevel@tonic-gate 	int		sttype;
10130Sstevel@tonic-gate 	int		stbind;
10140Sstevel@tonic-gate 
10150Sstevel@tonic-gate 	symtab_entry = syms;
10160Sstevel@tonic-gate 	if (pflag) {
10170Sstevel@tonic-gate 		(void) fprintf(OUTPUT_FD,
10180Sstevel@tonic-gate 		    "#profiling symbols in .text section of %s\n",
10190Sstevel@tonic-gate 		    c->obj->ename);
10200Sstevel@tonic-gate 		output_dtneeded(dt_needed);
10210Sstevel@tonic-gate 	}
10220Sstevel@tonic-gate 	for (i = 0; i < symn; i++, symtab_entry++) {
10230Sstevel@tonic-gate 		binding_bucket *binding;
10240Sstevel@tonic-gate 		/* look only at .text section symbols */
10250Sstevel@tonic-gate 		if (!is_text_section(symtab_entry->st_shndx,
10260Sstevel@tonic-gate 				    c->obj->elf,
10270Sstevel@tonic-gate 				    c->obj->ehdr))
10280Sstevel@tonic-gate 			continue;
10290Sstevel@tonic-gate 
10300Sstevel@tonic-gate 		/* look only at weak and global symbols */
10310Sstevel@tonic-gate #if	defined(_LP64)
10320Sstevel@tonic-gate 		stbind = ELF64_ST_BIND(symtab_entry->st_info);
10330Sstevel@tonic-gate #else
10340Sstevel@tonic-gate 		stbind = ELF32_ST_BIND(symtab_entry->st_info);
10350Sstevel@tonic-gate #endif
10360Sstevel@tonic-gate 		if (stbind != STB_GLOBAL) {
10370Sstevel@tonic-gate 			if (stbind != STB_WEAK)
10380Sstevel@tonic-gate 				continue;
10390Sstevel@tonic-gate 		}
10400Sstevel@tonic-gate 		/* look only at functions and objects */
10410Sstevel@tonic-gate #if	defined(_LP64)
10420Sstevel@tonic-gate 		sttype = ELF64_ST_TYPE(symtab_entry->st_info);
10430Sstevel@tonic-gate #else
10440Sstevel@tonic-gate 		sttype = ELF32_ST_TYPE(symtab_entry->st_info);
10450Sstevel@tonic-gate #endif
10460Sstevel@tonic-gate 		if (sttype != STT_FUNC) {
10470Sstevel@tonic-gate 			if (sttype != STT_OBJECT)
10480Sstevel@tonic-gate 				continue;
10490Sstevel@tonic-gate 		}
10500Sstevel@tonic-gate 		sym_name = buf + symtab_entry->st_name;
10510Sstevel@tonic-gate 		binding = (struct binding_bucket *)
10520Sstevel@tonic-gate 			    malloc(sizeof (binding_bucket));
10530Sstevel@tonic-gate 		binding->sym = sym_name;
10540Sstevel@tonic-gate 		binding->obj = c->obj->ename;
10550Sstevel@tonic-gate 		binding->section = "TEXT";
10560Sstevel@tonic-gate 		binding->ref_lib = "<Unknown>";
10570Sstevel@tonic-gate 		binding->def_lib = "*DIRECT*";
10580Sstevel@tonic-gate 		if (stbind == STB_GLOBAL)
10590Sstevel@tonic-gate 			binding->stbind = "GLOB";
10600Sstevel@tonic-gate 		else if (stbind == STB_WEAK)
10610Sstevel@tonic-gate 			binding->stbind = "WEAK";
10620Sstevel@tonic-gate 		if (sttype == STT_FUNC)
10630Sstevel@tonic-gate 			binding->sttype = "FUNC";
10640Sstevel@tonic-gate 		else if (sttype == STT_OBJECT)
10650Sstevel@tonic-gate 			binding->sttype = "OBJT";
10660Sstevel@tonic-gate 		if (pflag)
10670Sstevel@tonic-gate 			profile_binding(binding);
10680Sstevel@tonic-gate 		else
10690Sstevel@tonic-gate 			store_binding(binding);
10700Sstevel@tonic-gate 	}			/* end for */
10710Sstevel@tonic-gate }
10720Sstevel@tonic-gate 
10730Sstevel@tonic-gate /* ========= bind_symbols ================================================= */
10740Sstevel@tonic-gate /*
10750Sstevel@tonic-gate  * DESCRIPTION:
10760Sstevel@tonic-gate  * Scan through the dynamic symbol table and write them out.
10770Sstevel@tonic-gate  * INPUTS:        syms - pointer to application symbol table
10780Sstevel@tonic-gate  * symn - number of entries in application symbol table
10790Sstevel@tonic-gate  * buf  - first byte of application string table
10800Sstevel@tonic-gate  */
10810Sstevel@tonic-gate /* ======================================================================== */
10820Sstevel@tonic-gate 
10830Sstevel@tonic-gate static void
bind_symbols(obj_list * c,Elf64_Sym * syms,int symn,char * buf)10840Sstevel@tonic-gate bind_symbols(obj_list * c,
10850Sstevel@tonic-gate #if	defined(_LP64)
10860Sstevel@tonic-gate     Elf64_Sym * syms,
10870Sstevel@tonic-gate #else
10880Sstevel@tonic-gate     Elf32_Sym * syms,
10890Sstevel@tonic-gate #endif
10900Sstevel@tonic-gate     int symn,
10910Sstevel@tonic-gate     char *buf)
10920Sstevel@tonic-gate {
10930Sstevel@tonic-gate #if	defined(_LP64)
10940Sstevel@tonic-gate 	Elf64_Sym	*symtab_entry;
10950Sstevel@tonic-gate #else
10960Sstevel@tonic-gate 	Elf32_Sym	*symtab_entry;
10970Sstevel@tonic-gate #endif
10980Sstevel@tonic-gate 	int		i;
10990Sstevel@tonic-gate 	char		*sym_name;
11000Sstevel@tonic-gate 	binding_bucket	*binding;
11010Sstevel@tonic-gate 	int		sttype;
11020Sstevel@tonic-gate 	int		stbind;
11030Sstevel@tonic-gate 
11040Sstevel@tonic-gate 	symtab_entry = syms;
11050Sstevel@tonic-gate 	for (i = 0; i < symn; i++, symtab_entry++) {
11060Sstevel@tonic-gate 		/* look only at global symbols */
11070Sstevel@tonic-gate #if	defined(_LP64)
11080Sstevel@tonic-gate 		stbind = ELF64_ST_BIND(symtab_entry->st_info);
11090Sstevel@tonic-gate #else
11100Sstevel@tonic-gate 		stbind = ELF32_ST_BIND(symtab_entry->st_info);
11110Sstevel@tonic-gate #endif
11120Sstevel@tonic-gate 		if (symtab_entry->st_shndx == SHN_UNDEF)
11130Sstevel@tonic-gate 			continue;
11140Sstevel@tonic-gate 		if (symtab_entry->st_shndx == SHN_ABS)
11150Sstevel@tonic-gate 			continue;
11160Sstevel@tonic-gate 		if (stbind != STB_GLOBAL) {
11170Sstevel@tonic-gate 			if (stbind != STB_WEAK)
11180Sstevel@tonic-gate 				continue;
11190Sstevel@tonic-gate 		}
11200Sstevel@tonic-gate 		/* look only at functions and objects */
11210Sstevel@tonic-gate #if	defined(_LP64)
11220Sstevel@tonic-gate 		sttype = ELF64_ST_TYPE(symtab_entry->st_info);
11230Sstevel@tonic-gate #else
11240Sstevel@tonic-gate 		sttype = ELF32_ST_TYPE(symtab_entry->st_info);
11250Sstevel@tonic-gate #endif
11260Sstevel@tonic-gate 		if (sttype != STT_FUNC) {
11270Sstevel@tonic-gate 			if (sttype != STT_OBJECT)
11280Sstevel@tonic-gate 				continue;
11290Sstevel@tonic-gate 		}
11300Sstevel@tonic-gate 		sym_name = buf + symtab_entry->st_name;
11310Sstevel@tonic-gate 		binding = (binding_bucket *) malloc(sizeof (binding_bucket));
11320Sstevel@tonic-gate 		binding->obj = c->obj->ename;
11330Sstevel@tonic-gate 		binding->sym = sym_name;
11340Sstevel@tonic-gate 		if (!pflag)
11350Sstevel@tonic-gate 			check_store_binding(binding);
11360Sstevel@tonic-gate 	}			/* end for */
11370Sstevel@tonic-gate }
11380Sstevel@tonic-gate 
11390Sstevel@tonic-gate /* ========== get_scnfd =================================================== */
11400Sstevel@tonic-gate /*
11410Sstevel@tonic-gate  * DESCRIPTION:
11420Sstevel@tonic-gate  * Gets section descriptor for the associated string table
11430Sstevel@tonic-gate  * and verifies that the type of the section pointed to is
11440Sstevel@tonic-gate  * indeed of type STRTAB.  Returns a valid section descriptor
11450Sstevel@tonic-gate  * or NULL on error.
11460Sstevel@tonic-gate  */
11470Sstevel@tonic-gate /* ======================================================================== */
11480Sstevel@tonic-gate 
11490Sstevel@tonic-gate static Elf_Scn *
get_scnfd(Elf * e_file,int shstrtab,int SCN_TYPE)11500Sstevel@tonic-gate get_scnfd(Elf * e_file,
11510Sstevel@tonic-gate     int shstrtab,
11520Sstevel@tonic-gate     int SCN_TYPE)
11530Sstevel@tonic-gate {
11540Sstevel@tonic-gate 	Elf_Scn		*scn_fd;
11550Sstevel@tonic-gate #if	defined(_LP64)
11560Sstevel@tonic-gate 	Elf64_Shdr	*shdr;
11570Sstevel@tonic-gate #else
11580Sstevel@tonic-gate 	Elf32_Shdr	*shdr;
11590Sstevel@tonic-gate #endif
11600Sstevel@tonic-gate 
11610Sstevel@tonic-gate 	if ((scn_fd = elf_getscn(e_file, shstrtab)) == NULL)
11620Sstevel@tonic-gate 		return (NULL);
11630Sstevel@tonic-gate 
11640Sstevel@tonic-gate #if	defined(_LP64)
11650Sstevel@tonic-gate 	shdr = elf64_getshdr(scn_fd);
11660Sstevel@tonic-gate #else
11670Sstevel@tonic-gate 	shdr = elf32_getshdr(scn_fd);
11680Sstevel@tonic-gate #endif
11690Sstevel@tonic-gate 
11700Sstevel@tonic-gate 	if (shdr->sh_type != SCN_TYPE)
11710Sstevel@tonic-gate 		return (NULL);
11720Sstevel@tonic-gate 	return (scn_fd);
11730Sstevel@tonic-gate }
11740Sstevel@tonic-gate 
11750Sstevel@tonic-gate /* ========== print_symtab ================================================ */
11760Sstevel@tonic-gate /*
11770Sstevel@tonic-gate  * DESCRIPTION:
11780Sstevel@tonic-gate  * Outputs symbol bindings from symbol table to hash table.
11790Sstevel@tonic-gate  */
11800Sstevel@tonic-gate /* ======================================================================== */
11810Sstevel@tonic-gate 
11820Sstevel@tonic-gate static void
print_symtab(obj_list * com,Elf * elf_file,Elf64_Ehdr * ehdr,Elf64_Shdr * shdr,Elf_Scn * p_sd,char * filename)11830Sstevel@tonic-gate print_symtab(obj_list * com,
11840Sstevel@tonic-gate     Elf * elf_file,
11850Sstevel@tonic-gate #if	defined(_LP64)
11860Sstevel@tonic-gate     Elf64_Ehdr * ehdr,
11870Sstevel@tonic-gate     Elf64_Shdr * shdr,
11880Sstevel@tonic-gate #else
11890Sstevel@tonic-gate     Elf32_Ehdr * ehdr,
11900Sstevel@tonic-gate     Elf32_Shdr * shdr,
11910Sstevel@tonic-gate #endif
11920Sstevel@tonic-gate     Elf_Scn * p_sd,
11930Sstevel@tonic-gate     char *filename)
11940Sstevel@tonic-gate {
11950Sstevel@tonic-gate #if	defined(_LP64)
11960Sstevel@tonic-gate 	Elf64_Sym	*syms;
11970Sstevel@tonic-gate #else
11980Sstevel@tonic-gate 	Elf32_Sym	*syms;
11990Sstevel@tonic-gate #endif
12000Sstevel@tonic-gate 	Elf_Data	*data;
12010Sstevel@tonic-gate 	Elf_Scn		*scn;
12020Sstevel@tonic-gate 	int		count = 0;
12030Sstevel@tonic-gate 	char		*strs, *fullname;
12040Sstevel@tonic-gate 	obj_list	*c;
12050Sstevel@tonic-gate 
12060Sstevel@tonic-gate 	c = (obj_list *) malloc(sizeof (obj_list));
12070Sstevel@tonic-gate 	c->obj = (obj_com *) malloc(sizeof (obj_com));
12080Sstevel@tonic-gate 	fullname = (char *)malloc(strlen(com->obj->ename)
12090Sstevel@tonic-gate 			+ strlen(filename) + 2);
12100Sstevel@tonic-gate 	(void *) strcpy(fullname, com->obj->ename);
12110Sstevel@tonic-gate 	(void *) strcat(fullname, "(");
12120Sstevel@tonic-gate 	(void *) strcat(fullname, filename);
12130Sstevel@tonic-gate 	(void *) strcat(fullname, ")");
12140Sstevel@tonic-gate 	c->obj->ename = fullname;
12150Sstevel@tonic-gate 
12160Sstevel@tonic-gate 	if ((data = elf_getdata(p_sd, NULL)) == NULL) {
12170Sstevel@tonic-gate 		if (sflag)
12180Sstevel@tonic-gate 			(void) fprintf(stderr,
12190Sstevel@tonic-gate 			    "%s - No symbol table data\n",
12200Sstevel@tonic-gate 			    c->obj->ename);
12210Sstevel@tonic-gate 		return;
12220Sstevel@tonic-gate 	}
12230Sstevel@tonic-gate #if	defined(_LP64)
12240Sstevel@tonic-gate 	syms = (Elf64_Sym *) data->d_buf;
12250Sstevel@tonic-gate #else
12260Sstevel@tonic-gate 	syms = (Elf32_Sym *) data->d_buf;
12270Sstevel@tonic-gate #endif
12280Sstevel@tonic-gate 
12290Sstevel@tonic-gate 	scn = elf_getscn(elf_file, shdr->sh_link);
12300Sstevel@tonic-gate 	if (scn == NULL)
12310Sstevel@tonic-gate 		return;
12320Sstevel@tonic-gate 	data = elf_getdata(scn, NULL);
12330Sstevel@tonic-gate 	if (data == NULL)
12340Sstevel@tonic-gate 		return;
12350Sstevel@tonic-gate 	strs = data->d_buf;
12360Sstevel@tonic-gate 	count = shdr->sh_size / shdr->sh_entsize;
12370Sstevel@tonic-gate 	if (syms == NULL) {
12380Sstevel@tonic-gate 		if (sflag)
12390Sstevel@tonic-gate 			(void) fprintf(stderr,
12400Sstevel@tonic-gate 			    "%s: Problem reading symbol data\n",
12410Sstevel@tonic-gate 			    c->obj->ename);
12420Sstevel@tonic-gate 		return;
12430Sstevel@tonic-gate 	}
12440Sstevel@tonic-gate 	c->obj->sym_tab = syms;
12450Sstevel@tonic-gate 	c->obj->sym_num = count;
12460Sstevel@tonic-gate 	c->obj->sym_names = strs;
12470Sstevel@tonic-gate 
12480Sstevel@tonic-gate 	if (aflag)
12490Sstevel@tonic-gate 		(void) scan_archive_symbols(c,
12500Sstevel@tonic-gate 		    c->obj->sym_tab,
12510Sstevel@tonic-gate 		    c->obj->sym_num,
12520Sstevel@tonic-gate 		    c->obj->sym_names,
12530Sstevel@tonic-gate 		    elf_file,
12540Sstevel@tonic-gate 		    ehdr);
12550Sstevel@tonic-gate 	else
12560Sstevel@tonic-gate 		(void) bind_symbols(c,
12570Sstevel@tonic-gate 		    c->obj->sym_tab,
12580Sstevel@tonic-gate 		    c->obj->sym_num,
12590Sstevel@tonic-gate 		    c->obj->sym_names);
12600Sstevel@tonic-gate 	free(c->obj);
12610Sstevel@tonic-gate 	free(c);
12620Sstevel@tonic-gate }
12630Sstevel@tonic-gate 
12640Sstevel@tonic-gate /* ========== get_symtab ================================================== */
12650Sstevel@tonic-gate /*
12660Sstevel@tonic-gate  * DESCRIPTION:
12670Sstevel@tonic-gate  * Gets the symbol table.  This function does not output the contents
12680Sstevel@tonic-gate  * of the symbol table but sets up the parameters and then calls
12690Sstevel@tonic-gate  * print_symtab() to output the symbol bindings.
12700Sstevel@tonic-gate  */
12710Sstevel@tonic-gate /* ======================================================================== */
12720Sstevel@tonic-gate 
12730Sstevel@tonic-gate static void
get_symtab(obj_list * c,Elf * elf_file,Elf64_Ehdr * ehdr,char * filename)12740Sstevel@tonic-gate get_symtab(obj_list * c,
12750Sstevel@tonic-gate     Elf * elf_file,
12760Sstevel@tonic-gate #if	defined(_LP64)
12770Sstevel@tonic-gate     Elf64_Ehdr * ehdr,
12780Sstevel@tonic-gate #else
12790Sstevel@tonic-gate     Elf32_Ehdr * ehdr,
12800Sstevel@tonic-gate #endif
12810Sstevel@tonic-gate     char *filename)
12820Sstevel@tonic-gate {
12830Sstevel@tonic-gate 	Elf_Scn		*scn, *scnfd;
12840Sstevel@tonic-gate 	Elf_Data	*data;
12850Sstevel@tonic-gate #if	defined(_LP64)
12860Sstevel@tonic-gate 	Elf64_Word	symtabtype;
12870Sstevel@tonic-gate #else
12880Sstevel@tonic-gate 	Elf32_Word	symtabtype;
12890Sstevel@tonic-gate #endif
12900Sstevel@tonic-gate 
12910Sstevel@tonic-gate 	/* get section header string table */
12920Sstevel@tonic-gate 	scnfd = get_scnfd(elf_file, ehdr->e_shstrndx, SHT_STRTAB);
12930Sstevel@tonic-gate 	if (scnfd == NULL) {
12940Sstevel@tonic-gate 		if (sflag)
12950Sstevel@tonic-gate 			(void) fprintf(stderr,
12960Sstevel@tonic-gate 			    "%s: Could not get string table\n",
12970Sstevel@tonic-gate 			    filename);
12980Sstevel@tonic-gate 		return;
12990Sstevel@tonic-gate 	}
13000Sstevel@tonic-gate 	data = elf_getdata(scnfd, NULL);
13010Sstevel@tonic-gate 	if (data->d_size == 0) {
13020Sstevel@tonic-gate 		if (sflag)
13030Sstevel@tonic-gate 			(void) fprintf(stderr,
13040Sstevel@tonic-gate 			    "%s: No data in string table\n",
13050Sstevel@tonic-gate 			    filename);
13060Sstevel@tonic-gate 		return;
13070Sstevel@tonic-gate 	}
13080Sstevel@tonic-gate 	symtabtype = SHT_SYMTAB;
13090Sstevel@tonic-gate 	scn = 0;
13100Sstevel@tonic-gate 	while ((scn = elf_nextscn(elf_file, scn)) != 0) {
13110Sstevel@tonic-gate #if	defined(_LP64)
13120Sstevel@tonic-gate 		Elf64_Shdr	*shdr;
13130Sstevel@tonic-gate 		if ((shdr = elf64_getshdr(scn)) == NULL)
13140Sstevel@tonic-gate #else
13150Sstevel@tonic-gate 		Elf32_Shdr	*shdr;
13160Sstevel@tonic-gate 		if ((shdr = elf32_getshdr(scn)) == NULL)
13170Sstevel@tonic-gate #endif
13180Sstevel@tonic-gate 		{
13190Sstevel@tonic-gate 			if (sflag)
13200Sstevel@tonic-gate 				(void) fprintf(stderr,
13210Sstevel@tonic-gate 				    "%s: %s:\n",
13220Sstevel@tonic-gate 				    filename,
13230Sstevel@tonic-gate 				    elf_errmsg(-1));
13240Sstevel@tonic-gate 			return;
13250Sstevel@tonic-gate 		}
13260Sstevel@tonic-gate 		if (shdr->sh_type == symtabtype)
13270Sstevel@tonic-gate 			print_symtab(c, elf_file, ehdr, shdr, scn, filename);
13280Sstevel@tonic-gate 	}			/* end while */
13290Sstevel@tonic-gate }
13300Sstevel@tonic-gate 
13310Sstevel@tonic-gate /* ========== process ===================================================== */
13320Sstevel@tonic-gate /*
13330Sstevel@tonic-gate  * DESCRIPTION:
13340Sstevel@tonic-gate  * Gets the ELF header and, if it exists, call get_symtab() to begin
13350Sstevel@tonic-gate  * processing of the file; otherwise, returns with a warning.
13360Sstevel@tonic-gate  */
13370Sstevel@tonic-gate /* ======================================================================== */
13380Sstevel@tonic-gate 
13390Sstevel@tonic-gate static void
process(obj_list * c,Elf * elf_file,char * filename)13400Sstevel@tonic-gate process(obj_list * c,
13410Sstevel@tonic-gate     Elf * elf_file,
13420Sstevel@tonic-gate     char *filename)
13430Sstevel@tonic-gate {
13440Sstevel@tonic-gate #if	defined(_LP64)
13450Sstevel@tonic-gate 	Elf64_Ehdr	*ehdr;
13460Sstevel@tonic-gate #else
13470Sstevel@tonic-gate 	Elf32_Ehdr	*ehdr;
13480Sstevel@tonic-gate #endif
13490Sstevel@tonic-gate 
13500Sstevel@tonic-gate #if	defined(_LP64)
13510Sstevel@tonic-gate 	if ((ehdr = elf64_getehdr(elf_file)) == NULL)
13520Sstevel@tonic-gate #else
13530Sstevel@tonic-gate 	if ((ehdr = elf32_getehdr(elf_file)) == NULL)
13540Sstevel@tonic-gate #endif
13550Sstevel@tonic-gate 	{
13560Sstevel@tonic-gate 		if (sflag)
13570Sstevel@tonic-gate 			(void) fprintf(stderr,
13580Sstevel@tonic-gate 			    "%s: %s\n",
13590Sstevel@tonic-gate 			    filename, elf_errmsg(-1));
13600Sstevel@tonic-gate 		return;
13610Sstevel@tonic-gate 	}
13620Sstevel@tonic-gate 	get_symtab(c, elf_file, ehdr, filename);
13630Sstevel@tonic-gate }
13640Sstevel@tonic-gate 
13650Sstevel@tonic-gate /* ========== process_archive ============================================= */
13660Sstevel@tonic-gate /*
13670Sstevel@tonic-gate  * DESCRIPTION:
13680Sstevel@tonic-gate  * Processes member files of an archive.  This function provides
13690Sstevel@tonic-gate  * a loop through an archive equivalent the processing of each_file
13700Sstevel@tonic-gate  * for individual object file.
13710Sstevel@tonic-gate  */
13720Sstevel@tonic-gate /* ======================================================================== */
13730Sstevel@tonic-gate 
13740Sstevel@tonic-gate static int
process_archive(obj_list * c)13750Sstevel@tonic-gate process_archive(obj_list * c)
13760Sstevel@tonic-gate {
13770Sstevel@tonic-gate 	Elf_Arhdr	*p_ar;
13780Sstevel@tonic-gate 	Elf		*arf;
13790Sstevel@tonic-gate 	Elf_Cmd		cmd = ELF_C_READ;
13800Sstevel@tonic-gate 
13810Sstevel@tonic-gate 	while ((arf = elf_begin(c->obj->fd, cmd, c->obj->elf)) != 0) {
13820Sstevel@tonic-gate 		p_ar = elf_getarhdr(arf);
13830Sstevel@tonic-gate 		if (p_ar == NULL) {
13840Sstevel@tonic-gate 			if (sflag)
13850Sstevel@tonic-gate 				(void) fprintf(stderr,
13860Sstevel@tonic-gate 				    "%s: %s\n",
13870Sstevel@tonic-gate 				    c->obj->filename, elf_errmsg(-1));
13880Sstevel@tonic-gate 			return (FAIL);
13890Sstevel@tonic-gate 		}
13900Sstevel@tonic-gate 		if ((int)strncmp(p_ar->ar_name, "/", 1) == 0) {
13910Sstevel@tonic-gate 			cmd = elf_next(arf);
13920Sstevel@tonic-gate 			(void) elf_end(arf);
13930Sstevel@tonic-gate 			continue;
13940Sstevel@tonic-gate 		}
13950Sstevel@tonic-gate 		if (elf_kind(arf) == ELF_K_ELF) {
13960Sstevel@tonic-gate 			process(c, arf, p_ar->ar_name);
13970Sstevel@tonic-gate 		} else {
13980Sstevel@tonic-gate 			cmd = elf_next(arf);
13990Sstevel@tonic-gate 			(void) elf_end(arf);
14000Sstevel@tonic-gate 			continue;
14010Sstevel@tonic-gate 		}
14020Sstevel@tonic-gate 		cmd = elf_next(arf);
14030Sstevel@tonic-gate 		(void) elf_end(arf);
14040Sstevel@tonic-gate 	}			/* end while */
14050Sstevel@tonic-gate 	return (SUCCEED);
14060Sstevel@tonic-gate }
14070Sstevel@tonic-gate 
14080Sstevel@tonic-gate /* ========== add_dtneeded ================================================ */
14090Sstevel@tonic-gate /*
14100Sstevel@tonic-gate  * DESCRIPTION:
14110Sstevel@tonic-gate  * Inserts a new node into the linked list.  It is basically for
14120Sstevel@tonic-gate  * generating a simple linked list of DT_NEEDED entries.
14130Sstevel@tonic-gate  */
14140Sstevel@tonic-gate /* ======================================================================== */
14150Sstevel@tonic-gate 
14160Sstevel@tonic-gate static dt_list *
add_dtneeded(dt_list * p,dt_list * node)14170Sstevel@tonic-gate add_dtneeded(dt_list * p,
14180Sstevel@tonic-gate     dt_list * node)
14190Sstevel@tonic-gate {
14200Sstevel@tonic-gate 	dt_list		*head = p, *tail;
14210Sstevel@tonic-gate 
14220Sstevel@tonic-gate 	if (!head)
14230Sstevel@tonic-gate 		head = node;
14240Sstevel@tonic-gate 	else {
14250Sstevel@tonic-gate 		tail = head;
14260Sstevel@tonic-gate 		if (strcmp(tail->libname, node->libname) == 0) {
14270Sstevel@tonic-gate 			free(node);
14280Sstevel@tonic-gate 			return (head);
14290Sstevel@tonic-gate 		}
14300Sstevel@tonic-gate 		while (tail->next != NULL) {
14310Sstevel@tonic-gate 			tail = tail->next;
14320Sstevel@tonic-gate 			if (strcmp(tail->libname, node->libname) == 0) {
14330Sstevel@tonic-gate 				free(node);
14340Sstevel@tonic-gate 				return (head);
14350Sstevel@tonic-gate 			}
14360Sstevel@tonic-gate 		}
14370Sstevel@tonic-gate 		tail->next = node;
14380Sstevel@tonic-gate 	}
14390Sstevel@tonic-gate 	return (head);
14400Sstevel@tonic-gate }
14410Sstevel@tonic-gate 
14420Sstevel@tonic-gate /* ========== find_dtneeded =============================================== */
14430Sstevel@tonic-gate /*
14440Sstevel@tonic-gate  * DESCRIPTION:
14450Sstevel@tonic-gate  * Find the DT_NEEDED, DT_FILTER, and DT_AUXILIARY entries, and save
14460Sstevel@tonic-gate  * them to link list.
14470Sstevel@tonic-gate  */
14480Sstevel@tonic-gate /* ======================================================================== */
14490Sstevel@tonic-gate 
14500Sstevel@tonic-gate static void
find_dtneeded(obj_list * c)14510Sstevel@tonic-gate find_dtneeded(obj_list * c)
14520Sstevel@tonic-gate {
14530Sstevel@tonic-gate #if	defined(_LP64)
14540Sstevel@tonic-gate 	Elf64_Dyn	*dcurrent; /* temp 64 bit dynamic table entry ptr */
14550Sstevel@tonic-gate #else
14560Sstevel@tonic-gate 	Elf32_Dyn	*dcurrent; /* temp 32 bit dynamic table entry ptr */
14570Sstevel@tonic-gate #endif
14580Sstevel@tonic-gate 	dt_list		*tmp_lib;
14590Sstevel@tonic-gate 
14600Sstevel@tonic-gate 	dcurrent = c->obj->dynsect;
14610Sstevel@tonic-gate 	if (!dcurrent)
14620Sstevel@tonic-gate 		return;
14630Sstevel@tonic-gate 
14640Sstevel@tonic-gate 	/*
14650Sstevel@tonic-gate 	 * If there are any DT_NEEDED
14660Sstevel@tonic-gate 	 * entries, add them to the dt_needed list.
14670Sstevel@tonic-gate 	 */
14680Sstevel@tonic-gate 
14690Sstevel@tonic-gate 	while (dcurrent->d_tag != DT_NULL) {
14700Sstevel@tonic-gate 		if (dcurrent->d_tag == DT_NEEDED) {
14710Sstevel@tonic-gate 			tmp_lib = (dt_list *) malloc(sizeof (dt_list));
14720Sstevel@tonic-gate 			tmp_lib->libname = c->obj->dynnames +
14730Sstevel@tonic-gate 					    dcurrent->d_un.d_val;
14740Sstevel@tonic-gate 			tmp_lib->d_tag = dcurrent->d_tag;
14750Sstevel@tonic-gate 			tmp_lib->next = NULL;
14760Sstevel@tonic-gate 			dt_needed = add_dtneeded(dt_needed, tmp_lib);
14770Sstevel@tonic-gate 		}
14780Sstevel@tonic-gate 		dcurrent++;
14790Sstevel@tonic-gate 	}
14800Sstevel@tonic-gate }
14810Sstevel@tonic-gate 
14820Sstevel@tonic-gate /* ========= obj_elfcheck ================================================= */
14830Sstevel@tonic-gate /*
14840Sstevel@tonic-gate  * DESCRIPTION:
14850Sstevel@tonic-gate  * It checks the elf header and saves its pointer if succeeds.
14860Sstevel@tonic-gate  * It checks the program header and saves its pointer if succeed.
14870Sstevel@tonic-gate  * It checks the section header table and saves its pointer to
14880Sstevel@tonic-gate  * section header table and section header string table if it
14890Sstevel@tonic-gate  * succeeds.  It finds dynsym symbol table and saves its pointer.
14900Sstevel@tonic-gate  * It finds symtab and saves its pointers.
14910Sstevel@tonic-gate  */
14920Sstevel@tonic-gate /* ======================================================================== */
14930Sstevel@tonic-gate 
14940Sstevel@tonic-gate static int
obj_elfcheck(obj_list * c)14950Sstevel@tonic-gate obj_elfcheck(obj_list * c)
14960Sstevel@tonic-gate {
14970Sstevel@tonic-gate 	/* open the file and ELF descriptor */
14980Sstevel@tonic-gate 	if (obj_init(c) == FAIL) {
14990Sstevel@tonic-gate 		obj_finis(c);
15000Sstevel@tonic-gate 		return (FAIL);
15010Sstevel@tonic-gate 	}
15020Sstevel@tonic-gate 	/* if it is an archive library */
15030Sstevel@tonic-gate 	if (elf_kind(c->obj->elf) == ELF_K_AR) {
15040Sstevel@tonic-gate 		if (process_archive(c) == SUCCEED)
15050Sstevel@tonic-gate 			return (SUCCEED);
15060Sstevel@tonic-gate 		else
15070Sstevel@tonic-gate 			return (FAIL);
15080Sstevel@tonic-gate 	}
15090Sstevel@tonic-gate 	/* get the ELF header information */
15100Sstevel@tonic-gate 	if (obj_elf_hdr(c) == FAIL) {
15110Sstevel@tonic-gate 		obj_finis(c);
15120Sstevel@tonic-gate 		return (FAIL);
15130Sstevel@tonic-gate 	}
15140Sstevel@tonic-gate 	/* get the program header for dynamic, etc. */
15150Sstevel@tonic-gate 	if (obj_prog_hdr(c) == FAIL) {
15160Sstevel@tonic-gate 		obj_finis(c);
15170Sstevel@tonic-gate 		return (FAIL);
15180Sstevel@tonic-gate 	}
15190Sstevel@tonic-gate 	/* find and save pointers to application symbol tables */
15200Sstevel@tonic-gate 	if (find_symtabs(c) == FAIL) {
15210Sstevel@tonic-gate 		obj_finis(c);
15220Sstevel@tonic-gate 		return (FAIL);
15230Sstevel@tonic-gate 	}
15240Sstevel@tonic-gate 	/* check the existence of application's symbol tables */
15250Sstevel@tonic-gate 	if (obj_app_symtab(c) == FAIL) {
15260Sstevel@tonic-gate 		obj_finis(c);
15270Sstevel@tonic-gate 		return (FAIL);
15280Sstevel@tonic-gate 	}
15290Sstevel@tonic-gate 	/* find and save pointers to the dynamic section */
15300Sstevel@tonic-gate 	if (find_dynamic_sect(c) == FAIL) {
15310Sstevel@tonic-gate 		obj_finis(c);
15320Sstevel@tonic-gate 		return (FAIL);
15330Sstevel@tonic-gate 	}
15340Sstevel@tonic-gate 	/*
15350Sstevel@tonic-gate 	 * find the DT_NEEDED entries and save the name to dt_needed link
15360Sstevel@tonic-gate 	 * list
15370Sstevel@tonic-gate 	 */
15380Sstevel@tonic-gate 	(void) find_dtneeded(c);
15390Sstevel@tonic-gate 
15400Sstevel@tonic-gate 	return (SUCCEED);
15410Sstevel@tonic-gate }
15420Sstevel@tonic-gate 
15430Sstevel@tonic-gate /* ========= analyze_dependency ========================================== */
15440Sstevel@tonic-gate /*
15450Sstevel@tonic-gate  * DESCRIPTION:
15460Sstevel@tonic-gate  * Read in an dependency object file and analyze it.
15470Sstevel@tonic-gate  * INPUTS:        dep_file - dependency object file name
15480Sstevel@tonic-gate  */
15490Sstevel@tonic-gate /* ======================================================================= */
15500Sstevel@tonic-gate 
15510Sstevel@tonic-gate static int
analyze_dependency(char * dep_file)15520Sstevel@tonic-gate analyze_dependency(char *dep_file)
15530Sstevel@tonic-gate {
15540Sstevel@tonic-gate 	obj_list	*dep_obj;
15550Sstevel@tonic-gate 
15560Sstevel@tonic-gate 	if (!dep_file)
15570Sstevel@tonic-gate 		return (SUCCEED);
15580Sstevel@tonic-gate 
15590Sstevel@tonic-gate 	dep_obj = (obj_list *) malloc(sizeof (obj_list));
15600Sstevel@tonic-gate 	(void) memset(dep_obj, 0, sizeof (obj_list));
15610Sstevel@tonic-gate 	dep_obj->obj = (obj_com *) malloc(sizeof (obj_com));
15620Sstevel@tonic-gate 	(void) memset(dep_obj->obj, 0, sizeof (obj_com));
15630Sstevel@tonic-gate 	dep_obj->next = NULL;
15640Sstevel@tonic-gate 	dep_obj->obj->filename = dep_file;
15650Sstevel@tonic-gate 	dep_obj->obj->ename = dep_obj->obj->filename;
15660Sstevel@tonic-gate 
15670Sstevel@tonic-gate 	if (obj_elfcheck(dep_obj) == FAIL)
15680Sstevel@tonic-gate 		return (FAIL);
15690Sstevel@tonic-gate 
15700Sstevel@tonic-gate 	if (dep_obj->obj->dsym_names != NULL)
15710Sstevel@tonic-gate 		bind_symbols(dep_obj,
15720Sstevel@tonic-gate 		    dep_obj->obj->dsym_tab,
15730Sstevel@tonic-gate 		    dep_obj->obj->dsym_num,
15740Sstevel@tonic-gate 		    dep_obj->obj->dsym_names);
15750Sstevel@tonic-gate 
15760Sstevel@tonic-gate 	if (dep_obj->obj->sym_names != NULL)
15770Sstevel@tonic-gate 		bind_symbols(dep_obj,
15780Sstevel@tonic-gate 		    dep_obj->obj->sym_tab,
15790Sstevel@tonic-gate 		    dep_obj->obj->sym_num,
15800Sstevel@tonic-gate 		    dep_obj->obj->sym_names);
15810Sstevel@tonic-gate 	return (SUCCEED);
15820Sstevel@tonic-gate }
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate /* ========= analyze_main =============================================== */
15850Sstevel@tonic-gate /*
15860Sstevel@tonic-gate  * DESCRIPTION:
15870Sstevel@tonic-gate  * Read in an object file and analyze it.
15880Sstevel@tonic-gate  */
15890Sstevel@tonic-gate /* ====================================================================== */
15900Sstevel@tonic-gate 
15910Sstevel@tonic-gate static void
analyze_main(obj_list * c)15920Sstevel@tonic-gate analyze_main(obj_list * c)
15930Sstevel@tonic-gate {
15940Sstevel@tonic-gate 	int	i;
15950Sstevel@tonic-gate 
15960Sstevel@tonic-gate 	if (obj_elfcheck(c) == FAIL)
15970Sstevel@tonic-gate 		exit(1);
15980Sstevel@tonic-gate 
15990Sstevel@tonic-gate 	aflag = FALSE;
16000Sstevel@tonic-gate 
16010Sstevel@tonic-gate 	if (c->obj->sym_names != NULL)
16020Sstevel@tonic-gate 		scan_symbols(c,
16030Sstevel@tonic-gate 		    c->obj->sym_tab,
16040Sstevel@tonic-gate 		    c->obj->sym_num,
16050Sstevel@tonic-gate 		    c->obj->sym_names);
16060Sstevel@tonic-gate 	else if (c->obj->dsym_names != NULL)
16070Sstevel@tonic-gate 		scan_symbols(c,
16080Sstevel@tonic-gate 		    c->obj->dsym_tab,
16090Sstevel@tonic-gate 		    c->obj->dsym_num,
16100Sstevel@tonic-gate 		    c->obj->dsym_names);
16110Sstevel@tonic-gate 
16120Sstevel@tonic-gate 	if (c->obj->numfiles == 0)
16130Sstevel@tonic-gate 		return;
16140Sstevel@tonic-gate 
16150Sstevel@tonic-gate 	for (i = 0; i < c->obj->numfiles; i++)
16160Sstevel@tonic-gate 		(void) analyze_dependency(c->obj->filenames[i]);
16170Sstevel@tonic-gate }
16180Sstevel@tonic-gate 
16190Sstevel@tonic-gate /* ========= analyze_args ================================================= */
16200Sstevel@tonic-gate /*
16210Sstevel@tonic-gate  * DESCRIPTION:
16220Sstevel@tonic-gate  * Analyze the command-line options.
16230Sstevel@tonic-gate  */
16240Sstevel@tonic-gate /* ======================================================================== */
16250Sstevel@tonic-gate 
16260Sstevel@tonic-gate static int
analyze_args(obj_list * c,int argc,char * argv[])16270Sstevel@tonic-gate analyze_args(obj_list * c,
16280Sstevel@tonic-gate     int argc,
16290Sstevel@tonic-gate     char *argv[])
16300Sstevel@tonic-gate {
16310Sstevel@tonic-gate 	extern char	*optarg;
16320Sstevel@tonic-gate 	extern int	optind;
16330Sstevel@tonic-gate 	int		option;
16340Sstevel@tonic-gate 	int		i;
16350Sstevel@tonic-gate 	char		*nameptr;
16360Sstevel@tonic-gate 	char		slash = '/';
16370Sstevel@tonic-gate 	int		errflg = 0;
16380Sstevel@tonic-gate 
16390Sstevel@tonic-gate 	if ((nameptr = strrchr(argv[0], slash)) != NULL)
16400Sstevel@tonic-gate 		nameptr++;
16410Sstevel@tonic-gate 	else
16420Sstevel@tonic-gate 		nameptr = argv[0];
16430Sstevel@tonic-gate 
16440Sstevel@tonic-gate 	while ((option = getopt(argc, argv, "pso:a")) != EOF) {
16450Sstevel@tonic-gate 		switch (option) {
16460Sstevel@tonic-gate 		case 'p':	/* just do profiling; write to stdout */
16470Sstevel@tonic-gate 			pflag = 1;
16480Sstevel@tonic-gate 			break;
16490Sstevel@tonic-gate 		case 's':	/* silent mode to turn off stderr messages */
16500Sstevel@tonic-gate 			sflag = 0;
16510Sstevel@tonic-gate 			break;
16520Sstevel@tonic-gate 		case 'o':	/* redirects the output */
16530Sstevel@tonic-gate 			outputfile = optarg;
16540Sstevel@tonic-gate 			oflag = 1;
16550Sstevel@tonic-gate 			break;
16560Sstevel@tonic-gate 		case 'a':	/* processes archive as input */
16570Sstevel@tonic-gate 			aflag = 1;
16580Sstevel@tonic-gate 			break;
16590Sstevel@tonic-gate 		case '?':
16600Sstevel@tonic-gate 		default:
16610Sstevel@tonic-gate 			errflg++;
16620Sstevel@tonic-gate 		}		/* end switch */
16630Sstevel@tonic-gate 	}			/* end while */
16640Sstevel@tonic-gate 
16650Sstevel@tonic-gate 	/* exit if there are no files to process */
16660Sstevel@tonic-gate 	if (optind >= argc)
16670Sstevel@tonic-gate 		errflg++;
16680Sstevel@tonic-gate 	if (errflg) {
16690Sstevel@tonic-gate 		(void) fprintf(stderr,
16700Sstevel@tonic-gate 		    "usage: %s [-p] [-s] [-o outputfile] ", nameptr);
16710Sstevel@tonic-gate 		(void) fprintf(stderr,
16720Sstevel@tonic-gate 		    "<archive>|<binary_executable>\n");
16730Sstevel@tonic-gate 		(void) fprintf(stderr,
16740Sstevel@tonic-gate 		    "\t\t   [<archive>|<dynamic library>...]\n");
16750Sstevel@tonic-gate 		return (FALSE);
16760Sstevel@tonic-gate 	}			/* end if */
16770Sstevel@tonic-gate 	c->obj->filename = argv[optind++];
16780Sstevel@tonic-gate 	c->obj->ename = c->obj->filename;
16790Sstevel@tonic-gate 
16800Sstevel@tonic-gate 	/* compute number of files and save their pointers */
16810Sstevel@tonic-gate 	c->obj->numfiles = argc - optind;
16820Sstevel@tonic-gate 
16830Sstevel@tonic-gate 	if (c->obj->numfiles > 0) {
16840Sstevel@tonic-gate 		i = 0;
16850Sstevel@tonic-gate 		c->obj->filenames = (char **)
16860Sstevel@tonic-gate 				    malloc(sizeof (char *) *
16870Sstevel@tonic-gate 				    (c->obj->numfiles + 1));
16880Sstevel@tonic-gate 		for (; optind < argc; i++, optind++)
16890Sstevel@tonic-gate 			c->obj->filenames[i] = argv[optind];
16900Sstevel@tonic-gate 	}
16910Sstevel@tonic-gate 	return (TRUE);
16920Sstevel@tonic-gate }
16930Sstevel@tonic-gate 
16940Sstevel@tonic-gate /* ======================================================================= */
16950Sstevel@tonic-gate /*
16960Sstevel@tonic-gate  * Here starts the main ()
16970Sstevel@tonic-gate  */
16980Sstevel@tonic-gate /* ======================================================================= */
16990Sstevel@tonic-gate 
1700*71Scraigm int
main(int argc,char * argv[])1701*71Scraigm main(int argc, char *argv[])
17020Sstevel@tonic-gate {
17030Sstevel@tonic-gate 	obj_list	*main_obj;
17040Sstevel@tonic-gate 	dt_list		*q;
17050Sstevel@tonic-gate 
17060Sstevel@tonic-gate 	main_obj = (obj_list *) malloc(sizeof (obj_list));
17070Sstevel@tonic-gate 	(void) memset(main_obj, 0, sizeof (obj_list));
17080Sstevel@tonic-gate 	main_obj->obj = (obj_com *) malloc(sizeof (obj_com));
17090Sstevel@tonic-gate 	(void) memset(main_obj->obj, 0, sizeof (obj_com));
17100Sstevel@tonic-gate 	main_obj->next = NULL;
17110Sstevel@tonic-gate 
17120Sstevel@tonic-gate 	if (!analyze_args(main_obj, argc, argv))
17130Sstevel@tonic-gate 		exit(1);
17140Sstevel@tonic-gate 
17150Sstevel@tonic-gate 	if (oflag && pflag) {
17160Sstevel@tonic-gate 		if ((OUTPUT_FD = fopen(outputfile, "w")) == NULL) {
17170Sstevel@tonic-gate 			if (sflag)
17180Sstevel@tonic-gate 				(void) fprintf(stderr,
17190Sstevel@tonic-gate 				    "\nfopen failed to open <%s>...\n\n",
17200Sstevel@tonic-gate 				    outputfile);
17210Sstevel@tonic-gate 			exit(1);
17220Sstevel@tonic-gate 		}
17230Sstevel@tonic-gate 	}
17240Sstevel@tonic-gate 	/* generates profile report if pflag is set */
17250Sstevel@tonic-gate 	if (pflag)
17260Sstevel@tonic-gate 		(void) fprintf(OUTPUT_FD,
17270Sstevel@tonic-gate 		    "#generated by %s\n",
17280Sstevel@tonic-gate 		    argv[0]);
17290Sstevel@tonic-gate 
17300Sstevel@tonic-gate 	/* analyze the input file */
17310Sstevel@tonic-gate 	analyze_main(main_obj);
17320Sstevel@tonic-gate 
17330Sstevel@tonic-gate 	/* generates profile report */
17340Sstevel@tonic-gate 	if (!pflag)
17350Sstevel@tonic-gate 		output_binding(argv[0], main_obj->obj->ename);
17360Sstevel@tonic-gate 
17370Sstevel@tonic-gate 	/* close the library .so file descriptor and ELF descriptor */
17380Sstevel@tonic-gate 	obj_finis(main_obj);
17390Sstevel@tonic-gate 
17400Sstevel@tonic-gate 	/* de-allocates the dt_needed link list */
17410Sstevel@tonic-gate 	if (dt_needed) {
17420Sstevel@tonic-gate 		while (dt_needed) {
17430Sstevel@tonic-gate 			q = dt_needed;
17440Sstevel@tonic-gate 			dt_needed = dt_needed->next;
17450Sstevel@tonic-gate 			free(q);
17460Sstevel@tonic-gate 		}
17470Sstevel@tonic-gate 	}
17480Sstevel@tonic-gate 	/* close the output redirect file descriptor */
17490Sstevel@tonic-gate 	if (oflag)
17500Sstevel@tonic-gate 		(void) fclose(OUTPUT_FD);
17510Sstevel@tonic-gate 
1752*71Scraigm 	return (0);
17530Sstevel@tonic-gate }
1754