17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5883492d5Sraf  * Common Development and Distribution License (the "License").
6883492d5Sraf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21883492d5Sraf 
227c478bd9Sstevel@tonic-gate /*
2320c1c355SRod Evans  * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate #include	<link.h>
267c478bd9Sstevel@tonic-gate #include	<stdlib.h>
277c478bd9Sstevel@tonic-gate #include	<unistd.h>
287c478bd9Sstevel@tonic-gate #include	<sys/types.h>
297c478bd9Sstevel@tonic-gate #include	<sys/stat.h>
307c478bd9Sstevel@tonic-gate #include	<sys/regset.h>
317c478bd9Sstevel@tonic-gate #include	<sys/frame.h>
327c478bd9Sstevel@tonic-gate #include	<sys/lwp.h>
337c478bd9Sstevel@tonic-gate #include	<fcntl.h>
347c478bd9Sstevel@tonic-gate #include	<stdio.h>
357c478bd9Sstevel@tonic-gate #include	<sys/mman.h>
367c478bd9Sstevel@tonic-gate #include	<errno.h>
377c478bd9Sstevel@tonic-gate #include	<signal.h>
387c478bd9Sstevel@tonic-gate #include	<synch.h>
397c478bd9Sstevel@tonic-gate #include	<string.h>
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #include	"bindings.h"
427c478bd9Sstevel@tonic-gate #include	"env.h"
437c478bd9Sstevel@tonic-gate 
4420c1c355SRod Evans static Elist		*bindto_list = NULL;
4520c1c355SRod Evans static Elist		*bindfrom_list = NULL;
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate static bindhead		*bhp = NULL;
487c478bd9Sstevel@tonic-gate static unsigned int	current_map_len = 0;
497c478bd9Sstevel@tonic-gate static char		*buffer_name;
507c478bd9Sstevel@tonic-gate static const sigset_t	iset = { ~0U, ~0U, ~0U, ~0U };
517c478bd9Sstevel@tonic-gate static lwp_mutex_t	sharedmutex = SHAREDMUTEX;
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate /*
547c478bd9Sstevel@tonic-gate  * This routine was stolen from libelf.so.1
557c478bd9Sstevel@tonic-gate  */
567c478bd9Sstevel@tonic-gate static unsigned long
ehash(const char * name)577c478bd9Sstevel@tonic-gate ehash(const char *name)
587c478bd9Sstevel@tonic-gate {
5920c1c355SRod Evans 	unsigned int		g, h = 0;
6020c1c355SRod Evans 	const unsigned char	*nm = (unsigned char *)name;
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate 	while (*nm != '\0') {
637c478bd9Sstevel@tonic-gate 		h = (h << 4) + *nm++;
647c478bd9Sstevel@tonic-gate 		/* LINTED */
657c478bd9Sstevel@tonic-gate 		if ((g = (unsigned int)(h & MASK)) != 0)
667c478bd9Sstevel@tonic-gate 			h ^= g >> 24;
677c478bd9Sstevel@tonic-gate 		h &= ~MASK;
687c478bd9Sstevel@tonic-gate 	}
697c478bd9Sstevel@tonic-gate 	return ((unsigned long)h);
707c478bd9Sstevel@tonic-gate }
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate static void
output_err_message(const char * msg)747c478bd9Sstevel@tonic-gate output_err_message(const char *msg)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate 	int fd;
777c478bd9Sstevel@tonic-gate 	if ((fd = open("/tmp/bind_err", O_RDWR | O_CREAT, 0666)) == -1) {
787c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "bindings.so: unable to open err_log\n");
797c478bd9Sstevel@tonic-gate 		perror("open");
807c478bd9Sstevel@tonic-gate 	}
817c478bd9Sstevel@tonic-gate 	(void) lseek(fd, 0, SEEK_END);
827c478bd9Sstevel@tonic-gate 	(void) write(fd, msg, strlen(msg));
837c478bd9Sstevel@tonic-gate 	(void) close(fd);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * common mutex locking & unlocking routines for this module.  This is to
887c478bd9Sstevel@tonic-gate  * control the setting of 'lock_held'.
897c478bd9Sstevel@tonic-gate  */
907c478bd9Sstevel@tonic-gate static void
bt_lock(lwp_mutex_t * lock)917c478bd9Sstevel@tonic-gate bt_lock(lwp_mutex_t *lock)
927c478bd9Sstevel@tonic-gate {
937c478bd9Sstevel@tonic-gate 	if (_lwp_mutex_lock(lock) != 0) {
947c478bd9Sstevel@tonic-gate 		output_err_message("bt_lock failed!!\n");
957c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "bindings.so: unable to obtain lock\n");
967c478bd9Sstevel@tonic-gate 		perror("_lwp_mutex_lock");
977c478bd9Sstevel@tonic-gate 	}
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate static void
bt_unlock(lwp_mutex_t * lock)1017c478bd9Sstevel@tonic-gate bt_unlock(lwp_mutex_t *lock)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate 	if (_lwp_mutex_unlock(lock) != 0) {
1047c478bd9Sstevel@tonic-gate 		output_err_message("bt_unlock failed!!\n");
1057c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "bindings.so: unable to unlock lock\n");
1067c478bd9Sstevel@tonic-gate 		perror("_lwp_mutex_unlock");
1077c478bd9Sstevel@tonic-gate 	}
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate  * It's always possible that another process sharing our buffer
1147c478bd9Sstevel@tonic-gate  * has caused it to grow.  If this is the case we must adjust our
1157c478bd9Sstevel@tonic-gate  * mappings to compensate.
1167c478bd9Sstevel@tonic-gate  */
1177c478bd9Sstevel@tonic-gate static void
remap_buffer(int fd)1187c478bd9Sstevel@tonic-gate remap_buffer(int fd)
1197c478bd9Sstevel@tonic-gate {
1207c478bd9Sstevel@tonic-gate 	void *	new_bhp;
1217c478bd9Sstevel@tonic-gate 	if ((new_bhp = mmap(0, bhp->bh_size, PROT_READ | PROT_WRITE,
1227c478bd9Sstevel@tonic-gate 	    MAP_SHARED, fd, 0)) == MAP_FAILED) {
1237c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "bindings: remap: mmap failed\n");
1247c478bd9Sstevel@tonic-gate 		perror("mmap");
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 		bt_unlock(&bhp->bh_lock);
1277c478bd9Sstevel@tonic-gate 		exit(1);
1287c478bd9Sstevel@tonic-gate 	}
1297c478bd9Sstevel@tonic-gate 	/*
1307c478bd9Sstevel@tonic-gate 	 * clean up old mapping
1317c478bd9Sstevel@tonic-gate 	 */
1327c478bd9Sstevel@tonic-gate 	(void) munmap((caddr_t)bhp, current_map_len);
1337c478bd9Sstevel@tonic-gate 	bhp = (bindhead *)new_bhp;
1347c478bd9Sstevel@tonic-gate 	current_map_len = bhp->bh_size;
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate static void
grow_buffer(void)138883492d5Sraf grow_buffer(void)
1397c478bd9Sstevel@tonic-gate {
1407c478bd9Sstevel@tonic-gate 	int	fd;
1417c478bd9Sstevel@tonic-gate 	if ((fd = open(buffer_name, O_RDWR)) == -1) {
1427c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
14320c1c355SRod Evans 		    "bidings: grow_buffer: open failed: %s\n", buffer_name);
1447c478bd9Sstevel@tonic-gate 		perror("open");
1457c478bd9Sstevel@tonic-gate 		bt_unlock(&bhp->bh_lock);
1467c478bd9Sstevel@tonic-gate 		exit(1);
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 	if (ftruncate(fd, bhp->bh_size + BLKSIZE) == -1) {
1497c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "grow_buffer failed\n");
1507c478bd9Sstevel@tonic-gate 		perror("ftruncate");
1517c478bd9Sstevel@tonic-gate 		bt_unlock(&bhp->bh_lock);
1527c478bd9Sstevel@tonic-gate 		exit(1);
1537c478bd9Sstevel@tonic-gate 	}
1547c478bd9Sstevel@tonic-gate 	bhp->bh_size += BLKSIZE;
1557c478bd9Sstevel@tonic-gate 	remap_buffer(fd);
1567c478bd9Sstevel@tonic-gate 	(void) close(fd);
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate static void
get_new_strbuf(void)160883492d5Sraf get_new_strbuf(void)
1617c478bd9Sstevel@tonic-gate {
1627c478bd9Sstevel@tonic-gate 	bt_lock(&bhp->bh_lock);
1637c478bd9Sstevel@tonic-gate 	while (bhp->bh_end + STRBLKSIZE > bhp->bh_size)
1647c478bd9Sstevel@tonic-gate 		grow_buffer();
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	bhp->bh_strcur = bhp->bh_end;
1677c478bd9Sstevel@tonic-gate 	bhp->bh_end = bhp->bh_strend = bhp->bh_strcur + STRBLKSIZE;
1687c478bd9Sstevel@tonic-gate 	bt_unlock(&bhp->bh_lock);
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate static unsigned int
save_str(const char * str)1727c478bd9Sstevel@tonic-gate save_str(const char *str)
1737c478bd9Sstevel@tonic-gate {
1747c478bd9Sstevel@tonic-gate 	char		*sptr;
1757c478bd9Sstevel@tonic-gate 	unsigned int	bptr;
1767c478bd9Sstevel@tonic-gate 	unsigned int	slen;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	bt_lock(&bhp->bh_strlock);
1797c478bd9Sstevel@tonic-gate 	/* LINTED */
1807c478bd9Sstevel@tonic-gate 	slen = (unsigned int)strlen(str);
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	/*
1837c478bd9Sstevel@tonic-gate 	 * will string fit into our current string buffer?
1847c478bd9Sstevel@tonic-gate 	 */
1857c478bd9Sstevel@tonic-gate 	if ((slen + 1) > (bhp->bh_strend - bhp->bh_strcur))
1867c478bd9Sstevel@tonic-gate 		get_new_strbuf();
1877c478bd9Sstevel@tonic-gate 	bptr = bhp->bh_strcur;
1887c478bd9Sstevel@tonic-gate 	sptr = (char *)bhp + bhp->bh_strcur;
1897c478bd9Sstevel@tonic-gate 	bhp->bh_strcur += slen + 1;
1907c478bd9Sstevel@tonic-gate 	(void) strncpy(sptr, str, slen);
1917c478bd9Sstevel@tonic-gate 	sptr[slen] = '\0';
1927c478bd9Sstevel@tonic-gate 	bt_unlock(&bhp->bh_strlock);
1937c478bd9Sstevel@tonic-gate 	return (bptr);
1947c478bd9Sstevel@tonic-gate }
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate static unsigned int
get_new_entry(void)198883492d5Sraf get_new_entry(void)
1997c478bd9Sstevel@tonic-gate {
2007c478bd9Sstevel@tonic-gate 	unsigned int	new_ent;
2017c478bd9Sstevel@tonic-gate 	bt_lock(&bhp->bh_lock);
2027c478bd9Sstevel@tonic-gate 	while ((sizeof (binding_entry) + bhp->bh_end) > bhp->bh_size)
2037c478bd9Sstevel@tonic-gate 		grow_buffer();
2047c478bd9Sstevel@tonic-gate 	new_ent = bhp->bh_end;
2057c478bd9Sstevel@tonic-gate 	bhp->bh_end += sizeof (binding_entry);
2067c478bd9Sstevel@tonic-gate 	bt_unlock(&bhp->bh_lock);
2077c478bd9Sstevel@tonic-gate 	return (new_ent);
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate static void
init_locks(void)213883492d5Sraf init_locks(void)
2147c478bd9Sstevel@tonic-gate {
2157c478bd9Sstevel@tonic-gate 	int i;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	(void) memcpy(&bhp->bh_lock, &sharedmutex, sizeof (lwp_mutex_t));
2187c478bd9Sstevel@tonic-gate 	for (i = 0; i < DEFBKTS; i++)
2197c478bd9Sstevel@tonic-gate 		(void) memcpy(&bhp->bh_bkts[i].bb_lock, &sharedmutex,
2207c478bd9Sstevel@tonic-gate 		    sizeof (lwp_mutex_t));
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	(void) memcpy(&bhp->bh_strlock, &sharedmutex, sizeof (lwp_mutex_t));
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate uint_t
la_version(uint_t version)2267c478bd9Sstevel@tonic-gate la_version(uint_t version)
2277c478bd9Sstevel@tonic-gate {
2287c478bd9Sstevel@tonic-gate 	int	fd;
2297c478bd9Sstevel@tonic-gate 	sigset_t	omask;
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	if (version < LAV_CURRENT) {
2327c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
23320c1c355SRod Evans 		    "bindings.so: unexpected link_audit version: %d\n",
23420c1c355SRod Evans 		    version);
2357c478bd9Sstevel@tonic-gate 		return (0);
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	build_env_list(&bindto_list, (const char *)"BT_BINDTO");
2397c478bd9Sstevel@tonic-gate 	build_env_list(&bindfrom_list, (const char *)"BT_BINDFROM");
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	if ((buffer_name = getenv(FILEENV)) == NULL)
2427c478bd9Sstevel@tonic-gate 		buffer_name = DEFFILE;
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	(void) sigprocmask(SIG_BLOCK, &iset, &omask);
2457c478bd9Sstevel@tonic-gate 	if ((fd = open(buffer_name, O_RDWR | O_CREAT | O_EXCL, 0666)) != -1) {
2467c478bd9Sstevel@tonic-gate 		int	init_size = sizeof (bindhead) + BLKSIZE;
24720c1c355SRod Evans 
2487c478bd9Sstevel@tonic-gate 		if (ftruncate(fd, init_size) == -1) {
2497c478bd9Sstevel@tonic-gate 			perror("ftruncate");
2507c478bd9Sstevel@tonic-gate 			return (0);
2517c478bd9Sstevel@tonic-gate 		}
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 		/* LINTED */
2547c478bd9Sstevel@tonic-gate 		if ((bhp = (bindhead *)mmap(0, init_size,
2557c478bd9Sstevel@tonic-gate 		    PROT_READ | PROT_WRITE,
2567c478bd9Sstevel@tonic-gate 		    MAP_SHARED, fd, 0)) == MAP_FAILED) {
2577c478bd9Sstevel@tonic-gate 			perror("bindings.so: mmap");
2587c478bd9Sstevel@tonic-gate 			return (0);
2597c478bd9Sstevel@tonic-gate 		}
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 		(void) close(fd);
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 		init_locks();
2647c478bd9Sstevel@tonic-gate 		/*
2657c478bd9Sstevel@tonic-gate 		 * Lock our structure and then initialize the data
2667c478bd9Sstevel@tonic-gate 		 */
2677c478bd9Sstevel@tonic-gate 		bt_lock(&bhp->bh_lock);
2687c478bd9Sstevel@tonic-gate 		bhp->bh_vers = BINDCURVERS;
2697c478bd9Sstevel@tonic-gate 		current_map_len = bhp->bh_size = init_size;
2707c478bd9Sstevel@tonic-gate 		bhp->bh_end = sizeof (bindhead);
2717c478bd9Sstevel@tonic-gate 		bhp->bh_bktcnt = DEFBKTS;
2727c478bd9Sstevel@tonic-gate 		bt_unlock(&bhp->bh_lock);
2737c478bd9Sstevel@tonic-gate 		/*
2747c478bd9Sstevel@tonic-gate 		 * Set up our initial string buffer
2757c478bd9Sstevel@tonic-gate 		 */
2767c478bd9Sstevel@tonic-gate 		get_new_strbuf();
2777c478bd9Sstevel@tonic-gate 	} else if ((fd = open(buffer_name, O_RDWR)) != -1) {
2787c478bd9Sstevel@tonic-gate 		struct stat	stbuf;
2797c478bd9Sstevel@tonic-gate 		int		i;
2807c478bd9Sstevel@tonic-gate 		for (i = 0; i < 4; i++) {
2817c478bd9Sstevel@tonic-gate 			if (fstat(fd, &stbuf) == -1) {
2827c478bd9Sstevel@tonic-gate 				(void) sleep(1);
2837c478bd9Sstevel@tonic-gate 				continue;
2847c478bd9Sstevel@tonic-gate 			}
2857c478bd9Sstevel@tonic-gate 			if (stbuf.st_size < sizeof (bindhead)) {
2867c478bd9Sstevel@tonic-gate 				(void) sleep(1);
2877c478bd9Sstevel@tonic-gate 				continue;
2887c478bd9Sstevel@tonic-gate 			}
2897c478bd9Sstevel@tonic-gate 			/* LINTED */
2907c478bd9Sstevel@tonic-gate 			if ((bhp = (bindhead *)mmap(0, stbuf.st_size,
2917c478bd9Sstevel@tonic-gate 			    PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) ==
2927c478bd9Sstevel@tonic-gate 			    MAP_FAILED) {
2937c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
29420c1c355SRod Evans 				    "bindings: mmap failed\n");
2957c478bd9Sstevel@tonic-gate 				perror("mmap");
2967c478bd9Sstevel@tonic-gate 				return (0);
2977c478bd9Sstevel@tonic-gate 			}
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 			/* LINTED */
3007c478bd9Sstevel@tonic-gate 			current_map_len = (unsigned int)stbuf.st_size;
3017c478bd9Sstevel@tonic-gate 		}
3027c478bd9Sstevel@tonic-gate 		if (bhp == NULL) {
3037c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
30420c1c355SRod Evans 			    "bindings: buffer mapping timed out\n");
3057c478bd9Sstevel@tonic-gate 			return (0);
3067c478bd9Sstevel@tonic-gate 		}
3077c478bd9Sstevel@tonic-gate 		for (i = 0; i < 4; i++) {
3087c478bd9Sstevel@tonic-gate 			if (bhp->bh_vers == 0) {
3097c478bd9Sstevel@tonic-gate 				(void) sleep(1);
3107c478bd9Sstevel@tonic-gate 				continue;
3117c478bd9Sstevel@tonic-gate 			}
3127c478bd9Sstevel@tonic-gate 		}
3137c478bd9Sstevel@tonic-gate 		if (bhp->bh_vers == 0) {
3147c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
31520c1c355SRod Evans 			    "bindings: %s not initialized\n", buffer_name);
3167c478bd9Sstevel@tonic-gate 			return (0);
3177c478bd9Sstevel@tonic-gate 		}
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 		bt_lock(&bhp->bh_lock);
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 		if (bhp->bh_size != current_map_len)
3227c478bd9Sstevel@tonic-gate 			remap_buffer(fd);
3237c478bd9Sstevel@tonic-gate 		(void) close(fd);
3247c478bd9Sstevel@tonic-gate 	} else {
3257c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "bindings: unable to open %s\n",
32620c1c355SRod Evans 		    buffer_name);
3277c478bd9Sstevel@tonic-gate 		perror("open");
3287c478bd9Sstevel@tonic-gate 		return (0);
3297c478bd9Sstevel@tonic-gate 	}
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	(void) sigprocmask(SIG_SETMASK, &omask, NULL);
3327c478bd9Sstevel@tonic-gate 	bt_unlock(&bhp->bh_lock);
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	return (LAV_CURRENT);
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate /* ARGSUSED 0 */
3387c478bd9Sstevel@tonic-gate uint_t
la_objopen(Link_map * lmp,Lmid_t lmid,uintptr_t * cookie)3397c478bd9Sstevel@tonic-gate la_objopen(Link_map *lmp, Lmid_t lmid, uintptr_t *cookie)
3407c478bd9Sstevel@tonic-gate {
3417c478bd9Sstevel@tonic-gate 	uint_t	flags;
3427c478bd9Sstevel@tonic-gate 
34320c1c355SRod Evans 	if ((bindto_list == NULL) ||
3447c478bd9Sstevel@tonic-gate 	    (check_list(bindto_list, lmp->l_name)))
3457c478bd9Sstevel@tonic-gate 		flags = LA_FLG_BINDTO;
3467c478bd9Sstevel@tonic-gate 	else
3477c478bd9Sstevel@tonic-gate 		flags = 0;
3487c478bd9Sstevel@tonic-gate 
34920c1c355SRod Evans 	if ((bindfrom_list == NULL) ||
3507c478bd9Sstevel@tonic-gate 	    (check_list(bindfrom_list, lmp->l_name)))
3517c478bd9Sstevel@tonic-gate 		flags |= LA_FLG_BINDFROM;
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	return (flags);
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate /* ARGSUSED 1 */
3587c478bd9Sstevel@tonic-gate #if	defined(__sparcv9)
3597c478bd9Sstevel@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)3607c478bd9Sstevel@tonic-gate la_sparcv9_pltenter(Elf64_Sym *symp, uint_t symndx, uintptr_t *refcooke,
3617c478bd9Sstevel@tonic-gate 	uintptr_t *defcook, La_sparcv9_regs *regset, uint_t *sb_flags,
3627c478bd9Sstevel@tonic-gate 	const char *sym_name)
3637c478bd9Sstevel@tonic-gate #elif	defined(__sparc)
3647c478bd9Sstevel@tonic-gate uintptr_t
3657c478bd9Sstevel@tonic-gate la_sparcv8_pltenter(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcooke,
3667c478bd9Sstevel@tonic-gate 	uintptr_t *defcook, La_sparcv8_regs *regset, uint_t *sb_flags)
3677c478bd9Sstevel@tonic-gate #elif	defined(__amd64)
3687c478bd9Sstevel@tonic-gate uintptr_t
3697c478bd9Sstevel@tonic-gate la_amd64_pltenter(Elf64_Sym *symp, uint_t symndx, uintptr_t *refcooke,
3707c478bd9Sstevel@tonic-gate 	uintptr_t *defcook, La_amd64_regs *regset, uint_t *sb_flags,
3717c478bd9Sstevel@tonic-gate 	const char *sym_name)
3727c478bd9Sstevel@tonic-gate #elif	defined(__i386)
3737c478bd9Sstevel@tonic-gate uintptr_t
3747c478bd9Sstevel@tonic-gate la_i86_pltenter(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcooke,
3757c478bd9Sstevel@tonic-gate 	uintptr_t *defcook, La_i86_regs *regset, uint_t *sb_flags)
3767c478bd9Sstevel@tonic-gate #endif
3777c478bd9Sstevel@tonic-gate {
3787c478bd9Sstevel@tonic-gate 	unsigned long	bktno;
3797c478bd9Sstevel@tonic-gate 	Link_map	*dlmp = (Link_map *)*defcook;
3807c478bd9Sstevel@tonic-gate 	const char	*lib_name;
3817c478bd9Sstevel@tonic-gate 	sigset_t	omask;
3827c478bd9Sstevel@tonic-gate #if	!defined(_LP64)
3837c478bd9Sstevel@tonic-gate 	const char	*sym_name = (const char *)symp->st_name;
3847c478bd9Sstevel@tonic-gate #endif
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	lib_name = dlmp->l_name;
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	(void) sigprocmask(SIG_BLOCK, &iset, &omask);
39020c1c355SRod Evans 	if (sym_name == NULL) {
3917c478bd9Sstevel@tonic-gate 		output_err_message("null symname\n");
3927c478bd9Sstevel@tonic-gate 		return (symp->st_value);
3937c478bd9Sstevel@tonic-gate 	}
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	bktno = ehash(sym_name) % bhp->bh_bktcnt;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	bt_lock(&bhp->bh_bkts[bktno].bb_lock);
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	/*
4007c478bd9Sstevel@tonic-gate 	 * The buffer has been grown (by another process) and
4017c478bd9Sstevel@tonic-gate 	 * we need to remap it into memory.
4027c478bd9Sstevel@tonic-gate 	 */
4037c478bd9Sstevel@tonic-gate 	if (bhp->bh_size != current_map_len) {
4047c478bd9Sstevel@tonic-gate 		int fd;
4057c478bd9Sstevel@tonic-gate 		if ((fd = open(buffer_name, O_RDWR)) == -1) {
4067c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
4077c478bd9Sstevel@tonic-gate 				"bidings: plt_enter: open failed: %s\n",
4087c478bd9Sstevel@tonic-gate 				buffer_name);
4097c478bd9Sstevel@tonic-gate 			perror("open");
4107c478bd9Sstevel@tonic-gate 			bt_unlock(&bhp->bh_lock);
4117c478bd9Sstevel@tonic-gate 			exit(1);
4127c478bd9Sstevel@tonic-gate 		}
4137c478bd9Sstevel@tonic-gate 		bt_lock(&bhp->bh_lock);
4147c478bd9Sstevel@tonic-gate 		remap_buffer(fd);
4157c478bd9Sstevel@tonic-gate 		bt_unlock(&bhp->bh_lock);
4167c478bd9Sstevel@tonic-gate 		(void) close(fd);
4177c478bd9Sstevel@tonic-gate 	}
4187c478bd9Sstevel@tonic-gate 
419*e2294b84SToomas Soome 	if (bhp->bh_bkts[bktno].bb_head == 0) {
4207c478bd9Sstevel@tonic-gate 		binding_entry *	bep;
4217c478bd9Sstevel@tonic-gate 		unsigned int	be_off;
4227c478bd9Sstevel@tonic-gate 		unsigned int	sym_off;
4237c478bd9Sstevel@tonic-gate 		unsigned int	lib_off;
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 		be_off = get_new_entry();
4267c478bd9Sstevel@tonic-gate 		sym_off = save_str(sym_name);
4277c478bd9Sstevel@tonic-gate 		lib_off = save_str(lib_name);
4287c478bd9Sstevel@tonic-gate 		/* LINTED */
4297c478bd9Sstevel@tonic-gate 		bep = (binding_entry *)((char *)bhp + be_off);
4307c478bd9Sstevel@tonic-gate 		bep->be_next = 0;
4317c478bd9Sstevel@tonic-gate 		bep->be_sym_name = sym_off;
4327c478bd9Sstevel@tonic-gate 		bep->be_lib_name = lib_off;
4337c478bd9Sstevel@tonic-gate 		bep->be_count = 1;
4347c478bd9Sstevel@tonic-gate 		bhp->bh_bkts[bktno].bb_head = be_off;
4357c478bd9Sstevel@tonic-gate 	} else {
4367c478bd9Sstevel@tonic-gate 		int		strcmp_res;
4377c478bd9Sstevel@tonic-gate 		unsigned int	prev_off = 0;
43820c1c355SRod Evans 		binding_entry	*prev_bep = NULL;
4397c478bd9Sstevel@tonic-gate 		unsigned int	cur_off;
44020c1c355SRod Evans 		binding_entry	*cur_bep;
4417c478bd9Sstevel@tonic-gate 		unsigned int	lib_off = 0;
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 		/*
4447c478bd9Sstevel@tonic-gate 		 * Once we get to the bucket, we do a two tiered
4457c478bd9Sstevel@tonic-gate 		 * search.  First we search for a library match, then
4467c478bd9Sstevel@tonic-gate 		 * we search for a symbol match.
4477c478bd9Sstevel@tonic-gate 		 */
4487c478bd9Sstevel@tonic-gate 		cur_off = bhp->bh_bkts[bktno].bb_head;
4497c478bd9Sstevel@tonic-gate 		/* LINTED */
4507c478bd9Sstevel@tonic-gate 		cur_bep = (binding_entry *)((char *)bhp +
4517c478bd9Sstevel@tonic-gate 			cur_off);
4527c478bd9Sstevel@tonic-gate 		while (cur_off && (strcmp_res = strcmp((char *)bhp +
4537c478bd9Sstevel@tonic-gate 		    cur_bep->be_lib_name, lib_name)) < 0) {
4547c478bd9Sstevel@tonic-gate 			prev_off = cur_off;
4557c478bd9Sstevel@tonic-gate 			cur_off = cur_bep->be_next;
4567c478bd9Sstevel@tonic-gate 			/* LINTED */
4577c478bd9Sstevel@tonic-gate 			cur_bep = (binding_entry *)((char *)bhp +
4587c478bd9Sstevel@tonic-gate 				cur_off);
4597c478bd9Sstevel@tonic-gate 		}
4607c478bd9Sstevel@tonic-gate 		if (cur_off && (strcmp_res == 0)) {
4617c478bd9Sstevel@tonic-gate 			/*
4627c478bd9Sstevel@tonic-gate 			 * This is a small optimization.  For
4637c478bd9Sstevel@tonic-gate 			 * each bucket we will only record a library
4647c478bd9Sstevel@tonic-gate 			 * name once.  Once it has been recorded in
4657c478bd9Sstevel@tonic-gate 			 * a bucket we will just re-use the same
4667c478bd9Sstevel@tonic-gate 			 * string.
4677c478bd9Sstevel@tonic-gate 			 */
4687c478bd9Sstevel@tonic-gate 			lib_off = cur_bep->be_lib_name;
4697c478bd9Sstevel@tonic-gate 			while (cur_off && (strcmp_res = strcmp((char *)bhp +
4707c478bd9Sstevel@tonic-gate 			    cur_bep->be_sym_name, sym_name)) < 0) {
4717c478bd9Sstevel@tonic-gate 				prev_off = cur_off;
4727c478bd9Sstevel@tonic-gate 				cur_off = cur_bep->be_next;
4737c478bd9Sstevel@tonic-gate 				/* LINTED */
4747c478bd9Sstevel@tonic-gate 				cur_bep = (binding_entry *)((char *)bhp +
4757c478bd9Sstevel@tonic-gate 					cur_off);
4767c478bd9Sstevel@tonic-gate 			}
4777c478bd9Sstevel@tonic-gate 		}
4787c478bd9Sstevel@tonic-gate 		if (strcmp_res == 0) {
4797c478bd9Sstevel@tonic-gate 			/*
4807c478bd9Sstevel@tonic-gate 			 * We've got a match
4817c478bd9Sstevel@tonic-gate 			 */
4827c478bd9Sstevel@tonic-gate 			cur_bep->be_count++;
4837c478bd9Sstevel@tonic-gate 		} else {
4847c478bd9Sstevel@tonic-gate 			unsigned int	new_off;
4857c478bd9Sstevel@tonic-gate 			binding_entry *	new_bep;
4867c478bd9Sstevel@tonic-gate 			unsigned int	sym_off;
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 			new_off = get_new_entry();
4897c478bd9Sstevel@tonic-gate 			if (lib_off == 0)
4907c478bd9Sstevel@tonic-gate 				lib_off = save_str(lib_name);
4917c478bd9Sstevel@tonic-gate 			sym_off = save_str(sym_name);
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 			/* LINTED */
4947c478bd9Sstevel@tonic-gate 			new_bep = (binding_entry *)((char *)bhp +
4957c478bd9Sstevel@tonic-gate 				new_off);
4967c478bd9Sstevel@tonic-gate 			new_bep->be_sym_name = sym_off;
4977c478bd9Sstevel@tonic-gate 			new_bep->be_lib_name = lib_off;
4987c478bd9Sstevel@tonic-gate 			new_bep->be_count = 1;
4997c478bd9Sstevel@tonic-gate 			new_bep->be_next = cur_off;
5007c478bd9Sstevel@tonic-gate 			if (prev_off) {
5017c478bd9Sstevel@tonic-gate 				/* LINTED */
5027c478bd9Sstevel@tonic-gate 				prev_bep = (binding_entry *)((char *)bhp +
5037c478bd9Sstevel@tonic-gate 					prev_off);
5047c478bd9Sstevel@tonic-gate 				prev_bep->be_next = new_off;
5057c478bd9Sstevel@tonic-gate 			} else
5067c478bd9Sstevel@tonic-gate 				/*
5077c478bd9Sstevel@tonic-gate 				 * Insert at head of list.
5087c478bd9Sstevel@tonic-gate 				 */
5097c478bd9Sstevel@tonic-gate 				bhp->bh_bkts[bktno].bb_head = new_off;
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 		}
5127c478bd9Sstevel@tonic-gate 	}
5137c478bd9Sstevel@tonic-gate 	bt_unlock(&bhp->bh_bkts[bktno].bb_lock);
5147c478bd9Sstevel@tonic-gate 	(void) sigprocmask(SIG_SETMASK, &omask, NULL);
5157c478bd9Sstevel@tonic-gate 	return (symp->st_value);
5167c478bd9Sstevel@tonic-gate }
517