1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate #include <link.h> 31*0Sstevel@tonic-gate #include <stdlib.h> 32*0Sstevel@tonic-gate #include <unistd.h> 33*0Sstevel@tonic-gate #include <sys/types.h> 34*0Sstevel@tonic-gate #include <sys/stat.h> 35*0Sstevel@tonic-gate #include <sys/regset.h> 36*0Sstevel@tonic-gate #include <sys/frame.h> 37*0Sstevel@tonic-gate #include <sys/lwp.h> 38*0Sstevel@tonic-gate #include <fcntl.h> 39*0Sstevel@tonic-gate #include <stdio.h> 40*0Sstevel@tonic-gate #include <sys/mman.h> 41*0Sstevel@tonic-gate #include <errno.h> 42*0Sstevel@tonic-gate #include <signal.h> 43*0Sstevel@tonic-gate #include <synch.h> 44*0Sstevel@tonic-gate #include <string.h> 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #include "bindings.h" 47*0Sstevel@tonic-gate #include "env.h" 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate static Elist *bindto_list = 0; 50*0Sstevel@tonic-gate static Elist *bindfrom_list = 0; 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate static bindhead *bhp = NULL; 53*0Sstevel@tonic-gate static unsigned int current_map_len = 0; 54*0Sstevel@tonic-gate static char *buffer_name; 55*0Sstevel@tonic-gate static const sigset_t iset = { ~0U, ~0U, ~0U, ~0U }; 56*0Sstevel@tonic-gate static lwp_mutex_t sharedmutex = SHAREDMUTEX; 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate /* 59*0Sstevel@tonic-gate * This routine was stolen from libelf.so.1 60*0Sstevel@tonic-gate */ 61*0Sstevel@tonic-gate static unsigned long 62*0Sstevel@tonic-gate ehash(const char *name) 63*0Sstevel@tonic-gate { 64*0Sstevel@tonic-gate register unsigned int g, h = 0; 65*0Sstevel@tonic-gate register const unsigned char *nm = (unsigned char *)name; 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate while (*nm != '\0') { 68*0Sstevel@tonic-gate h = (h << 4) + *nm++; 69*0Sstevel@tonic-gate /* LINTED */ 70*0Sstevel@tonic-gate if ((g = (unsigned int)(h & MASK)) != 0) 71*0Sstevel@tonic-gate h ^= g >> 24; 72*0Sstevel@tonic-gate h &= ~MASK; 73*0Sstevel@tonic-gate } 74*0Sstevel@tonic-gate return ((unsigned long)h); 75*0Sstevel@tonic-gate } 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate static void 79*0Sstevel@tonic-gate output_err_message(const char *msg) 80*0Sstevel@tonic-gate { 81*0Sstevel@tonic-gate int fd; 82*0Sstevel@tonic-gate if ((fd = open("/tmp/bind_err", O_RDWR | O_CREAT, 0666)) == -1) { 83*0Sstevel@tonic-gate (void) fprintf(stderr, "bindings.so: unable to open err_log\n"); 84*0Sstevel@tonic-gate perror("open"); 85*0Sstevel@tonic-gate } 86*0Sstevel@tonic-gate (void) lseek(fd, 0, SEEK_END); 87*0Sstevel@tonic-gate (void) write(fd, msg, strlen(msg)); 88*0Sstevel@tonic-gate (void) close(fd); 89*0Sstevel@tonic-gate } 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate /* 92*0Sstevel@tonic-gate * common mutex locking & unlocking routines for this module. This is to 93*0Sstevel@tonic-gate * control the setting of 'lock_held'. 94*0Sstevel@tonic-gate */ 95*0Sstevel@tonic-gate static void 96*0Sstevel@tonic-gate bt_lock(lwp_mutex_t *lock) 97*0Sstevel@tonic-gate { 98*0Sstevel@tonic-gate if (_lwp_mutex_lock(lock) != 0) { 99*0Sstevel@tonic-gate output_err_message("bt_lock failed!!\n"); 100*0Sstevel@tonic-gate (void) fprintf(stderr, "bindings.so: unable to obtain lock\n"); 101*0Sstevel@tonic-gate perror("_lwp_mutex_lock"); 102*0Sstevel@tonic-gate } 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate static void 106*0Sstevel@tonic-gate bt_unlock(lwp_mutex_t *lock) 107*0Sstevel@tonic-gate { 108*0Sstevel@tonic-gate if (_lwp_mutex_unlock(lock) != 0) { 109*0Sstevel@tonic-gate output_err_message("bt_unlock failed!!\n"); 110*0Sstevel@tonic-gate (void) fprintf(stderr, "bindings.so: unable to unlock lock\n"); 111*0Sstevel@tonic-gate perror("_lwp_mutex_unlock"); 112*0Sstevel@tonic-gate } 113*0Sstevel@tonic-gate } 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate /* 118*0Sstevel@tonic-gate * It's always possible that another process sharing our buffer 119*0Sstevel@tonic-gate * has caused it to grow. If this is the case we must adjust our 120*0Sstevel@tonic-gate * mappings to compensate. 121*0Sstevel@tonic-gate */ 122*0Sstevel@tonic-gate static void 123*0Sstevel@tonic-gate remap_buffer(int fd) 124*0Sstevel@tonic-gate { 125*0Sstevel@tonic-gate void * new_bhp; 126*0Sstevel@tonic-gate if ((new_bhp = mmap(0, bhp->bh_size, PROT_READ | PROT_WRITE, 127*0Sstevel@tonic-gate MAP_SHARED, fd, 0)) == MAP_FAILED) { 128*0Sstevel@tonic-gate (void) fprintf(stderr, "bindings: remap: mmap failed\n"); 129*0Sstevel@tonic-gate perror("mmap"); 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate bt_unlock(&bhp->bh_lock); 132*0Sstevel@tonic-gate exit(1); 133*0Sstevel@tonic-gate } 134*0Sstevel@tonic-gate /* 135*0Sstevel@tonic-gate * clean up old mapping 136*0Sstevel@tonic-gate */ 137*0Sstevel@tonic-gate (void) munmap((caddr_t)bhp, current_map_len); 138*0Sstevel@tonic-gate bhp = (bindhead *)new_bhp; 139*0Sstevel@tonic-gate current_map_len = bhp->bh_size; 140*0Sstevel@tonic-gate } 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate static void 143*0Sstevel@tonic-gate grow_buffer() 144*0Sstevel@tonic-gate { 145*0Sstevel@tonic-gate int fd; 146*0Sstevel@tonic-gate if ((fd = open(buffer_name, O_RDWR)) == -1) { 147*0Sstevel@tonic-gate (void) fprintf(stderr, 148*0Sstevel@tonic-gate "bidings: grow_buffer: open failed: %s\n", 149*0Sstevel@tonic-gate buffer_name); 150*0Sstevel@tonic-gate perror("open"); 151*0Sstevel@tonic-gate bt_unlock(&bhp->bh_lock); 152*0Sstevel@tonic-gate exit(1); 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate if (ftruncate(fd, bhp->bh_size + BLKSIZE) == -1) { 155*0Sstevel@tonic-gate (void) fprintf(stderr, "grow_buffer failed\n"); 156*0Sstevel@tonic-gate perror("ftruncate"); 157*0Sstevel@tonic-gate bt_unlock(&bhp->bh_lock); 158*0Sstevel@tonic-gate exit(1); 159*0Sstevel@tonic-gate } 160*0Sstevel@tonic-gate bhp->bh_size += BLKSIZE; 161*0Sstevel@tonic-gate remap_buffer(fd); 162*0Sstevel@tonic-gate (void) close(fd); 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate static void 166*0Sstevel@tonic-gate get_new_strbuf() 167*0Sstevel@tonic-gate { 168*0Sstevel@tonic-gate bt_lock(&bhp->bh_lock); 169*0Sstevel@tonic-gate while (bhp->bh_end + STRBLKSIZE > bhp->bh_size) 170*0Sstevel@tonic-gate grow_buffer(); 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate bhp->bh_strcur = bhp->bh_end; 173*0Sstevel@tonic-gate bhp->bh_end = bhp->bh_strend = bhp->bh_strcur + STRBLKSIZE; 174*0Sstevel@tonic-gate bt_unlock(&bhp->bh_lock); 175*0Sstevel@tonic-gate } 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate static unsigned int 178*0Sstevel@tonic-gate save_str(const char *str) 179*0Sstevel@tonic-gate { 180*0Sstevel@tonic-gate char *sptr; 181*0Sstevel@tonic-gate unsigned int bptr; 182*0Sstevel@tonic-gate unsigned int slen; 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate bt_lock(&bhp->bh_strlock); 185*0Sstevel@tonic-gate /* LINTED */ 186*0Sstevel@tonic-gate slen = (unsigned int)strlen(str); 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate /* 189*0Sstevel@tonic-gate * will string fit into our current string buffer? 190*0Sstevel@tonic-gate */ 191*0Sstevel@tonic-gate if ((slen + 1) > (bhp->bh_strend - bhp->bh_strcur)) 192*0Sstevel@tonic-gate get_new_strbuf(); 193*0Sstevel@tonic-gate bptr = bhp->bh_strcur; 194*0Sstevel@tonic-gate sptr = (char *)bhp + bhp->bh_strcur; 195*0Sstevel@tonic-gate bhp->bh_strcur += slen + 1; 196*0Sstevel@tonic-gate (void) strncpy(sptr, str, slen); 197*0Sstevel@tonic-gate sptr[slen] = '\0'; 198*0Sstevel@tonic-gate bt_unlock(&bhp->bh_strlock); 199*0Sstevel@tonic-gate return (bptr); 200*0Sstevel@tonic-gate } 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate static unsigned int 204*0Sstevel@tonic-gate get_new_entry() 205*0Sstevel@tonic-gate { 206*0Sstevel@tonic-gate unsigned int new_ent; 207*0Sstevel@tonic-gate bt_lock(&bhp->bh_lock); 208*0Sstevel@tonic-gate while ((sizeof (binding_entry) + bhp->bh_end) > bhp->bh_size) 209*0Sstevel@tonic-gate grow_buffer(); 210*0Sstevel@tonic-gate new_ent = bhp->bh_end; 211*0Sstevel@tonic-gate bhp->bh_end += sizeof (binding_entry); 212*0Sstevel@tonic-gate bt_unlock(&bhp->bh_lock); 213*0Sstevel@tonic-gate return (new_ent); 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate static void 219*0Sstevel@tonic-gate init_locks() 220*0Sstevel@tonic-gate { 221*0Sstevel@tonic-gate int i; 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate /* 224*0Sstevel@tonic-gate * NOTE: I should call _lwp_mutex_init() but it doesn't 225*0Sstevel@tonic-gate * yet exist. see bug#1179352 226*0Sstevel@tonic-gate */ 227*0Sstevel@tonic-gate (void) memcpy(&bhp->bh_lock, &sharedmutex, sizeof (lwp_mutex_t)); 228*0Sstevel@tonic-gate for (i = 0; i < DEFBKTS; i++) 229*0Sstevel@tonic-gate (void) memcpy(&bhp->bh_bkts[i].bb_lock, &sharedmutex, 230*0Sstevel@tonic-gate sizeof (lwp_mutex_t)); 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate (void) memcpy(&bhp->bh_strlock, &sharedmutex, sizeof (lwp_mutex_t)); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate uint_t 236*0Sstevel@tonic-gate la_version(uint_t version) 237*0Sstevel@tonic-gate { 238*0Sstevel@tonic-gate int fd; 239*0Sstevel@tonic-gate sigset_t omask; 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate if (version < LAV_CURRENT) { 242*0Sstevel@tonic-gate (void) fprintf(stderr, 243*0Sstevel@tonic-gate "bindings.so: unexpected link_audit version: %d\n", 244*0Sstevel@tonic-gate version); 245*0Sstevel@tonic-gate return (0); 246*0Sstevel@tonic-gate } 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate build_env_list(&bindto_list, (const char *)"BT_BINDTO"); 249*0Sstevel@tonic-gate build_env_list(&bindfrom_list, (const char *)"BT_BINDFROM"); 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate if ((buffer_name = getenv(FILEENV)) == NULL) 252*0Sstevel@tonic-gate buffer_name = DEFFILE; 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &iset, &omask); 255*0Sstevel@tonic-gate if ((fd = open(buffer_name, O_RDWR | O_CREAT | O_EXCL, 0666)) != -1) { 256*0Sstevel@tonic-gate int init_size = sizeof (bindhead) + BLKSIZE; 257*0Sstevel@tonic-gate if (ftruncate(fd, init_size) == -1) { 258*0Sstevel@tonic-gate perror("ftruncate"); 259*0Sstevel@tonic-gate return (0); 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate /* LINTED */ 263*0Sstevel@tonic-gate if ((bhp = (bindhead *)mmap(0, init_size, 264*0Sstevel@tonic-gate PROT_READ | PROT_WRITE, 265*0Sstevel@tonic-gate MAP_SHARED, fd, 0)) == MAP_FAILED) { 266*0Sstevel@tonic-gate perror("bindings.so: mmap"); 267*0Sstevel@tonic-gate return (0); 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate (void) close(fd); 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate init_locks(); 273*0Sstevel@tonic-gate /* 274*0Sstevel@tonic-gate * Lock our structure and then initialize the data 275*0Sstevel@tonic-gate */ 276*0Sstevel@tonic-gate bt_lock(&bhp->bh_lock); 277*0Sstevel@tonic-gate bhp->bh_vers = BINDCURVERS; 278*0Sstevel@tonic-gate current_map_len = bhp->bh_size = init_size; 279*0Sstevel@tonic-gate bhp->bh_end = sizeof (bindhead); 280*0Sstevel@tonic-gate bhp->bh_bktcnt = DEFBKTS; 281*0Sstevel@tonic-gate bt_unlock(&bhp->bh_lock); 282*0Sstevel@tonic-gate /* 283*0Sstevel@tonic-gate * Set up our initial string buffer 284*0Sstevel@tonic-gate */ 285*0Sstevel@tonic-gate get_new_strbuf(); 286*0Sstevel@tonic-gate } else if ((fd = open(buffer_name, O_RDWR)) != -1) { 287*0Sstevel@tonic-gate struct stat stbuf; 288*0Sstevel@tonic-gate int i; 289*0Sstevel@tonic-gate for (i = 0; i < 4; i++) { 290*0Sstevel@tonic-gate if (fstat(fd, &stbuf) == -1) { 291*0Sstevel@tonic-gate (void) sleep(1); 292*0Sstevel@tonic-gate continue; 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate if (stbuf.st_size < sizeof (bindhead)) { 295*0Sstevel@tonic-gate (void) sleep(1); 296*0Sstevel@tonic-gate continue; 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate /* LINTED */ 299*0Sstevel@tonic-gate if ((bhp = (bindhead *)mmap(0, stbuf.st_size, 300*0Sstevel@tonic-gate PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == 301*0Sstevel@tonic-gate MAP_FAILED) { 302*0Sstevel@tonic-gate (void) fprintf(stderr, 303*0Sstevel@tonic-gate "bindings: mmap failed\n"); 304*0Sstevel@tonic-gate perror("mmap"); 305*0Sstevel@tonic-gate return (0); 306*0Sstevel@tonic-gate } 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate /* LINTED */ 309*0Sstevel@tonic-gate current_map_len = (unsigned int)stbuf.st_size; 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate if (bhp == NULL) { 312*0Sstevel@tonic-gate (void) fprintf(stderr, 313*0Sstevel@tonic-gate "bindings: buffer mapping timed out\n"); 314*0Sstevel@tonic-gate return (0); 315*0Sstevel@tonic-gate } 316*0Sstevel@tonic-gate for (i = 0; i < 4; i++) { 317*0Sstevel@tonic-gate if (bhp->bh_vers == 0) { 318*0Sstevel@tonic-gate (void) sleep(1); 319*0Sstevel@tonic-gate continue; 320*0Sstevel@tonic-gate } 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate if (bhp->bh_vers == 0) { 323*0Sstevel@tonic-gate (void) fprintf(stderr, 324*0Sstevel@tonic-gate "bindings: %s not initialized\n", buffer_name); 325*0Sstevel@tonic-gate return (0); 326*0Sstevel@tonic-gate } 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate bt_lock(&bhp->bh_lock); 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate if (bhp->bh_size != current_map_len) 331*0Sstevel@tonic-gate remap_buffer(fd); 332*0Sstevel@tonic-gate (void) close(fd); 333*0Sstevel@tonic-gate } else { 334*0Sstevel@tonic-gate (void) fprintf(stderr, "bindings: unable to open %s\n", 335*0Sstevel@tonic-gate buffer_name); 336*0Sstevel@tonic-gate perror("open"); 337*0Sstevel@tonic-gate return (0); 338*0Sstevel@tonic-gate } 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &omask, NULL); 341*0Sstevel@tonic-gate bt_unlock(&bhp->bh_lock); 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate return (LAV_CURRENT); 344*0Sstevel@tonic-gate } 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate /* ARGSUSED 0 */ 347*0Sstevel@tonic-gate uint_t 348*0Sstevel@tonic-gate la_objopen(Link_map *lmp, Lmid_t lmid, uintptr_t *cookie) 349*0Sstevel@tonic-gate { 350*0Sstevel@tonic-gate uint_t flags; 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate if ((bindto_list == 0) || 353*0Sstevel@tonic-gate (check_list(bindto_list, lmp->l_name))) 354*0Sstevel@tonic-gate flags = LA_FLG_BINDTO; 355*0Sstevel@tonic-gate else 356*0Sstevel@tonic-gate flags = 0; 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate if ((bindfrom_list == 0) || 359*0Sstevel@tonic-gate (check_list(bindfrom_list, lmp->l_name))) 360*0Sstevel@tonic-gate flags |= LA_FLG_BINDFROM; 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate return (flags); 363*0Sstevel@tonic-gate } 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate /* ARGSUSED 1 */ 367*0Sstevel@tonic-gate #if defined(__sparcv9) 368*0Sstevel@tonic-gate uintptr_t 369*0Sstevel@tonic-gate la_sparcv9_pltenter(Elf64_Sym *symp, uint_t symndx, uintptr_t *refcooke, 370*0Sstevel@tonic-gate uintptr_t *defcook, La_sparcv9_regs *regset, uint_t *sb_flags, 371*0Sstevel@tonic-gate const char *sym_name) 372*0Sstevel@tonic-gate #elif defined(__sparc) 373*0Sstevel@tonic-gate uintptr_t 374*0Sstevel@tonic-gate la_sparcv8_pltenter(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcooke, 375*0Sstevel@tonic-gate uintptr_t *defcook, La_sparcv8_regs *regset, uint_t *sb_flags) 376*0Sstevel@tonic-gate #elif defined(__amd64) 377*0Sstevel@tonic-gate uintptr_t 378*0Sstevel@tonic-gate la_amd64_pltenter(Elf64_Sym *symp, uint_t symndx, uintptr_t *refcooke, 379*0Sstevel@tonic-gate uintptr_t *defcook, La_amd64_regs *regset, uint_t *sb_flags, 380*0Sstevel@tonic-gate const char *sym_name) 381*0Sstevel@tonic-gate #elif defined(__i386) 382*0Sstevel@tonic-gate uintptr_t 383*0Sstevel@tonic-gate la_i86_pltenter(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcooke, 384*0Sstevel@tonic-gate uintptr_t *defcook, La_i86_regs *regset, uint_t *sb_flags) 385*0Sstevel@tonic-gate #endif 386*0Sstevel@tonic-gate { 387*0Sstevel@tonic-gate unsigned long bktno; 388*0Sstevel@tonic-gate Link_map *dlmp = (Link_map *)*defcook; 389*0Sstevel@tonic-gate const char *lib_name; 390*0Sstevel@tonic-gate sigset_t omask; 391*0Sstevel@tonic-gate #if !defined(_LP64) 392*0Sstevel@tonic-gate const char *sym_name = (const char *)symp->st_name; 393*0Sstevel@tonic-gate #endif 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate lib_name = dlmp->l_name; 397*0Sstevel@tonic-gate 398*0Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &iset, &omask); 399*0Sstevel@tonic-gate if (sym_name == 0) { 400*0Sstevel@tonic-gate output_err_message("null symname\n"); 401*0Sstevel@tonic-gate return (symp->st_value); 402*0Sstevel@tonic-gate } 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate bktno = ehash(sym_name) % bhp->bh_bktcnt; 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate bt_lock(&bhp->bh_bkts[bktno].bb_lock); 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate /* 409*0Sstevel@tonic-gate * The buffer has been grown (by another process) and 410*0Sstevel@tonic-gate * we need to remap it into memory. 411*0Sstevel@tonic-gate */ 412*0Sstevel@tonic-gate if (bhp->bh_size != current_map_len) { 413*0Sstevel@tonic-gate int fd; 414*0Sstevel@tonic-gate if ((fd = open(buffer_name, O_RDWR)) == -1) { 415*0Sstevel@tonic-gate (void) fprintf(stderr, 416*0Sstevel@tonic-gate "bidings: plt_enter: open failed: %s\n", 417*0Sstevel@tonic-gate buffer_name); 418*0Sstevel@tonic-gate perror("open"); 419*0Sstevel@tonic-gate bt_unlock(&bhp->bh_lock); 420*0Sstevel@tonic-gate exit(1); 421*0Sstevel@tonic-gate } 422*0Sstevel@tonic-gate bt_lock(&bhp->bh_lock); 423*0Sstevel@tonic-gate remap_buffer(fd); 424*0Sstevel@tonic-gate bt_unlock(&bhp->bh_lock); 425*0Sstevel@tonic-gate (void) close(fd); 426*0Sstevel@tonic-gate } 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate if (bhp->bh_bkts[bktno].bb_head == NULL) { 429*0Sstevel@tonic-gate binding_entry * bep; 430*0Sstevel@tonic-gate unsigned int be_off; 431*0Sstevel@tonic-gate unsigned int sym_off; 432*0Sstevel@tonic-gate unsigned int lib_off; 433*0Sstevel@tonic-gate 434*0Sstevel@tonic-gate be_off = get_new_entry(); 435*0Sstevel@tonic-gate sym_off = save_str(sym_name); 436*0Sstevel@tonic-gate lib_off = save_str(lib_name); 437*0Sstevel@tonic-gate /* LINTED */ 438*0Sstevel@tonic-gate bep = (binding_entry *)((char *)bhp + be_off); 439*0Sstevel@tonic-gate bep->be_next = 0; 440*0Sstevel@tonic-gate bep->be_sym_name = sym_off; 441*0Sstevel@tonic-gate bep->be_lib_name = lib_off; 442*0Sstevel@tonic-gate bep->be_count = 1; 443*0Sstevel@tonic-gate bhp->bh_bkts[bktno].bb_head = be_off; 444*0Sstevel@tonic-gate } else { 445*0Sstevel@tonic-gate int strcmp_res; 446*0Sstevel@tonic-gate unsigned int prev_off = 0; 447*0Sstevel@tonic-gate binding_entry * prev_bep = NULL; 448*0Sstevel@tonic-gate unsigned int cur_off; 449*0Sstevel@tonic-gate binding_entry * cur_bep; 450*0Sstevel@tonic-gate unsigned int lib_off = 0; 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate /* 453*0Sstevel@tonic-gate * Once we get to the bucket, we do a two tiered 454*0Sstevel@tonic-gate * search. First we search for a library match, then 455*0Sstevel@tonic-gate * we search for a symbol match. 456*0Sstevel@tonic-gate */ 457*0Sstevel@tonic-gate cur_off = bhp->bh_bkts[bktno].bb_head; 458*0Sstevel@tonic-gate /* LINTED */ 459*0Sstevel@tonic-gate cur_bep = (binding_entry *)((char *)bhp + 460*0Sstevel@tonic-gate cur_off); 461*0Sstevel@tonic-gate while (cur_off && (strcmp_res = strcmp((char *)bhp + 462*0Sstevel@tonic-gate cur_bep->be_lib_name, lib_name)) < 0) { 463*0Sstevel@tonic-gate prev_off = cur_off; 464*0Sstevel@tonic-gate cur_off = cur_bep->be_next; 465*0Sstevel@tonic-gate /* LINTED */ 466*0Sstevel@tonic-gate cur_bep = (binding_entry *)((char *)bhp + 467*0Sstevel@tonic-gate cur_off); 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate if (cur_off && (strcmp_res == 0)) { 470*0Sstevel@tonic-gate /* 471*0Sstevel@tonic-gate * This is a small optimization. For 472*0Sstevel@tonic-gate * each bucket we will only record a library 473*0Sstevel@tonic-gate * name once. Once it has been recorded in 474*0Sstevel@tonic-gate * a bucket we will just re-use the same 475*0Sstevel@tonic-gate * string. 476*0Sstevel@tonic-gate */ 477*0Sstevel@tonic-gate lib_off = cur_bep->be_lib_name; 478*0Sstevel@tonic-gate while (cur_off && (strcmp_res = strcmp((char *)bhp + 479*0Sstevel@tonic-gate cur_bep->be_sym_name, sym_name)) < 0) { 480*0Sstevel@tonic-gate prev_off = cur_off; 481*0Sstevel@tonic-gate cur_off = cur_bep->be_next; 482*0Sstevel@tonic-gate /* LINTED */ 483*0Sstevel@tonic-gate cur_bep = (binding_entry *)((char *)bhp + 484*0Sstevel@tonic-gate cur_off); 485*0Sstevel@tonic-gate } 486*0Sstevel@tonic-gate } 487*0Sstevel@tonic-gate if (strcmp_res == 0) { 488*0Sstevel@tonic-gate /* 489*0Sstevel@tonic-gate * We've got a match 490*0Sstevel@tonic-gate */ 491*0Sstevel@tonic-gate cur_bep->be_count++; 492*0Sstevel@tonic-gate } else { 493*0Sstevel@tonic-gate unsigned int new_off; 494*0Sstevel@tonic-gate binding_entry * new_bep; 495*0Sstevel@tonic-gate unsigned int sym_off; 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate new_off = get_new_entry(); 498*0Sstevel@tonic-gate if (lib_off == 0) 499*0Sstevel@tonic-gate lib_off = save_str(lib_name); 500*0Sstevel@tonic-gate sym_off = save_str(sym_name); 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate /* LINTED */ 503*0Sstevel@tonic-gate new_bep = (binding_entry *)((char *)bhp + 504*0Sstevel@tonic-gate new_off); 505*0Sstevel@tonic-gate new_bep->be_sym_name = sym_off; 506*0Sstevel@tonic-gate new_bep->be_lib_name = lib_off; 507*0Sstevel@tonic-gate new_bep->be_count = 1; 508*0Sstevel@tonic-gate new_bep->be_next = cur_off; 509*0Sstevel@tonic-gate if (prev_off) { 510*0Sstevel@tonic-gate /* LINTED */ 511*0Sstevel@tonic-gate prev_bep = (binding_entry *)((char *)bhp + 512*0Sstevel@tonic-gate prev_off); 513*0Sstevel@tonic-gate prev_bep->be_next = new_off; 514*0Sstevel@tonic-gate } else 515*0Sstevel@tonic-gate /* 516*0Sstevel@tonic-gate * Insert at head of list. 517*0Sstevel@tonic-gate */ 518*0Sstevel@tonic-gate bhp->bh_bkts[bktno].bb_head = new_off; 519*0Sstevel@tonic-gate 520*0Sstevel@tonic-gate } 521*0Sstevel@tonic-gate } 522*0Sstevel@tonic-gate bt_unlock(&bhp->bh_bkts[bktno].bb_lock); 523*0Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &omask, NULL); 524*0Sstevel@tonic-gate return (symp->st_value); 525*0Sstevel@tonic-gate } 526