xref: /onnv-gate/usr/src/cmd/sgs/link_audit/common/bindings.c (revision 12927:a27c46eb192b)
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
54574Sraf  * Common Development and Distribution License (the "License").
64574Sraf  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
214574Sraf 
220Sstevel@tonic-gate /*
23*12927SRod.Evans@Sun.COM  * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate #include	<link.h>
260Sstevel@tonic-gate #include	<stdlib.h>
270Sstevel@tonic-gate #include	<unistd.h>
280Sstevel@tonic-gate #include	<sys/types.h>
290Sstevel@tonic-gate #include	<sys/stat.h>
300Sstevel@tonic-gate #include	<sys/regset.h>
310Sstevel@tonic-gate #include	<sys/frame.h>
320Sstevel@tonic-gate #include	<sys/lwp.h>
330Sstevel@tonic-gate #include	<fcntl.h>
340Sstevel@tonic-gate #include	<stdio.h>
350Sstevel@tonic-gate #include	<sys/mman.h>
360Sstevel@tonic-gate #include	<errno.h>
370Sstevel@tonic-gate #include	<signal.h>
380Sstevel@tonic-gate #include	<synch.h>
390Sstevel@tonic-gate #include	<string.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #include	"bindings.h"
420Sstevel@tonic-gate #include	"env.h"
430Sstevel@tonic-gate 
44*12927SRod.Evans@Sun.COM static Elist		*bindto_list = NULL;
45*12927SRod.Evans@Sun.COM static Elist		*bindfrom_list = NULL;
460Sstevel@tonic-gate 
470Sstevel@tonic-gate static bindhead		*bhp = NULL;
480Sstevel@tonic-gate static unsigned int	current_map_len = 0;
490Sstevel@tonic-gate static char		*buffer_name;
500Sstevel@tonic-gate static const sigset_t	iset = { ~0U, ~0U, ~0U, ~0U };
510Sstevel@tonic-gate static lwp_mutex_t	sharedmutex = SHAREDMUTEX;
520Sstevel@tonic-gate 
530Sstevel@tonic-gate /*
540Sstevel@tonic-gate  * This routine was stolen from libelf.so.1
550Sstevel@tonic-gate  */
560Sstevel@tonic-gate static unsigned long
ehash(const char * name)570Sstevel@tonic-gate ehash(const char *name)
580Sstevel@tonic-gate {
59*12927SRod.Evans@Sun.COM 	unsigned int		g, h = 0;
60*12927SRod.Evans@Sun.COM 	const unsigned char	*nm = (unsigned char *)name;
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	while (*nm != '\0') {
630Sstevel@tonic-gate 		h = (h << 4) + *nm++;
640Sstevel@tonic-gate 		/* LINTED */
650Sstevel@tonic-gate 		if ((g = (unsigned int)(h & MASK)) != 0)
660Sstevel@tonic-gate 			h ^= g >> 24;
670Sstevel@tonic-gate 		h &= ~MASK;
680Sstevel@tonic-gate 	}
690Sstevel@tonic-gate 	return ((unsigned long)h);
700Sstevel@tonic-gate }
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 
730Sstevel@tonic-gate static void
output_err_message(const char * msg)740Sstevel@tonic-gate output_err_message(const char *msg)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate 	int fd;
770Sstevel@tonic-gate 	if ((fd = open("/tmp/bind_err", O_RDWR | O_CREAT, 0666)) == -1) {
780Sstevel@tonic-gate 		(void) fprintf(stderr, "bindings.so: unable to open err_log\n");
790Sstevel@tonic-gate 		perror("open");
800Sstevel@tonic-gate 	}
810Sstevel@tonic-gate 	(void) lseek(fd, 0, SEEK_END);
820Sstevel@tonic-gate 	(void) write(fd, msg, strlen(msg));
830Sstevel@tonic-gate 	(void) close(fd);
840Sstevel@tonic-gate }
850Sstevel@tonic-gate 
860Sstevel@tonic-gate /*
870Sstevel@tonic-gate  * common mutex locking & unlocking routines for this module.  This is to
880Sstevel@tonic-gate  * control the setting of 'lock_held'.
890Sstevel@tonic-gate  */
900Sstevel@tonic-gate static void
bt_lock(lwp_mutex_t * lock)910Sstevel@tonic-gate bt_lock(lwp_mutex_t *lock)
920Sstevel@tonic-gate {
930Sstevel@tonic-gate 	if (_lwp_mutex_lock(lock) != 0) {
940Sstevel@tonic-gate 		output_err_message("bt_lock failed!!\n");
950Sstevel@tonic-gate 		(void) fprintf(stderr, "bindings.so: unable to obtain lock\n");
960Sstevel@tonic-gate 		perror("_lwp_mutex_lock");
970Sstevel@tonic-gate 	}
980Sstevel@tonic-gate }
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate static void
bt_unlock(lwp_mutex_t * lock)1010Sstevel@tonic-gate bt_unlock(lwp_mutex_t *lock)
1020Sstevel@tonic-gate {
1030Sstevel@tonic-gate 	if (_lwp_mutex_unlock(lock) != 0) {
1040Sstevel@tonic-gate 		output_err_message("bt_unlock failed!!\n");
1050Sstevel@tonic-gate 		(void) fprintf(stderr, "bindings.so: unable to unlock lock\n");
1060Sstevel@tonic-gate 		perror("_lwp_mutex_unlock");
1070Sstevel@tonic-gate 	}
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate /*
1130Sstevel@tonic-gate  * It's always possible that another process sharing our buffer
1140Sstevel@tonic-gate  * has caused it to grow.  If this is the case we must adjust our
1150Sstevel@tonic-gate  * mappings to compensate.
1160Sstevel@tonic-gate  */
1170Sstevel@tonic-gate static void
remap_buffer(int fd)1180Sstevel@tonic-gate remap_buffer(int fd)
1190Sstevel@tonic-gate {
1200Sstevel@tonic-gate 	void *	new_bhp;
1210Sstevel@tonic-gate 	if ((new_bhp = mmap(0, bhp->bh_size, PROT_READ | PROT_WRITE,
1220Sstevel@tonic-gate 	    MAP_SHARED, fd, 0)) == MAP_FAILED) {
1230Sstevel@tonic-gate 		(void) fprintf(stderr, "bindings: remap: mmap failed\n");
1240Sstevel@tonic-gate 		perror("mmap");
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 		bt_unlock(&bhp->bh_lock);
1270Sstevel@tonic-gate 		exit(1);
1280Sstevel@tonic-gate 	}
1290Sstevel@tonic-gate 	/*
1300Sstevel@tonic-gate 	 * clean up old mapping
1310Sstevel@tonic-gate 	 */
1320Sstevel@tonic-gate 	(void) munmap((caddr_t)bhp, current_map_len);
1330Sstevel@tonic-gate 	bhp = (bindhead *)new_bhp;
1340Sstevel@tonic-gate 	current_map_len = bhp->bh_size;
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate static void
grow_buffer(void)1384574Sraf grow_buffer(void)
1390Sstevel@tonic-gate {
1400Sstevel@tonic-gate 	int	fd;
1410Sstevel@tonic-gate 	if ((fd = open(buffer_name, O_RDWR)) == -1) {
1420Sstevel@tonic-gate 		(void) fprintf(stderr,
143*12927SRod.Evans@Sun.COM 		    "bidings: grow_buffer: open failed: %s\n", buffer_name);
1440Sstevel@tonic-gate 		perror("open");
1450Sstevel@tonic-gate 		bt_unlock(&bhp->bh_lock);
1460Sstevel@tonic-gate 		exit(1);
1470Sstevel@tonic-gate 	}
1480Sstevel@tonic-gate 	if (ftruncate(fd, bhp->bh_size + BLKSIZE) == -1) {
1490Sstevel@tonic-gate 		(void) fprintf(stderr, "grow_buffer failed\n");
1500Sstevel@tonic-gate 		perror("ftruncate");
1510Sstevel@tonic-gate 		bt_unlock(&bhp->bh_lock);
1520Sstevel@tonic-gate 		exit(1);
1530Sstevel@tonic-gate 	}
1540Sstevel@tonic-gate 	bhp->bh_size += BLKSIZE;
1550Sstevel@tonic-gate 	remap_buffer(fd);
1560Sstevel@tonic-gate 	(void) close(fd);
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate static void
get_new_strbuf(void)1604574Sraf get_new_strbuf(void)
1610Sstevel@tonic-gate {
1620Sstevel@tonic-gate 	bt_lock(&bhp->bh_lock);
1630Sstevel@tonic-gate 	while (bhp->bh_end + STRBLKSIZE > bhp->bh_size)
1640Sstevel@tonic-gate 		grow_buffer();
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	bhp->bh_strcur = bhp->bh_end;
1670Sstevel@tonic-gate 	bhp->bh_end = bhp->bh_strend = bhp->bh_strcur + STRBLKSIZE;
1680Sstevel@tonic-gate 	bt_unlock(&bhp->bh_lock);
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate static unsigned int
save_str(const char * str)1720Sstevel@tonic-gate save_str(const char *str)
1730Sstevel@tonic-gate {
1740Sstevel@tonic-gate 	char		*sptr;
1750Sstevel@tonic-gate 	unsigned int	bptr;
1760Sstevel@tonic-gate 	unsigned int	slen;
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 	bt_lock(&bhp->bh_strlock);
1790Sstevel@tonic-gate 	/* LINTED */
1800Sstevel@tonic-gate 	slen = (unsigned int)strlen(str);
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	/*
1830Sstevel@tonic-gate 	 * will string fit into our current string buffer?
1840Sstevel@tonic-gate 	 */
1850Sstevel@tonic-gate 	if ((slen + 1) > (bhp->bh_strend - bhp->bh_strcur))
1860Sstevel@tonic-gate 		get_new_strbuf();
1870Sstevel@tonic-gate 	bptr = bhp->bh_strcur;
1880Sstevel@tonic-gate 	sptr = (char *)bhp + bhp->bh_strcur;
1890Sstevel@tonic-gate 	bhp->bh_strcur += slen + 1;
1900Sstevel@tonic-gate 	(void) strncpy(sptr, str, slen);
1910Sstevel@tonic-gate 	sptr[slen] = '\0';
1920Sstevel@tonic-gate 	bt_unlock(&bhp->bh_strlock);
1930Sstevel@tonic-gate 	return (bptr);
1940Sstevel@tonic-gate }
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate static unsigned int
get_new_entry(void)1984574Sraf get_new_entry(void)
1990Sstevel@tonic-gate {
2000Sstevel@tonic-gate 	unsigned int	new_ent;
2010Sstevel@tonic-gate 	bt_lock(&bhp->bh_lock);
2020Sstevel@tonic-gate 	while ((sizeof (binding_entry) + bhp->bh_end) > bhp->bh_size)
2030Sstevel@tonic-gate 		grow_buffer();
2040Sstevel@tonic-gate 	new_ent = bhp->bh_end;
2050Sstevel@tonic-gate 	bhp->bh_end += sizeof (binding_entry);
2060Sstevel@tonic-gate 	bt_unlock(&bhp->bh_lock);
2070Sstevel@tonic-gate 	return (new_ent);
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate static void
init_locks(void)2134574Sraf init_locks(void)
2140Sstevel@tonic-gate {
2150Sstevel@tonic-gate 	int i;
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 	(void) memcpy(&bhp->bh_lock, &sharedmutex, sizeof (lwp_mutex_t));
2180Sstevel@tonic-gate 	for (i = 0; i < DEFBKTS; i++)
2190Sstevel@tonic-gate 		(void) memcpy(&bhp->bh_bkts[i].bb_lock, &sharedmutex,
2200Sstevel@tonic-gate 		    sizeof (lwp_mutex_t));
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	(void) memcpy(&bhp->bh_strlock, &sharedmutex, sizeof (lwp_mutex_t));
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate uint_t
la_version(uint_t version)2260Sstevel@tonic-gate la_version(uint_t version)
2270Sstevel@tonic-gate {
2280Sstevel@tonic-gate 	int	fd;
2290Sstevel@tonic-gate 	sigset_t	omask;
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	if (version < LAV_CURRENT) {
2320Sstevel@tonic-gate 		(void) fprintf(stderr,
233*12927SRod.Evans@Sun.COM 		    "bindings.so: unexpected link_audit version: %d\n",
234*12927SRod.Evans@Sun.COM 		    version);
2350Sstevel@tonic-gate 		return (0);
2360Sstevel@tonic-gate 	}
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 	build_env_list(&bindto_list, (const char *)"BT_BINDTO");
2390Sstevel@tonic-gate 	build_env_list(&bindfrom_list, (const char *)"BT_BINDFROM");
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	if ((buffer_name = getenv(FILEENV)) == NULL)
2420Sstevel@tonic-gate 		buffer_name = DEFFILE;
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	(void) sigprocmask(SIG_BLOCK, &iset, &omask);
2450Sstevel@tonic-gate 	if ((fd = open(buffer_name, O_RDWR | O_CREAT | O_EXCL, 0666)) != -1) {
2460Sstevel@tonic-gate 		int	init_size = sizeof (bindhead) + BLKSIZE;
247*12927SRod.Evans@Sun.COM 
2480Sstevel@tonic-gate 		if (ftruncate(fd, init_size) == -1) {
2490Sstevel@tonic-gate 			perror("ftruncate");
2500Sstevel@tonic-gate 			return (0);
2510Sstevel@tonic-gate 		}
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 		/* LINTED */
2540Sstevel@tonic-gate 		if ((bhp = (bindhead *)mmap(0, init_size,
2550Sstevel@tonic-gate 		    PROT_READ | PROT_WRITE,
2560Sstevel@tonic-gate 		    MAP_SHARED, fd, 0)) == MAP_FAILED) {
2570Sstevel@tonic-gate 			perror("bindings.so: mmap");
2580Sstevel@tonic-gate 			return (0);
2590Sstevel@tonic-gate 		}
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 		(void) close(fd);
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 		init_locks();
2640Sstevel@tonic-gate 		/*
2650Sstevel@tonic-gate 		 * Lock our structure and then initialize the data
2660Sstevel@tonic-gate 		 */
2670Sstevel@tonic-gate 		bt_lock(&bhp->bh_lock);
2680Sstevel@tonic-gate 		bhp->bh_vers = BINDCURVERS;
2690Sstevel@tonic-gate 		current_map_len = bhp->bh_size = init_size;
2700Sstevel@tonic-gate 		bhp->bh_end = sizeof (bindhead);
2710Sstevel@tonic-gate 		bhp->bh_bktcnt = DEFBKTS;
2720Sstevel@tonic-gate 		bt_unlock(&bhp->bh_lock);
2730Sstevel@tonic-gate 		/*
2740Sstevel@tonic-gate 		 * Set up our initial string buffer
2750Sstevel@tonic-gate 		 */
2760Sstevel@tonic-gate 		get_new_strbuf();
2770Sstevel@tonic-gate 	} else if ((fd = open(buffer_name, O_RDWR)) != -1) {
2780Sstevel@tonic-gate 		struct stat	stbuf;
2790Sstevel@tonic-gate 		int		i;
2800Sstevel@tonic-gate 		for (i = 0; i < 4; i++) {
2810Sstevel@tonic-gate 			if (fstat(fd, &stbuf) == -1) {
2820Sstevel@tonic-gate 				(void) sleep(1);
2830Sstevel@tonic-gate 				continue;
2840Sstevel@tonic-gate 			}
2850Sstevel@tonic-gate 			if (stbuf.st_size < sizeof (bindhead)) {
2860Sstevel@tonic-gate 				(void) sleep(1);
2870Sstevel@tonic-gate 				continue;
2880Sstevel@tonic-gate 			}
2890Sstevel@tonic-gate 			/* LINTED */
2900Sstevel@tonic-gate 			if ((bhp = (bindhead *)mmap(0, stbuf.st_size,
2910Sstevel@tonic-gate 			    PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) ==
2920Sstevel@tonic-gate 			    MAP_FAILED) {
2930Sstevel@tonic-gate 				(void) fprintf(stderr,
294*12927SRod.Evans@Sun.COM 				    "bindings: mmap failed\n");
2950Sstevel@tonic-gate 				perror("mmap");
2960Sstevel@tonic-gate 				return (0);
2970Sstevel@tonic-gate 			}
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 			/* LINTED */
3000Sstevel@tonic-gate 			current_map_len = (unsigned int)stbuf.st_size;
3010Sstevel@tonic-gate 		}
3020Sstevel@tonic-gate 		if (bhp == NULL) {
3030Sstevel@tonic-gate 			(void) fprintf(stderr,
304*12927SRod.Evans@Sun.COM 			    "bindings: buffer mapping timed out\n");
3050Sstevel@tonic-gate 			return (0);
3060Sstevel@tonic-gate 		}
3070Sstevel@tonic-gate 		for (i = 0; i < 4; i++) {
3080Sstevel@tonic-gate 			if (bhp->bh_vers == 0) {
3090Sstevel@tonic-gate 				(void) sleep(1);
3100Sstevel@tonic-gate 				continue;
3110Sstevel@tonic-gate 			}
3120Sstevel@tonic-gate 		}
3130Sstevel@tonic-gate 		if (bhp->bh_vers == 0) {
3140Sstevel@tonic-gate 			(void) fprintf(stderr,
315*12927SRod.Evans@Sun.COM 			    "bindings: %s not initialized\n", buffer_name);
3160Sstevel@tonic-gate 			return (0);
3170Sstevel@tonic-gate 		}
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 		bt_lock(&bhp->bh_lock);
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate 		if (bhp->bh_size != current_map_len)
3220Sstevel@tonic-gate 			remap_buffer(fd);
3230Sstevel@tonic-gate 		(void) close(fd);
3240Sstevel@tonic-gate 	} else {
3250Sstevel@tonic-gate 		(void) fprintf(stderr, "bindings: unable to open %s\n",
326*12927SRod.Evans@Sun.COM 		    buffer_name);
3270Sstevel@tonic-gate 		perror("open");
3280Sstevel@tonic-gate 		return (0);
3290Sstevel@tonic-gate 	}
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 	(void) sigprocmask(SIG_SETMASK, &omask, NULL);
3320Sstevel@tonic-gate 	bt_unlock(&bhp->bh_lock);
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	return (LAV_CURRENT);
3350Sstevel@tonic-gate }
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate /* ARGSUSED 0 */
3380Sstevel@tonic-gate uint_t
la_objopen(Link_map * lmp,Lmid_t lmid,uintptr_t * cookie)3390Sstevel@tonic-gate la_objopen(Link_map *lmp, Lmid_t lmid, uintptr_t *cookie)
3400Sstevel@tonic-gate {
3410Sstevel@tonic-gate 	uint_t	flags;
3420Sstevel@tonic-gate 
343*12927SRod.Evans@Sun.COM 	if ((bindto_list == NULL) ||
3440Sstevel@tonic-gate 	    (check_list(bindto_list, lmp->l_name)))
3450Sstevel@tonic-gate 		flags = LA_FLG_BINDTO;
3460Sstevel@tonic-gate 	else
3470Sstevel@tonic-gate 		flags = 0;
3480Sstevel@tonic-gate 
349*12927SRod.Evans@Sun.COM 	if ((bindfrom_list == NULL) ||
3500Sstevel@tonic-gate 	    (check_list(bindfrom_list, lmp->l_name)))
3510Sstevel@tonic-gate 		flags |= LA_FLG_BINDFROM;
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	return (flags);
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate /* ARGSUSED 1 */
3580Sstevel@tonic-gate #if	defined(__sparcv9)
3590Sstevel@tonic-gate uintptr_t
la_sparcv9_pltenter(Elf64_Sym * symp,uint_t symndx,uintptr_t * refcooke,uintptr_t * defcook,La_sparcv9_regs * regset,uint_t * sb_flags,const char * sym_name)3600Sstevel@tonic-gate la_sparcv9_pltenter(Elf64_Sym *symp, uint_t symndx, uintptr_t *refcooke,
3610Sstevel@tonic-gate 	uintptr_t *defcook, La_sparcv9_regs *regset, uint_t *sb_flags,
3620Sstevel@tonic-gate 	const char *sym_name)
3630Sstevel@tonic-gate #elif	defined(__sparc)
3640Sstevel@tonic-gate uintptr_t
3650Sstevel@tonic-gate la_sparcv8_pltenter(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcooke,
3660Sstevel@tonic-gate 	uintptr_t *defcook, La_sparcv8_regs *regset, uint_t *sb_flags)
3670Sstevel@tonic-gate #elif	defined(__amd64)
3680Sstevel@tonic-gate uintptr_t
3690Sstevel@tonic-gate la_amd64_pltenter(Elf64_Sym *symp, uint_t symndx, uintptr_t *refcooke,
3700Sstevel@tonic-gate 	uintptr_t *defcook, La_amd64_regs *regset, uint_t *sb_flags,
3710Sstevel@tonic-gate 	const char *sym_name)
3720Sstevel@tonic-gate #elif	defined(__i386)
3730Sstevel@tonic-gate uintptr_t
3740Sstevel@tonic-gate la_i86_pltenter(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcooke,
3750Sstevel@tonic-gate 	uintptr_t *defcook, La_i86_regs *regset, uint_t *sb_flags)
3760Sstevel@tonic-gate #endif
3770Sstevel@tonic-gate {
3780Sstevel@tonic-gate 	unsigned long	bktno;
3790Sstevel@tonic-gate 	Link_map	*dlmp = (Link_map *)*defcook;
3800Sstevel@tonic-gate 	const char	*lib_name;
3810Sstevel@tonic-gate 	sigset_t	omask;
3820Sstevel@tonic-gate #if	!defined(_LP64)
3830Sstevel@tonic-gate 	const char	*sym_name = (const char *)symp->st_name;
3840Sstevel@tonic-gate #endif
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	lib_name = dlmp->l_name;
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 	(void) sigprocmask(SIG_BLOCK, &iset, &omask);
390*12927SRod.Evans@Sun.COM 	if (sym_name == NULL) {
3910Sstevel@tonic-gate 		output_err_message("null symname\n");
3920Sstevel@tonic-gate 		return (symp->st_value);
3930Sstevel@tonic-gate 	}
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 	bktno = ehash(sym_name) % bhp->bh_bktcnt;
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	bt_lock(&bhp->bh_bkts[bktno].bb_lock);
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	/*
4000Sstevel@tonic-gate 	 * The buffer has been grown (by another process) and
4010Sstevel@tonic-gate 	 * we need to remap it into memory.
4020Sstevel@tonic-gate 	 */
4030Sstevel@tonic-gate 	if (bhp->bh_size != current_map_len) {
4040Sstevel@tonic-gate 		int fd;
4050Sstevel@tonic-gate 		if ((fd = open(buffer_name, O_RDWR)) == -1) {
4060Sstevel@tonic-gate 			(void) fprintf(stderr,
4070Sstevel@tonic-gate 				"bidings: plt_enter: open failed: %s\n",
4080Sstevel@tonic-gate 				buffer_name);
4090Sstevel@tonic-gate 			perror("open");
4100Sstevel@tonic-gate 			bt_unlock(&bhp->bh_lock);
4110Sstevel@tonic-gate 			exit(1);
4120Sstevel@tonic-gate 		}
4130Sstevel@tonic-gate 		bt_lock(&bhp->bh_lock);
4140Sstevel@tonic-gate 		remap_buffer(fd);
4150Sstevel@tonic-gate 		bt_unlock(&bhp->bh_lock);
4160Sstevel@tonic-gate 		(void) close(fd);
4170Sstevel@tonic-gate 	}
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	if (bhp->bh_bkts[bktno].bb_head == NULL) {
4200Sstevel@tonic-gate 		binding_entry *	bep;
4210Sstevel@tonic-gate 		unsigned int	be_off;
4220Sstevel@tonic-gate 		unsigned int	sym_off;
4230Sstevel@tonic-gate 		unsigned int	lib_off;
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 		be_off = get_new_entry();
4260Sstevel@tonic-gate 		sym_off = save_str(sym_name);
4270Sstevel@tonic-gate 		lib_off = save_str(lib_name);
4280Sstevel@tonic-gate 		/* LINTED */
4290Sstevel@tonic-gate 		bep = (binding_entry *)((char *)bhp + be_off);
4300Sstevel@tonic-gate 		bep->be_next = 0;
4310Sstevel@tonic-gate 		bep->be_sym_name = sym_off;
4320Sstevel@tonic-gate 		bep->be_lib_name = lib_off;
4330Sstevel@tonic-gate 		bep->be_count = 1;
4340Sstevel@tonic-gate 		bhp->bh_bkts[bktno].bb_head = be_off;
4350Sstevel@tonic-gate 	} else {
4360Sstevel@tonic-gate 		int		strcmp_res;
4370Sstevel@tonic-gate 		unsigned int	prev_off = 0;
438*12927SRod.Evans@Sun.COM 		binding_entry	*prev_bep = NULL;
4390Sstevel@tonic-gate 		unsigned int	cur_off;
440*12927SRod.Evans@Sun.COM 		binding_entry	*cur_bep;
4410Sstevel@tonic-gate 		unsigned int	lib_off = 0;
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 		/*
4440Sstevel@tonic-gate 		 * Once we get to the bucket, we do a two tiered
4450Sstevel@tonic-gate 		 * search.  First we search for a library match, then
4460Sstevel@tonic-gate 		 * we search for a symbol match.
4470Sstevel@tonic-gate 		 */
4480Sstevel@tonic-gate 		cur_off = bhp->bh_bkts[bktno].bb_head;
4490Sstevel@tonic-gate 		/* LINTED */
4500Sstevel@tonic-gate 		cur_bep = (binding_entry *)((char *)bhp +
4510Sstevel@tonic-gate 			cur_off);
4520Sstevel@tonic-gate 		while (cur_off && (strcmp_res = strcmp((char *)bhp +
4530Sstevel@tonic-gate 		    cur_bep->be_lib_name, lib_name)) < 0) {
4540Sstevel@tonic-gate 			prev_off = cur_off;
4550Sstevel@tonic-gate 			cur_off = cur_bep->be_next;
4560Sstevel@tonic-gate 			/* LINTED */
4570Sstevel@tonic-gate 			cur_bep = (binding_entry *)((char *)bhp +
4580Sstevel@tonic-gate 				cur_off);
4590Sstevel@tonic-gate 		}
4600Sstevel@tonic-gate 		if (cur_off && (strcmp_res == 0)) {
4610Sstevel@tonic-gate 			/*
4620Sstevel@tonic-gate 			 * This is a small optimization.  For
4630Sstevel@tonic-gate 			 * each bucket we will only record a library
4640Sstevel@tonic-gate 			 * name once.  Once it has been recorded in
4650Sstevel@tonic-gate 			 * a bucket we will just re-use the same
4660Sstevel@tonic-gate 			 * string.
4670Sstevel@tonic-gate 			 */
4680Sstevel@tonic-gate 			lib_off = cur_bep->be_lib_name;
4690Sstevel@tonic-gate 			while (cur_off && (strcmp_res = strcmp((char *)bhp +
4700Sstevel@tonic-gate 			    cur_bep->be_sym_name, sym_name)) < 0) {
4710Sstevel@tonic-gate 				prev_off = cur_off;
4720Sstevel@tonic-gate 				cur_off = cur_bep->be_next;
4730Sstevel@tonic-gate 				/* LINTED */
4740Sstevel@tonic-gate 				cur_bep = (binding_entry *)((char *)bhp +
4750Sstevel@tonic-gate 					cur_off);
4760Sstevel@tonic-gate 			}
4770Sstevel@tonic-gate 		}
4780Sstevel@tonic-gate 		if (strcmp_res == 0) {
4790Sstevel@tonic-gate 			/*
4800Sstevel@tonic-gate 			 * We've got a match
4810Sstevel@tonic-gate 			 */
4820Sstevel@tonic-gate 			cur_bep->be_count++;
4830Sstevel@tonic-gate 		} else {
4840Sstevel@tonic-gate 			unsigned int	new_off;
4850Sstevel@tonic-gate 			binding_entry *	new_bep;
4860Sstevel@tonic-gate 			unsigned int	sym_off;
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 			new_off = get_new_entry();
4890Sstevel@tonic-gate 			if (lib_off == 0)
4900Sstevel@tonic-gate 				lib_off = save_str(lib_name);
4910Sstevel@tonic-gate 			sym_off = save_str(sym_name);
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate 			/* LINTED */
4940Sstevel@tonic-gate 			new_bep = (binding_entry *)((char *)bhp +
4950Sstevel@tonic-gate 				new_off);
4960Sstevel@tonic-gate 			new_bep->be_sym_name = sym_off;
4970Sstevel@tonic-gate 			new_bep->be_lib_name = lib_off;
4980Sstevel@tonic-gate 			new_bep->be_count = 1;
4990Sstevel@tonic-gate 			new_bep->be_next = cur_off;
5000Sstevel@tonic-gate 			if (prev_off) {
5010Sstevel@tonic-gate 				/* LINTED */
5020Sstevel@tonic-gate 				prev_bep = (binding_entry *)((char *)bhp +
5030Sstevel@tonic-gate 					prev_off);
5040Sstevel@tonic-gate 				prev_bep->be_next = new_off;
5050Sstevel@tonic-gate 			} else
5060Sstevel@tonic-gate 				/*
5070Sstevel@tonic-gate 				 * Insert at head of list.
5080Sstevel@tonic-gate 				 */
5090Sstevel@tonic-gate 				bhp->bh_bkts[bktno].bb_head = new_off;
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate 		}
5120Sstevel@tonic-gate 	}
5130Sstevel@tonic-gate 	bt_unlock(&bhp->bh_bkts[bktno].bb_lock);
5140Sstevel@tonic-gate 	(void) sigprocmask(SIG_SETMASK, &omask, NULL);
5150Sstevel@tonic-gate 	return (symp->st_value);
5160Sstevel@tonic-gate }
517