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 (c) 1988 AT&T 24*0Sstevel@tonic-gate * All Rights Reserved 25*0Sstevel@tonic-gate * 26*0Sstevel@tonic-gate * 27*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 28*0Sstevel@tonic-gate * Use is subject to license terms. 29*0Sstevel@tonic-gate */ 30*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate /* 33*0Sstevel@tonic-gate * SPARC machine dependent and ELF file class dependent functions. 34*0Sstevel@tonic-gate * Contains routines for performing function binding and symbol relocations. 35*0Sstevel@tonic-gate */ 36*0Sstevel@tonic-gate #include "_synonyms.h" 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate #include <stdio.h> 39*0Sstevel@tonic-gate #include <sys/elf.h> 40*0Sstevel@tonic-gate #include <sys/elf_SPARC.h> 41*0Sstevel@tonic-gate #include <sys/mman.h> 42*0Sstevel@tonic-gate #include <dlfcn.h> 43*0Sstevel@tonic-gate #include <synch.h> 44*0Sstevel@tonic-gate #include <string.h> 45*0Sstevel@tonic-gate #include "_rtld.h" 46*0Sstevel@tonic-gate #include "_audit.h" 47*0Sstevel@tonic-gate #include "_elf.h" 48*0Sstevel@tonic-gate #include "msg.h" 49*0Sstevel@tonic-gate #include "debug.h" 50*0Sstevel@tonic-gate #include "reloc.h" 51*0Sstevel@tonic-gate #include "conv.h" 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate extern void iflush_range(caddr_t, size_t); 55*0Sstevel@tonic-gate extern void plt_full_range(uintptr_t, uintptr_t); 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate int 59*0Sstevel@tonic-gate elf_mach_flags_check(Rej_desc *rej, Ehdr *ehdr) 60*0Sstevel@tonic-gate { 61*0Sstevel@tonic-gate /* 62*0Sstevel@tonic-gate * Check machine type and flags. 63*0Sstevel@tonic-gate */ 64*0Sstevel@tonic-gate if (ehdr->e_machine != EM_SPARC) { 65*0Sstevel@tonic-gate if (ehdr->e_machine != EM_SPARC32PLUS) { 66*0Sstevel@tonic-gate rej->rej_type = SGS_REJ_MACH; 67*0Sstevel@tonic-gate rej->rej_info = (uint_t)ehdr->e_machine; 68*0Sstevel@tonic-gate return (0); 69*0Sstevel@tonic-gate } 70*0Sstevel@tonic-gate if ((ehdr->e_flags & EF_SPARC_32PLUS) == 0) { 71*0Sstevel@tonic-gate rej->rej_type = SGS_REJ_MISFLAG; 72*0Sstevel@tonic-gate rej->rej_info = (uint_t)ehdr->e_flags; 73*0Sstevel@tonic-gate return (0); 74*0Sstevel@tonic-gate } 75*0Sstevel@tonic-gate if ((ehdr->e_flags & ~at_flags) & EF_SPARC_32PLUS_MASK) { 76*0Sstevel@tonic-gate rej->rej_type = SGS_REJ_BADFLAG; 77*0Sstevel@tonic-gate rej->rej_info = (uint_t)ehdr->e_flags; 78*0Sstevel@tonic-gate return (0); 79*0Sstevel@tonic-gate } 80*0Sstevel@tonic-gate } else if ((ehdr->e_flags & ~EF_SPARCV9_MM) != 0) { 81*0Sstevel@tonic-gate rej->rej_type = SGS_REJ_BADFLAG; 82*0Sstevel@tonic-gate rej->rej_info = (uint_t)ehdr->e_flags; 83*0Sstevel@tonic-gate return (0); 84*0Sstevel@tonic-gate } 85*0Sstevel@tonic-gate return (1); 86*0Sstevel@tonic-gate } 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate void 89*0Sstevel@tonic-gate ldso_plt_init(Rt_map * lmp) 90*0Sstevel@tonic-gate { 91*0Sstevel@tonic-gate /* 92*0Sstevel@tonic-gate * There is no need to analyze ld.so because we don't map in any of 93*0Sstevel@tonic-gate * its dependencies. However we may map these dependencies in later 94*0Sstevel@tonic-gate * (as if ld.so had dlopened them), so initialize the plt and the 95*0Sstevel@tonic-gate * permission information. 96*0Sstevel@tonic-gate */ 97*0Sstevel@tonic-gate if (PLTGOT(lmp)) 98*0Sstevel@tonic-gate elf_plt_init((PLTGOT(lmp)), (caddr_t)lmp); 99*0Sstevel@tonic-gate } 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate /* 102*0Sstevel@tonic-gate * elf_plt_write() will test to see how far away our destination 103*0Sstevel@tonic-gate * address lies. If it is close enough that a branch can 104*0Sstevel@tonic-gate * be used instead of a jmpl - we will fill the plt in with 105*0Sstevel@tonic-gate * single branch. The branches are much quicker then 106*0Sstevel@tonic-gate * a jmpl instruction - see bug#4356879 for further 107*0Sstevel@tonic-gate * details. 108*0Sstevel@tonic-gate * 109*0Sstevel@tonic-gate * NOTE: we pass in both a 'pltaddr' and a 'vpltaddr' since 110*0Sstevel@tonic-gate * librtld/dldump update PLT's who's physical 111*0Sstevel@tonic-gate * address is not the same as the 'virtual' runtime 112*0Sstevel@tonic-gate * address. 113*0Sstevel@tonic-gate */ 114*0Sstevel@tonic-gate Pltbindtype 115*0Sstevel@tonic-gate /* ARGSUSED4 */ 116*0Sstevel@tonic-gate elf_plt_write(uintptr_t addr, uintptr_t vaddr, void *rptr, uintptr_t symval, 117*0Sstevel@tonic-gate Xword pltndx) 118*0Sstevel@tonic-gate { 119*0Sstevel@tonic-gate Rela *rel = (Rela *)rptr; 120*0Sstevel@tonic-gate uintptr_t vpltaddr, pltaddr; 121*0Sstevel@tonic-gate long disp; 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate pltaddr = addr + rel->r_offset; 125*0Sstevel@tonic-gate vpltaddr = vaddr + rel->r_offset; 126*0Sstevel@tonic-gate disp = symval - vpltaddr - 4; 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate /* 129*0Sstevel@tonic-gate * Test if the destination address is close enough to use 130*0Sstevel@tonic-gate * a ba,a... instruction to reach it. 131*0Sstevel@tonic-gate */ 132*0Sstevel@tonic-gate if (S_INRANGE(disp, 23) && !(rtld_flags & RT_FL_NOBAPLT)) { 133*0Sstevel@tonic-gate uint_t *pltent, bainstr; 134*0Sstevel@tonic-gate Pltbindtype rc; 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate pltent = (uint_t *)pltaddr; 137*0Sstevel@tonic-gate /* 138*0Sstevel@tonic-gate * The 139*0Sstevel@tonic-gate * 140*0Sstevel@tonic-gate * ba,a,pt %icc, <dest> 141*0Sstevel@tonic-gate * 142*0Sstevel@tonic-gate * is the most efficient of the PLT's. If we 143*0Sstevel@tonic-gate * are within +-20 bits *and* running on a 144*0Sstevel@tonic-gate * v8plus architecture - use that branch. 145*0Sstevel@tonic-gate */ 146*0Sstevel@tonic-gate if ((at_flags & EF_SPARC_32PLUS) && 147*0Sstevel@tonic-gate S_INRANGE(disp, 20)) { 148*0Sstevel@tonic-gate bainstr = M_BA_A_PT; /* ba,a,pt %icc,<dest> */ 149*0Sstevel@tonic-gate bainstr |= (S_MASK(19) & (disp >> 2)); 150*0Sstevel@tonic-gate rc = PLT_T_21D; 151*0Sstevel@tonic-gate DBG_CALL(pltcnt21d++); 152*0Sstevel@tonic-gate } else { 153*0Sstevel@tonic-gate /* 154*0Sstevel@tonic-gate * Otherwise - we fall back to the good old 155*0Sstevel@tonic-gate * 156*0Sstevel@tonic-gate * ba,a <dest> 157*0Sstevel@tonic-gate * 158*0Sstevel@tonic-gate * Which still beats a jmpl instruction. 159*0Sstevel@tonic-gate */ 160*0Sstevel@tonic-gate bainstr = M_BA_A; /* ba,a <dest> */ 161*0Sstevel@tonic-gate bainstr |= (S_MASK(22) & (disp >> 2)); 162*0Sstevel@tonic-gate rc = PLT_T_24D; 163*0Sstevel@tonic-gate DBG_CALL(pltcnt24d++); 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate pltent[2] = M_NOP; /* nop instr */ 167*0Sstevel@tonic-gate pltent[1] = bainstr; 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate iflush_range((char *)(&pltent[1]), 4); 170*0Sstevel@tonic-gate pltent[0] = M_NOP; /* nop instr */ 171*0Sstevel@tonic-gate iflush_range((char *)(&pltent[0]), 4); 172*0Sstevel@tonic-gate return (rc); 173*0Sstevel@tonic-gate } 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate /* 176*0Sstevel@tonic-gate * The PLT destination is not in reach of 177*0Sstevel@tonic-gate * a branch instruction - so we fall back 178*0Sstevel@tonic-gate * to a 'jmpl' sequence. 179*0Sstevel@tonic-gate */ 180*0Sstevel@tonic-gate plt_full_range(pltaddr, symval); 181*0Sstevel@tonic-gate DBG_CALL(pltcntfull++); 182*0Sstevel@tonic-gate return (PLT_T_FULL); 183*0Sstevel@tonic-gate } 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate /* 187*0Sstevel@tonic-gate * Local storage space created on the stack created for this glue 188*0Sstevel@tonic-gate * code includes space for: 189*0Sstevel@tonic-gate * 0x4 pointer to dyn_data 190*0Sstevel@tonic-gate * 0x4 size prev stack frame 191*0Sstevel@tonic-gate */ 192*0Sstevel@tonic-gate static const uchar_t dyn_plt_template[] = { 193*0Sstevel@tonic-gate /* 0x00 */ 0x80, 0x90, 0x00, 0x1e, /* tst %fp */ 194*0Sstevel@tonic-gate /* 0x04 */ 0x02, 0x80, 0x00, 0x04, /* be 0x14 */ 195*0Sstevel@tonic-gate /* 0x08 */ 0x82, 0x27, 0x80, 0x0e, /* sub %sp, %fp, %g1 */ 196*0Sstevel@tonic-gate /* 0x0c */ 0x10, 0x80, 0x00, 0x03, /* ba 0x20 */ 197*0Sstevel@tonic-gate /* 0x10 */ 0x01, 0x00, 0x00, 0x00, /* nop */ 198*0Sstevel@tonic-gate /* 0x14 */ 0x82, 0x10, 0x20, 0x60, /* mov 0x60, %g1 */ 199*0Sstevel@tonic-gate /* 0x18 */ 0x9d, 0xe3, 0xbf, 0x98, /* save %sp, -0x68, %sp */ 200*0Sstevel@tonic-gate /* 0x1c */ 0xc2, 0x27, 0xbf, 0xf8, /* st %g1, [%fp + -0x8] */ 201*0Sstevel@tonic-gate /* 0x20 */ 0x03, 0x00, 0x00, 0x00, /* sethi %hi(val), %g1 */ 202*0Sstevel@tonic-gate /* 0x24 */ 0x82, 0x10, 0x60, 0x00, /* or %g1, %lo(val), %g1 */ 203*0Sstevel@tonic-gate /* 0x28 */ 0x40, 0x00, 0x00, 0x00, /* call <rel_addr> */ 204*0Sstevel@tonic-gate /* 0x2c */ 0xc2, 0x27, 0xbf, 0xfc /* st %g1, [%fp + -0x4] */ 205*0Sstevel@tonic-gate }; 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate int dyn_plt_ent_size = sizeof (dyn_plt_template) + 208*0Sstevel@tonic-gate sizeof (uintptr_t) + /* reflmp */ 209*0Sstevel@tonic-gate sizeof (uintptr_t) + /* deflmp */ 210*0Sstevel@tonic-gate sizeof (ulong_t) + /* symndx */ 211*0Sstevel@tonic-gate sizeof (ulong_t) + /* sb_flags */ 212*0Sstevel@tonic-gate sizeof (Sym); /* symdef */ 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate /* 215*0Sstevel@tonic-gate * the dynamic plt entry is: 216*0Sstevel@tonic-gate * 217*0Sstevel@tonic-gate * tst %fp 218*0Sstevel@tonic-gate * be 1f 219*0Sstevel@tonic-gate * nop 220*0Sstevel@tonic-gate * sub %sp, %fp, %g1 221*0Sstevel@tonic-gate * ba 2f 222*0Sstevel@tonic-gate * nop 223*0Sstevel@tonic-gate * 1: 224*0Sstevel@tonic-gate * mov SA(MINFRAME), %g1 ! if %fp is null this is the 225*0Sstevel@tonic-gate * ! 'minimum stack'. %fp is null 226*0Sstevel@tonic-gate * ! on the initial stack frame 227*0Sstevel@tonic-gate * 2: 228*0Sstevel@tonic-gate * save %sp, -(SA(MINFRAME) + 2 * CLONGSIZE), %sp 229*0Sstevel@tonic-gate * st %g1, [%fp + -0x8] ! store prev_stack size in [%fp - 8] 230*0Sstevel@tonic-gate * sethi %hi(dyn_data), %g1 231*0Sstevel@tonic-gate * or %g1, %lo(dyn_data), %g1 232*0Sstevel@tonic-gate * call elf_plt_trace 233*0Sstevel@tonic-gate * st %g1, [%fp + -0x4] ! store dyn_data ptr in [%fp - 4] 234*0Sstevel@tonic-gate * dyn data: 235*0Sstevel@tonic-gate * uintptr_t reflmp 236*0Sstevel@tonic-gate * uintptr_t deflmp 237*0Sstevel@tonic-gate * ulong_t symndx 238*0Sstevel@tonic-gate * ulong_t sb_flags 239*0Sstevel@tonic-gate * Sym symdef 240*0Sstevel@tonic-gate */ 241*0Sstevel@tonic-gate static caddr_t 242*0Sstevel@tonic-gate elf_plt_trace_write(caddr_t addr, Rela *rptr, Rt_map *rlmp, Rt_map *dlmp, 243*0Sstevel@tonic-gate Sym *sym, ulong_t symndx, ulong_t pltndx, caddr_t to, ulong_t sb_flags, 244*0Sstevel@tonic-gate int *fail) 245*0Sstevel@tonic-gate { 246*0Sstevel@tonic-gate extern ulong_t elf_plt_trace(); 247*0Sstevel@tonic-gate uintptr_t dyn_plt; 248*0Sstevel@tonic-gate uintptr_t *dyndata; 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate /* 251*0Sstevel@tonic-gate * If both pltenter & pltexit have been disabled there 252*0Sstevel@tonic-gate * there is no reason to even create the glue code. 253*0Sstevel@tonic-gate */ 254*0Sstevel@tonic-gate if ((sb_flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) == 255*0Sstevel@tonic-gate (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) { 256*0Sstevel@tonic-gate (void) elf_plt_write((uintptr_t)addr, (uintptr_t)addr, 257*0Sstevel@tonic-gate rptr, (uintptr_t)to, pltndx); 258*0Sstevel@tonic-gate return (to); 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate /* 262*0Sstevel@tonic-gate * We only need to add the glue code if there is an auditing 263*0Sstevel@tonic-gate * library that is interested in this binding. 264*0Sstevel@tonic-gate */ 265*0Sstevel@tonic-gate dyn_plt = (uintptr_t)AUDINFO(rlmp)->ai_dynplts + 266*0Sstevel@tonic-gate (pltndx * dyn_plt_ent_size); 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate /* 269*0Sstevel@tonic-gate * Have we initialized this dynamic plt entry yet? If we haven't do it 270*0Sstevel@tonic-gate * now. Otherwise this function has been called before, but from a 271*0Sstevel@tonic-gate * different plt (ie. from another shared object). In that case 272*0Sstevel@tonic-gate * we just set the plt to point to the new dyn_plt. 273*0Sstevel@tonic-gate */ 274*0Sstevel@tonic-gate if (*(uint_t *)dyn_plt == 0) { 275*0Sstevel@tonic-gate Sym * symp; 276*0Sstevel@tonic-gate Xword symvalue; 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate (void) memcpy((void *)dyn_plt, dyn_plt_template, 279*0Sstevel@tonic-gate sizeof (dyn_plt_template)); 280*0Sstevel@tonic-gate dyndata = (uintptr_t *)(dyn_plt + sizeof (dyn_plt_template)); 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate /* 283*0Sstevel@tonic-gate * relocating: 284*0Sstevel@tonic-gate * sethi %hi(dyndata), %g1 285*0Sstevel@tonic-gate */ 286*0Sstevel@tonic-gate symvalue = (Xword)dyndata; 287*0Sstevel@tonic-gate if (do_reloc(R_SPARC_HI22, (uchar_t *)(dyn_plt + 0x20), 288*0Sstevel@tonic-gate &symvalue, MSG_ORIG(MSG_SYM_LADYNDATA), 289*0Sstevel@tonic-gate MSG_ORIG(MSG_SPECFIL_DYNPLT)) == 0) { 290*0Sstevel@tonic-gate *fail = 1; 291*0Sstevel@tonic-gate return (0); 292*0Sstevel@tonic-gate } 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate /* 295*0Sstevel@tonic-gate * relocating: 296*0Sstevel@tonic-gate * or %g1, %lo(dyndata), %g1 297*0Sstevel@tonic-gate */ 298*0Sstevel@tonic-gate symvalue = (Xword)dyndata; 299*0Sstevel@tonic-gate if (do_reloc(R_SPARC_LO10, (uchar_t *)(dyn_plt + 0x24), 300*0Sstevel@tonic-gate &symvalue, MSG_ORIG(MSG_SYM_LADYNDATA), 301*0Sstevel@tonic-gate MSG_ORIG(MSG_SPECFIL_DYNPLT)) == 0) { 302*0Sstevel@tonic-gate *fail = 1; 303*0Sstevel@tonic-gate return (0); 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate /* 307*0Sstevel@tonic-gate * relocating: 308*0Sstevel@tonic-gate * call elf_plt_trace 309*0Sstevel@tonic-gate */ 310*0Sstevel@tonic-gate symvalue = (Xword)((uintptr_t)&elf_plt_trace - 311*0Sstevel@tonic-gate (dyn_plt + 0x28)); 312*0Sstevel@tonic-gate if (do_reloc(R_SPARC_WDISP30, (uchar_t *)(dyn_plt + 0x28), 313*0Sstevel@tonic-gate &symvalue, MSG_ORIG(MSG_SYM_ELFPLTTRACE), 314*0Sstevel@tonic-gate MSG_ORIG(MSG_SPECFIL_DYNPLT)) == 0) { 315*0Sstevel@tonic-gate *fail = 1; 316*0Sstevel@tonic-gate return (0); 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate *dyndata++ = (uintptr_t)rlmp; 320*0Sstevel@tonic-gate *dyndata++ = (uintptr_t)dlmp; 321*0Sstevel@tonic-gate *(ulong_t *)dyndata++ = symndx; 322*0Sstevel@tonic-gate *(ulong_t *)dyndata++ = sb_flags; 323*0Sstevel@tonic-gate symp = (Sym *)dyndata; 324*0Sstevel@tonic-gate *symp = *sym; 325*0Sstevel@tonic-gate symp->st_name += (Word)STRTAB(dlmp); 326*0Sstevel@tonic-gate symp->st_value = (Addr)to; 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate iflush_range((void *)dyn_plt, sizeof (dyn_plt_template)); 329*0Sstevel@tonic-gate } 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate (void) elf_plt_write((uintptr_t)addr, (uintptr_t)addr, 332*0Sstevel@tonic-gate rptr, (uintptr_t)dyn_plt, 0); 333*0Sstevel@tonic-gate return ((caddr_t)dyn_plt); 334*0Sstevel@tonic-gate } 335*0Sstevel@tonic-gate 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate /* 338*0Sstevel@tonic-gate * Function binding routine - invoked on the first call to a function through 339*0Sstevel@tonic-gate * the procedure linkage table; 340*0Sstevel@tonic-gate * passes first through an assembly language interface. 341*0Sstevel@tonic-gate * 342*0Sstevel@tonic-gate * Takes the address of the PLT entry where the call originated, 343*0Sstevel@tonic-gate * the offset into the relocation table of the associated 344*0Sstevel@tonic-gate * relocation entry and the address of the link map (rt_private_map struct) 345*0Sstevel@tonic-gate * for the entry. 346*0Sstevel@tonic-gate * 347*0Sstevel@tonic-gate * Returns the address of the function referenced after re-writing the PLT 348*0Sstevel@tonic-gate * entry to invoke the function directly. 349*0Sstevel@tonic-gate * 350*0Sstevel@tonic-gate * On error, causes process to terminate with a signal. 351*0Sstevel@tonic-gate */ 352*0Sstevel@tonic-gate ulong_t 353*0Sstevel@tonic-gate elf_bndr(Rt_map *lmp, ulong_t pltoff, caddr_t from) 354*0Sstevel@tonic-gate { 355*0Sstevel@tonic-gate Rt_map *nlmp, *llmp; 356*0Sstevel@tonic-gate ulong_t addr, vaddr, reloff, symval, rsymndx; 357*0Sstevel@tonic-gate char *name; 358*0Sstevel@tonic-gate Rela *rptr; 359*0Sstevel@tonic-gate Sym *sym, *nsym; 360*0Sstevel@tonic-gate Xword pltndx; 361*0Sstevel@tonic-gate uint_t binfo, sb_flags = 0; 362*0Sstevel@tonic-gate Slookup sl; 363*0Sstevel@tonic-gate Pltbindtype pbtype; 364*0Sstevel@tonic-gate int entry, dbg_save, lmflags; 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate /* 367*0Sstevel@tonic-gate * For compatibility with libthread (TI_VERSION 1) we track the entry 368*0Sstevel@tonic-gate * value. A zero value indicates we have recursed into ld.so.1 to 369*0Sstevel@tonic-gate * further process a locking request. Under this recursion we disable 370*0Sstevel@tonic-gate * tsort and cleanup activities. 371*0Sstevel@tonic-gate */ 372*0Sstevel@tonic-gate entry = enter(); 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate if ((lmflags = LIST(lmp)->lm_flags) & LML_FLG_RTLDLM) { 375*0Sstevel@tonic-gate dbg_save = dbg_mask; 376*0Sstevel@tonic-gate dbg_mask = 0; 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate /* 380*0Sstevel@tonic-gate * Must calculate true plt relocation address from reloc. 381*0Sstevel@tonic-gate * Take offset, subtract number of reserved PLT entries, and divide 382*0Sstevel@tonic-gate * by PLT entry size, which should give the index of the plt 383*0Sstevel@tonic-gate * entry (and relocation entry since they have been defined to be 384*0Sstevel@tonic-gate * in the same order). Then we must multiply by the size of 385*0Sstevel@tonic-gate * a relocation entry, which will give us the offset of the 386*0Sstevel@tonic-gate * plt relocation entry from the start of them given by JMPREL(lm). 387*0Sstevel@tonic-gate */ 388*0Sstevel@tonic-gate addr = pltoff - M_PLT_RESERVSZ; 389*0Sstevel@tonic-gate pltndx = addr / M_PLT_ENTSIZE; 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate /* 392*0Sstevel@tonic-gate * Perform some basic sanity checks. If we didn't get a load map 393*0Sstevel@tonic-gate * or the plt offset is invalid then its possible someone has walked 394*0Sstevel@tonic-gate * over the plt entries or jumped to plt0 out of the blue. 395*0Sstevel@tonic-gate */ 396*0Sstevel@tonic-gate if (!lmp || ((addr % M_PLT_ENTSIZE) != 0)) { 397*0Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_REL_PLTREF), 398*0Sstevel@tonic-gate conv_reloc_SPARC_type_str(R_SPARC_JMP_SLOT), 399*0Sstevel@tonic-gate EC_XWORD(lmp), EC_XWORD(pltoff), EC_ADDR(from)); 400*0Sstevel@tonic-gate rtldexit(LIST(lmp), 1); 401*0Sstevel@tonic-gate } 402*0Sstevel@tonic-gate reloff = pltndx * sizeof (Rela); 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate /* 405*0Sstevel@tonic-gate * Use relocation entry to get symbol table entry and symbol name. 406*0Sstevel@tonic-gate */ 407*0Sstevel@tonic-gate addr = (ulong_t)JMPREL(lmp); 408*0Sstevel@tonic-gate rptr = (Rela *)(addr + reloff); 409*0Sstevel@tonic-gate rsymndx = ELF_R_SYM(rptr->r_info); 410*0Sstevel@tonic-gate sym = (Sym *)((ulong_t)SYMTAB(lmp) + (rsymndx * SYMENT(lmp))); 411*0Sstevel@tonic-gate name = (char *)(STRTAB(lmp) + sym->st_name); 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate /* 414*0Sstevel@tonic-gate * Determine the last link-map of this list, this'll be the starting 415*0Sstevel@tonic-gate * point for any tsort() processing. 416*0Sstevel@tonic-gate */ 417*0Sstevel@tonic-gate llmp = LIST(lmp)->lm_tail; 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate /* 420*0Sstevel@tonic-gate * Find definition for symbol. 421*0Sstevel@tonic-gate */ 422*0Sstevel@tonic-gate sl.sl_name = name; 423*0Sstevel@tonic-gate sl.sl_cmap = lmp; 424*0Sstevel@tonic-gate sl.sl_imap = LIST(lmp)->lm_head; 425*0Sstevel@tonic-gate sl.sl_hash = 0; 426*0Sstevel@tonic-gate sl.sl_rsymndx = rsymndx; 427*0Sstevel@tonic-gate sl.sl_flags = LKUP_DEFT; 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gate if ((nsym = lookup_sym(&sl, &nlmp, &binfo)) == 0) { 430*0Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), 431*0Sstevel@tonic-gate demangle(name)); 432*0Sstevel@tonic-gate rtldexit(LIST(lmp), 1); 433*0Sstevel@tonic-gate } 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate symval = nsym->st_value; 436*0Sstevel@tonic-gate if (!(FLAGS(nlmp) & FLG_RT_FIXED) && 437*0Sstevel@tonic-gate (nsym->st_shndx != SHN_ABS)) 438*0Sstevel@tonic-gate symval += ADDR(nlmp); 439*0Sstevel@tonic-gate if ((lmp != nlmp) && ((FLAGS1(nlmp) & FL1_RT_NOINIFIN) == 0)) { 440*0Sstevel@tonic-gate /* 441*0Sstevel@tonic-gate * Record that this new link map is now bound to the caller. 442*0Sstevel@tonic-gate */ 443*0Sstevel@tonic-gate if (bind_one(lmp, nlmp, BND_REFER) == 0) 444*0Sstevel@tonic-gate rtldexit(LIST(lmp), 1); 445*0Sstevel@tonic-gate } 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate if ((LIST(lmp)->lm_tflags | FLAGS1(lmp)) & LML_TFLG_AUD_SYMBIND) { 448*0Sstevel@tonic-gate ulong_t symndx = (((uintptr_t)nsym - 449*0Sstevel@tonic-gate (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp)); 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate symval = audit_symbind(lmp, nlmp, nsym, symndx, symval, 452*0Sstevel@tonic-gate &sb_flags); 453*0Sstevel@tonic-gate } 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate if (FLAGS(lmp) & FLG_RT_FIXED) 456*0Sstevel@tonic-gate vaddr = 0; 457*0Sstevel@tonic-gate else 458*0Sstevel@tonic-gate vaddr = ADDR(lmp); 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate pbtype = PLT_T_NONE; 461*0Sstevel@tonic-gate if (!(rtld_flags & RT_FL_NOBIND)) { 462*0Sstevel@tonic-gate if (((LIST(lmp)->lm_tflags | FLAGS1(lmp)) & 463*0Sstevel@tonic-gate (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) && 464*0Sstevel@tonic-gate AUDINFO(lmp)->ai_dynplts) { 465*0Sstevel@tonic-gate int fail = 0; 466*0Sstevel@tonic-gate ulong_t symndx = (((uintptr_t)nsym - 467*0Sstevel@tonic-gate (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp)); 468*0Sstevel@tonic-gate 469*0Sstevel@tonic-gate symval = (ulong_t)elf_plt_trace_write((caddr_t)vaddr, 470*0Sstevel@tonic-gate rptr, lmp, nlmp, nsym, symndx, pltndx, 471*0Sstevel@tonic-gate (caddr_t)symval, sb_flags, &fail); 472*0Sstevel@tonic-gate if (fail) 473*0Sstevel@tonic-gate rtldexit(LIST(lmp), 1); 474*0Sstevel@tonic-gate } else { 475*0Sstevel@tonic-gate /* 476*0Sstevel@tonic-gate * Write standard PLT entry to jump directly 477*0Sstevel@tonic-gate * to newly bound function. 478*0Sstevel@tonic-gate */ 479*0Sstevel@tonic-gate pbtype = elf_plt_write((uintptr_t)vaddr, 480*0Sstevel@tonic-gate (uintptr_t)vaddr, rptr, symval, pltndx); 481*0Sstevel@tonic-gate } 482*0Sstevel@tonic-gate } 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate /* 485*0Sstevel@tonic-gate * Print binding information and rebuild PLT entry. 486*0Sstevel@tonic-gate */ 487*0Sstevel@tonic-gate DBG_CALL(Dbg_bind_global(NAME(lmp), from, from - ADDR(lmp), pltndx, 488*0Sstevel@tonic-gate pbtype, NAME(nlmp), (caddr_t)symval, (caddr_t)nsym->st_value, 489*0Sstevel@tonic-gate name, binfo)); 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate /* 492*0Sstevel@tonic-gate * Complete any processing for newly loaded objects. Note we don't 493*0Sstevel@tonic-gate * know exactly where any new objects are loaded (we know the object 494*0Sstevel@tonic-gate * that supplied the symbol, but others may have been loaded lazily as 495*0Sstevel@tonic-gate * we searched for the symbol), so sorting starts from the last 496*0Sstevel@tonic-gate * link-map know on entry to this routine. 497*0Sstevel@tonic-gate */ 498*0Sstevel@tonic-gate if (entry) 499*0Sstevel@tonic-gate load_completion(llmp, lmp); 500*0Sstevel@tonic-gate 501*0Sstevel@tonic-gate /* 502*0Sstevel@tonic-gate * Some operations like dldump() or dlopen()'ing a relocatable object 503*0Sstevel@tonic-gate * result in objects being loaded on rtld's link-map, make sure these 504*0Sstevel@tonic-gate * objects are initialized also. 505*0Sstevel@tonic-gate */ 506*0Sstevel@tonic-gate if ((LIST(nlmp)->lm_flags & LML_FLG_RTLDLM) && LIST(nlmp)->lm_init) 507*0Sstevel@tonic-gate load_completion(nlmp, 0); 508*0Sstevel@tonic-gate 509*0Sstevel@tonic-gate /* 510*0Sstevel@tonic-gate * If the object we've bound to is in the process of being initialized 511*0Sstevel@tonic-gate * by another thread, determine whether we should block. 512*0Sstevel@tonic-gate */ 513*0Sstevel@tonic-gate is_dep_ready(nlmp, lmp, DBG_WAIT_SYMBOL); 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate /* 516*0Sstevel@tonic-gate * Make sure the object to which we've bound has had it's .init fired. 517*0Sstevel@tonic-gate * Cleanup before return to user code. 518*0Sstevel@tonic-gate */ 519*0Sstevel@tonic-gate if (entry) { 520*0Sstevel@tonic-gate is_dep_init(nlmp, lmp); 521*0Sstevel@tonic-gate leave(LIST(lmp)); 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate if (lmflags & LML_FLG_RTLDLM) 525*0Sstevel@tonic-gate dbg_mask = dbg_save; 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gate return (symval); 528*0Sstevel@tonic-gate } 529*0Sstevel@tonic-gate 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate /* 532*0Sstevel@tonic-gate * Read and process the relocations for one link object, we assume all 533*0Sstevel@tonic-gate * relocation sections for loadable segments are stored contiguously in 534*0Sstevel@tonic-gate * the file. 535*0Sstevel@tonic-gate */ 536*0Sstevel@tonic-gate int 537*0Sstevel@tonic-gate elf_reloc(Rt_map *lmp, uint_t plt) 538*0Sstevel@tonic-gate { 539*0Sstevel@tonic-gate ulong_t relbgn, relend, relsiz, basebgn, pltbgn, pltend; 540*0Sstevel@tonic-gate ulong_t roffset, rsymndx, psymndx = 0, etext = ETEXT(lmp); 541*0Sstevel@tonic-gate ulong_t emap, dsymndx, pltndx; 542*0Sstevel@tonic-gate uchar_t rtype; 543*0Sstevel@tonic-gate long reladd, value, pvalue; 544*0Sstevel@tonic-gate Sym *symref, *psymref, *symdef, *psymdef; 545*0Sstevel@tonic-gate char *name, *pname; 546*0Sstevel@tonic-gate Rt_map *_lmp, *plmp; 547*0Sstevel@tonic-gate int textrel = 0, ret = 1, noplt = 0; 548*0Sstevel@tonic-gate long relacount = RELACOUNT(lmp); 549*0Sstevel@tonic-gate Rela *rel; 550*0Sstevel@tonic-gate Pltbindtype pbtype; 551*0Sstevel@tonic-gate uint_t binfo, pbinfo; 552*0Sstevel@tonic-gate Alist *bound = 0; 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate /* 555*0Sstevel@tonic-gate * If an object has any DT_REGISTER entries associated with 556*0Sstevel@tonic-gate * it, they are processed now. 557*0Sstevel@tonic-gate */ 558*0Sstevel@tonic-gate if ((plt == 0) && (FLAGS(lmp) & FLG_RT_REGSYMS)) { 559*0Sstevel@tonic-gate if (elf_regsyms(lmp) == 0) 560*0Sstevel@tonic-gate return (0); 561*0Sstevel@tonic-gate } 562*0Sstevel@tonic-gate 563*0Sstevel@tonic-gate /* 564*0Sstevel@tonic-gate * Although only necessary for lazy binding, initialize the first 565*0Sstevel@tonic-gate * procedure linkage table entry to go to elf_rtbndr(). dbx(1) seems 566*0Sstevel@tonic-gate * to find this useful. 567*0Sstevel@tonic-gate */ 568*0Sstevel@tonic-gate if ((plt == 0) && PLTGOT(lmp)) { 569*0Sstevel@tonic-gate if ((ulong_t)PLTGOT(lmp) < etext) { 570*0Sstevel@tonic-gate if (elf_set_prot(lmp, PROT_WRITE) == 0) 571*0Sstevel@tonic-gate return (0); 572*0Sstevel@tonic-gate textrel = 1; 573*0Sstevel@tonic-gate } 574*0Sstevel@tonic-gate elf_plt_init(PLTGOT(lmp), (caddr_t)lmp); 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate /* 578*0Sstevel@tonic-gate * Initialize the plt start and end addresses. 579*0Sstevel@tonic-gate */ 580*0Sstevel@tonic-gate if ((pltbgn = (ulong_t)JMPREL(lmp)) != 0) 581*0Sstevel@tonic-gate pltend = pltbgn + (ulong_t)(PLTRELSZ(lmp)); 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate /* 584*0Sstevel@tonic-gate * If we've been called upon to promote an RTLD_LAZY object to an 585*0Sstevel@tonic-gate * RTLD_NOW then we're only interested in scaning the .plt table. 586*0Sstevel@tonic-gate */ 587*0Sstevel@tonic-gate if (plt) { 588*0Sstevel@tonic-gate relbgn = pltbgn; 589*0Sstevel@tonic-gate relend = pltend; 590*0Sstevel@tonic-gate } else { 591*0Sstevel@tonic-gate /* 592*0Sstevel@tonic-gate * The relocation sections appear to the run-time linker as a 593*0Sstevel@tonic-gate * single table. Determine the address of the beginning and end 594*0Sstevel@tonic-gate * of this table. There are two different interpretations of 595*0Sstevel@tonic-gate * the ABI at this point: 596*0Sstevel@tonic-gate * 597*0Sstevel@tonic-gate * o The REL table and its associated RELSZ indicate the 598*0Sstevel@tonic-gate * concatenation of *all* relocation sections (this is the 599*0Sstevel@tonic-gate * model our link-editor constructs). 600*0Sstevel@tonic-gate * 601*0Sstevel@tonic-gate * o The REL table and its associated RELSZ indicate the 602*0Sstevel@tonic-gate * concatenation of all *but* the .plt relocations. These 603*0Sstevel@tonic-gate * relocations are specified individually by the JMPREL and 604*0Sstevel@tonic-gate * PLTRELSZ entries. 605*0Sstevel@tonic-gate * 606*0Sstevel@tonic-gate * Determine from our knowledege of the relocation range and 607*0Sstevel@tonic-gate * .plt range, the range of the total relocation table. Note 608*0Sstevel@tonic-gate * that one other ABI assumption seems to be that the .plt 609*0Sstevel@tonic-gate * relocations always follow any other relocations, the 610*0Sstevel@tonic-gate * following range checking drops that assumption. 611*0Sstevel@tonic-gate */ 612*0Sstevel@tonic-gate relbgn = (ulong_t)(REL(lmp)); 613*0Sstevel@tonic-gate relend = relbgn + (ulong_t)(RELSZ(lmp)); 614*0Sstevel@tonic-gate if (pltbgn) { 615*0Sstevel@tonic-gate if (!relbgn || (relbgn > pltbgn)) 616*0Sstevel@tonic-gate relbgn = pltbgn; 617*0Sstevel@tonic-gate if (!relbgn || (relend < pltend)) 618*0Sstevel@tonic-gate relend = pltend; 619*0Sstevel@tonic-gate } 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate if (!relbgn || (relbgn == relend)) { 622*0Sstevel@tonic-gate DBG_CALL(Dbg_reloc_run(NAME(lmp), 0, plt, DBG_REL_NONE)); 623*0Sstevel@tonic-gate return (1); 624*0Sstevel@tonic-gate } 625*0Sstevel@tonic-gate 626*0Sstevel@tonic-gate relsiz = (ulong_t)(RELENT(lmp)); 627*0Sstevel@tonic-gate basebgn = ADDR(lmp); 628*0Sstevel@tonic-gate emap = ADDR(lmp) + MSIZE(lmp); 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate DBG_CALL(Dbg_reloc_run(NAME(lmp), M_REL_SHT_TYPE, plt, DBG_REL_START)); 631*0Sstevel@tonic-gate 632*0Sstevel@tonic-gate /* 633*0Sstevel@tonic-gate * If we're processing in lazy mode there is no need to scan the 634*0Sstevel@tonic-gate * .rela.plt table. 635*0Sstevel@tonic-gate */ 636*0Sstevel@tonic-gate if (pltbgn && ((MODE(lmp) & RTLD_NOW) == 0)) 637*0Sstevel@tonic-gate noplt = 1; 638*0Sstevel@tonic-gate 639*0Sstevel@tonic-gate /* 640*0Sstevel@tonic-gate * Loop through relocations. 641*0Sstevel@tonic-gate */ 642*0Sstevel@tonic-gate while (relbgn < relend) { 643*0Sstevel@tonic-gate Addr vaddr; 644*0Sstevel@tonic-gate uint_t sb_flags = 0; 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info); 647*0Sstevel@tonic-gate 648*0Sstevel@tonic-gate /* 649*0Sstevel@tonic-gate * If this is a RELATIVE relocation in a shared object (the 650*0Sstevel@tonic-gate * common case), and if we are not debugging, then jump into a 651*0Sstevel@tonic-gate * tighter relocation loop (elf_reloc_relative). Only make the 652*0Sstevel@tonic-gate * jump if we've been given a hint on the number of relocations. 653*0Sstevel@tonic-gate */ 654*0Sstevel@tonic-gate if ((rtype == R_SPARC_RELATIVE) && 655*0Sstevel@tonic-gate !(FLAGS(lmp) & FLG_RT_FIXED) && !dbg_mask) { 656*0Sstevel@tonic-gate /* 657*0Sstevel@tonic-gate * It's possible that the relative relocation block 658*0Sstevel@tonic-gate * has relocations against the text segment as well 659*0Sstevel@tonic-gate * as the data segment. Since our optimized relocation 660*0Sstevel@tonic-gate * engine does not check which segment the relocation 661*0Sstevel@tonic-gate * is against - just mprotect it now if it's been 662*0Sstevel@tonic-gate * marked as containing TEXTREL's. 663*0Sstevel@tonic-gate */ 664*0Sstevel@tonic-gate if ((textrel == 0) && (FLAGS1(lmp) & FL1_RT_TEXTREL)) { 665*0Sstevel@tonic-gate if (elf_set_prot(lmp, PROT_WRITE) == 0) { 666*0Sstevel@tonic-gate ret = 0; 667*0Sstevel@tonic-gate break; 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate textrel = 1; 670*0Sstevel@tonic-gate } 671*0Sstevel@tonic-gate if (relacount) { 672*0Sstevel@tonic-gate relbgn = elf_reloc_relacount(relbgn, relacount, 673*0Sstevel@tonic-gate relsiz, basebgn); 674*0Sstevel@tonic-gate relacount = 0; 675*0Sstevel@tonic-gate } else { 676*0Sstevel@tonic-gate relbgn = elf_reloc_relative(relbgn, relend, 677*0Sstevel@tonic-gate relsiz, basebgn, etext, emap); 678*0Sstevel@tonic-gate } 679*0Sstevel@tonic-gate if (relbgn >= relend) 680*0Sstevel@tonic-gate break; 681*0Sstevel@tonic-gate rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info); 682*0Sstevel@tonic-gate } 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gate roffset = ((Rela *)relbgn)->r_offset; 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gate reladd = (long)(((Rela *)relbgn)->r_addend); 687*0Sstevel@tonic-gate rsymndx = ELF_R_SYM(((Rela *)relbgn)->r_info); 688*0Sstevel@tonic-gate 689*0Sstevel@tonic-gate rel = (Rela *)relbgn; 690*0Sstevel@tonic-gate relbgn += relsiz; 691*0Sstevel@tonic-gate 692*0Sstevel@tonic-gate /* 693*0Sstevel@tonic-gate * Optimizations. 694*0Sstevel@tonic-gate */ 695*0Sstevel@tonic-gate if (rtype == R_SPARC_NONE) 696*0Sstevel@tonic-gate continue; 697*0Sstevel@tonic-gate if (noplt && ((ulong_t)rel >= pltbgn) && 698*0Sstevel@tonic-gate ((ulong_t)rel < pltend)) { 699*0Sstevel@tonic-gate relbgn = pltend; 700*0Sstevel@tonic-gate continue; 701*0Sstevel@tonic-gate } 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate if (rtype != R_SPARC_REGISTER) { 704*0Sstevel@tonic-gate /* 705*0Sstevel@tonic-gate * If this is a shared object, add the base address 706*0Sstevel@tonic-gate * to offset. 707*0Sstevel@tonic-gate */ 708*0Sstevel@tonic-gate if (!(FLAGS(lmp) & FLG_RT_FIXED)) 709*0Sstevel@tonic-gate roffset += basebgn; 710*0Sstevel@tonic-gate 711*0Sstevel@tonic-gate /* 712*0Sstevel@tonic-gate * If this relocation is not against part of the image 713*0Sstevel@tonic-gate * mapped into memory we skip it. 714*0Sstevel@tonic-gate */ 715*0Sstevel@tonic-gate if ((roffset < ADDR(lmp)) || (roffset > (ADDR(lmp) + 716*0Sstevel@tonic-gate MSIZE(lmp)))) { 717*0Sstevel@tonic-gate elf_reloc_bad(lmp, (void *)rel, rtype, roffset, 718*0Sstevel@tonic-gate rsymndx); 719*0Sstevel@tonic-gate continue; 720*0Sstevel@tonic-gate } 721*0Sstevel@tonic-gate } 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate /* 724*0Sstevel@tonic-gate * If we're promoting plts determine if this one has already 725*0Sstevel@tonic-gate * been written. An uninitialized plts' second instruction is a 726*0Sstevel@tonic-gate * branch. 727*0Sstevel@tonic-gate */ 728*0Sstevel@tonic-gate if (plt) { 729*0Sstevel@tonic-gate ulong_t *_roffset = (ulong_t *)roffset; 730*0Sstevel@tonic-gate 731*0Sstevel@tonic-gate _roffset++; 732*0Sstevel@tonic-gate if ((*_roffset & (~(S_MASK(22)))) != M_BA_A) 733*0Sstevel@tonic-gate continue; 734*0Sstevel@tonic-gate } 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gate binfo = 0; 737*0Sstevel@tonic-gate pltndx = (ulong_t)-1; 738*0Sstevel@tonic-gate pbtype = PLT_T_NONE; 739*0Sstevel@tonic-gate /* 740*0Sstevel@tonic-gate * If a symbol index is specified then get the symbol table 741*0Sstevel@tonic-gate * entry, locate the symbol definition, and determine its 742*0Sstevel@tonic-gate * address. 743*0Sstevel@tonic-gate */ 744*0Sstevel@tonic-gate if (rsymndx) { 745*0Sstevel@tonic-gate /* 746*0Sstevel@tonic-gate * Get the local symbol table entry. 747*0Sstevel@tonic-gate */ 748*0Sstevel@tonic-gate symref = (Sym *)((ulong_t)SYMTAB(lmp) + 749*0Sstevel@tonic-gate (rsymndx * SYMENT(lmp))); 750*0Sstevel@tonic-gate 751*0Sstevel@tonic-gate /* 752*0Sstevel@tonic-gate * If this is a local symbol, just use the base address. 753*0Sstevel@tonic-gate * (we should have no local relocations in the 754*0Sstevel@tonic-gate * executable). 755*0Sstevel@tonic-gate */ 756*0Sstevel@tonic-gate if (ELF_ST_BIND(symref->st_info) == STB_LOCAL) { 757*0Sstevel@tonic-gate value = basebgn; 758*0Sstevel@tonic-gate name = (char *)0; 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate /* 761*0Sstevel@tonic-gate * TLS relocation - value for DTPMOD relocation 762*0Sstevel@tonic-gate * is the TLS modid. 763*0Sstevel@tonic-gate */ 764*0Sstevel@tonic-gate if (rtype == M_R_DTPMOD) 765*0Sstevel@tonic-gate value = TLSMODID(lmp); 766*0Sstevel@tonic-gate } else { 767*0Sstevel@tonic-gate /* 768*0Sstevel@tonic-gate * If the symbol index is equal to the previous 769*0Sstevel@tonic-gate * symbol index relocation we processed then 770*0Sstevel@tonic-gate * reuse the previous values. (Note that there 771*0Sstevel@tonic-gate * have been cases where a relocation exists 772*0Sstevel@tonic-gate * against a copy relocation symbol, our ld(1) 773*0Sstevel@tonic-gate * should optimize this away, but make sure we 774*0Sstevel@tonic-gate * don't use the same symbol information should 775*0Sstevel@tonic-gate * this case exist). 776*0Sstevel@tonic-gate */ 777*0Sstevel@tonic-gate if ((rsymndx == psymndx) && 778*0Sstevel@tonic-gate (rtype != R_SPARC_COPY)) { 779*0Sstevel@tonic-gate /* LINTED */ 780*0Sstevel@tonic-gate if (psymdef == 0) { 781*0Sstevel@tonic-gate DBG_CALL(Dbg_bind_weak( 782*0Sstevel@tonic-gate NAME(lmp), (caddr_t)roffset, 783*0Sstevel@tonic-gate (caddr_t) 784*0Sstevel@tonic-gate (roffset - basebgn), name)); 785*0Sstevel@tonic-gate continue; 786*0Sstevel@tonic-gate } 787*0Sstevel@tonic-gate /* LINTED */ 788*0Sstevel@tonic-gate value = pvalue; 789*0Sstevel@tonic-gate /* LINTED */ 790*0Sstevel@tonic-gate name = pname; 791*0Sstevel@tonic-gate symdef = psymdef; 792*0Sstevel@tonic-gate /* LINTED */ 793*0Sstevel@tonic-gate symref = psymref; 794*0Sstevel@tonic-gate /* LINTED */ 795*0Sstevel@tonic-gate _lmp = plmp; 796*0Sstevel@tonic-gate /* LINTED */ 797*0Sstevel@tonic-gate binfo = pbinfo; 798*0Sstevel@tonic-gate 799*0Sstevel@tonic-gate if ((LIST(_lmp)->lm_tflags | 800*0Sstevel@tonic-gate FLAGS1(_lmp)) & 801*0Sstevel@tonic-gate LML_TFLG_AUD_SYMBIND) { 802*0Sstevel@tonic-gate value = audit_symbind(lmp, _lmp, 803*0Sstevel@tonic-gate /* LINTED */ 804*0Sstevel@tonic-gate symdef, dsymndx, value, 805*0Sstevel@tonic-gate &sb_flags); 806*0Sstevel@tonic-gate } 807*0Sstevel@tonic-gate } else { 808*0Sstevel@tonic-gate Slookup sl; 809*0Sstevel@tonic-gate uchar_t bind; 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gate /* 812*0Sstevel@tonic-gate * Lookup the symbol definition. 813*0Sstevel@tonic-gate */ 814*0Sstevel@tonic-gate name = (char *)(STRTAB(lmp) + 815*0Sstevel@tonic-gate symref->st_name); 816*0Sstevel@tonic-gate 817*0Sstevel@tonic-gate sl.sl_name = name; 818*0Sstevel@tonic-gate sl.sl_cmap = lmp; 819*0Sstevel@tonic-gate sl.sl_imap = 0; 820*0Sstevel@tonic-gate sl.sl_hash = 0; 821*0Sstevel@tonic-gate sl.sl_rsymndx = rsymndx; 822*0Sstevel@tonic-gate 823*0Sstevel@tonic-gate if (rtype == R_SPARC_COPY) 824*0Sstevel@tonic-gate sl.sl_flags = LKUP_COPY; 825*0Sstevel@tonic-gate else 826*0Sstevel@tonic-gate sl.sl_flags = LKUP_DEFT; 827*0Sstevel@tonic-gate 828*0Sstevel@tonic-gate sl.sl_flags |= LKUP_ALLCNTLIST; 829*0Sstevel@tonic-gate 830*0Sstevel@tonic-gate if (rtype != R_SPARC_JMP_SLOT) 831*0Sstevel@tonic-gate sl.sl_flags |= LKUP_SPEC; 832*0Sstevel@tonic-gate 833*0Sstevel@tonic-gate bind = ELF_ST_BIND(symref->st_info); 834*0Sstevel@tonic-gate if (bind == STB_WEAK) 835*0Sstevel@tonic-gate sl.sl_flags |= LKUP_WEAK; 836*0Sstevel@tonic-gate 837*0Sstevel@tonic-gate symdef = lookup_sym(&sl, &_lmp, &binfo); 838*0Sstevel@tonic-gate 839*0Sstevel@tonic-gate /* 840*0Sstevel@tonic-gate * If the symbol is not found and the 841*0Sstevel@tonic-gate * reference was not to a weak symbol, 842*0Sstevel@tonic-gate * report an error. Weak references 843*0Sstevel@tonic-gate * may be unresolved. 844*0Sstevel@tonic-gate */ 845*0Sstevel@tonic-gate if (symdef == 0) { 846*0Sstevel@tonic-gate if (bind != STB_WEAK) { 847*0Sstevel@tonic-gate if (LIST(lmp)->lm_flags & 848*0Sstevel@tonic-gate LML_FLG_IGNRELERR) { 849*0Sstevel@tonic-gate continue; 850*0Sstevel@tonic-gate } else if (LIST(lmp)->lm_flags & 851*0Sstevel@tonic-gate LML_FLG_TRC_WARN) { 852*0Sstevel@tonic-gate (void) printf(MSG_INTL( 853*0Sstevel@tonic-gate MSG_LDD_SYM_NFOUND), 854*0Sstevel@tonic-gate demangle(name), 855*0Sstevel@tonic-gate NAME(lmp)); 856*0Sstevel@tonic-gate continue; 857*0Sstevel@tonic-gate } else { 858*0Sstevel@tonic-gate eprintf(ERR_FATAL, 859*0Sstevel@tonic-gate MSG_INTL(MSG_REL_NOSYM), 860*0Sstevel@tonic-gate NAME(lmp), 861*0Sstevel@tonic-gate demangle(name)); 862*0Sstevel@tonic-gate ret = 0; 863*0Sstevel@tonic-gate break; 864*0Sstevel@tonic-gate } 865*0Sstevel@tonic-gate } else { 866*0Sstevel@tonic-gate psymndx = rsymndx; 867*0Sstevel@tonic-gate psymdef = 0; 868*0Sstevel@tonic-gate 869*0Sstevel@tonic-gate DBG_CALL(Dbg_bind_weak( 870*0Sstevel@tonic-gate NAME(lmp), (caddr_t)roffset, 871*0Sstevel@tonic-gate (caddr_t) 872*0Sstevel@tonic-gate (roffset - basebgn), name)); 873*0Sstevel@tonic-gate continue; 874*0Sstevel@tonic-gate } 875*0Sstevel@tonic-gate } 876*0Sstevel@tonic-gate 877*0Sstevel@tonic-gate /* 878*0Sstevel@tonic-gate * If symbol was found in an object 879*0Sstevel@tonic-gate * other than the referencing object 880*0Sstevel@tonic-gate * then record the binding. 881*0Sstevel@tonic-gate */ 882*0Sstevel@tonic-gate if ((lmp != _lmp) && ((FLAGS1(_lmp) & 883*0Sstevel@tonic-gate FL1_RT_NOINIFIN) == 0)) { 884*0Sstevel@tonic-gate if (alist_test(&bound, _lmp, 885*0Sstevel@tonic-gate sizeof (Rt_map *), 886*0Sstevel@tonic-gate AL_CNT_RELBIND) == 0) { 887*0Sstevel@tonic-gate ret = 0; 888*0Sstevel@tonic-gate break; 889*0Sstevel@tonic-gate } 890*0Sstevel@tonic-gate } 891*0Sstevel@tonic-gate 892*0Sstevel@tonic-gate /* 893*0Sstevel@tonic-gate * Calculate the location of definition; 894*0Sstevel@tonic-gate * symbol value plus base address of 895*0Sstevel@tonic-gate * containing shared object. 896*0Sstevel@tonic-gate */ 897*0Sstevel@tonic-gate value = symdef->st_value; 898*0Sstevel@tonic-gate if (!(FLAGS(_lmp) & FLG_RT_FIXED) && 899*0Sstevel@tonic-gate (symdef->st_shndx != SHN_ABS) && 900*0Sstevel@tonic-gate (ELF_ST_TYPE(symdef->st_info) != 901*0Sstevel@tonic-gate STT_TLS)) 902*0Sstevel@tonic-gate value += ADDR(_lmp); 903*0Sstevel@tonic-gate 904*0Sstevel@tonic-gate /* 905*0Sstevel@tonic-gate * Retain this symbol index and the 906*0Sstevel@tonic-gate * value in case it can be used for the 907*0Sstevel@tonic-gate * subsequent relocations. 908*0Sstevel@tonic-gate */ 909*0Sstevel@tonic-gate if (rtype != R_SPARC_COPY) { 910*0Sstevel@tonic-gate psymndx = rsymndx; 911*0Sstevel@tonic-gate pvalue = value; 912*0Sstevel@tonic-gate pname = name; 913*0Sstevel@tonic-gate psymdef = symdef; 914*0Sstevel@tonic-gate psymref = symref; 915*0Sstevel@tonic-gate plmp = _lmp; 916*0Sstevel@tonic-gate pbinfo = binfo; 917*0Sstevel@tonic-gate } 918*0Sstevel@tonic-gate if ((LIST(_lmp)->lm_tflags | 919*0Sstevel@tonic-gate FLAGS1(_lmp)) & 920*0Sstevel@tonic-gate LML_TFLG_AUD_SYMBIND) { 921*0Sstevel@tonic-gate dsymndx = (((uintptr_t)symdef - 922*0Sstevel@tonic-gate (uintptr_t)SYMTAB(_lmp)) / 923*0Sstevel@tonic-gate SYMENT(_lmp)); 924*0Sstevel@tonic-gate value = audit_symbind(lmp, _lmp, 925*0Sstevel@tonic-gate symdef, dsymndx, value, 926*0Sstevel@tonic-gate &sb_flags); 927*0Sstevel@tonic-gate } 928*0Sstevel@tonic-gate } 929*0Sstevel@tonic-gate 930*0Sstevel@tonic-gate /* 931*0Sstevel@tonic-gate * If relocation is PC-relative, subtract 932*0Sstevel@tonic-gate * offset address. 933*0Sstevel@tonic-gate */ 934*0Sstevel@tonic-gate if (IS_PC_RELATIVE(rtype)) 935*0Sstevel@tonic-gate value -= roffset; 936*0Sstevel@tonic-gate 937*0Sstevel@tonic-gate /* 938*0Sstevel@tonic-gate * TLS relocation - value for DTPMOD relocation 939*0Sstevel@tonic-gate * is the TLS modid. 940*0Sstevel@tonic-gate */ 941*0Sstevel@tonic-gate if (rtype == M_R_DTPMOD) 942*0Sstevel@tonic-gate value = TLSMODID(_lmp); 943*0Sstevel@tonic-gate else if (rtype == M_R_TPOFF) 944*0Sstevel@tonic-gate value = -(TLSSTATOFF(_lmp) - value); 945*0Sstevel@tonic-gate } 946*0Sstevel@tonic-gate } else { 947*0Sstevel@tonic-gate /* 948*0Sstevel@tonic-gate * Special cases, a register symbol associated with 949*0Sstevel@tonic-gate * symbol index 0 is initialized (i.e. relocated) to 950*0Sstevel@tonic-gate * a constant in the r_addend field rather than to a 951*0Sstevel@tonic-gate * symbol value. 952*0Sstevel@tonic-gate * 953*0Sstevel@tonic-gate * A DTPMOD relocation is a local binding to a TLS 954*0Sstevel@tonic-gate * symbol. Fill in the TLSMODID for the current object. 955*0Sstevel@tonic-gate */ 956*0Sstevel@tonic-gate if (rtype == R_SPARC_REGISTER) 957*0Sstevel@tonic-gate value = 0; 958*0Sstevel@tonic-gate else if (rtype == M_R_DTPMOD) 959*0Sstevel@tonic-gate value = TLSMODID(lmp); 960*0Sstevel@tonic-gate else 961*0Sstevel@tonic-gate value = basebgn; 962*0Sstevel@tonic-gate name = (char *)0; 963*0Sstevel@tonic-gate } 964*0Sstevel@tonic-gate 965*0Sstevel@tonic-gate /* 966*0Sstevel@tonic-gate * If this object has relocations in the text segment, turn 967*0Sstevel@tonic-gate * off the write protect. 968*0Sstevel@tonic-gate */ 969*0Sstevel@tonic-gate if ((rtype != R_SPARC_REGISTER) && (roffset < etext) && 970*0Sstevel@tonic-gate (textrel == 0)) { 971*0Sstevel@tonic-gate if (elf_set_prot(lmp, PROT_WRITE) == 0) { 972*0Sstevel@tonic-gate ret = 0; 973*0Sstevel@tonic-gate break; 974*0Sstevel@tonic-gate } 975*0Sstevel@tonic-gate textrel = 1; 976*0Sstevel@tonic-gate } 977*0Sstevel@tonic-gate 978*0Sstevel@tonic-gate /* 979*0Sstevel@tonic-gate * Call relocation routine to perform required relocation. 980*0Sstevel@tonic-gate */ 981*0Sstevel@tonic-gate DBG_CALL(Dbg_reloc_in(M_MACH, M_REL_SHT_TYPE, rel, name, NULL)); 982*0Sstevel@tonic-gate 983*0Sstevel@tonic-gate switch (rtype) { 984*0Sstevel@tonic-gate case R_SPARC_REGISTER: 985*0Sstevel@tonic-gate /* 986*0Sstevel@tonic-gate * The v9 ABI 4.2.4 says that system objects may, 987*0Sstevel@tonic-gate * but are not required to, use register symbols 988*0Sstevel@tonic-gate * to inidcate how they use global registers. Thus 989*0Sstevel@tonic-gate * at least %g6, %g7 must be allowed in addition 990*0Sstevel@tonic-gate * to %g2 and %g3. 991*0Sstevel@tonic-gate */ 992*0Sstevel@tonic-gate value += reladd; 993*0Sstevel@tonic-gate if (roffset == STO_SPARC_REGISTER_G1) { 994*0Sstevel@tonic-gate set_sparc_g1(value); 995*0Sstevel@tonic-gate } else if (roffset == STO_SPARC_REGISTER_G2) { 996*0Sstevel@tonic-gate set_sparc_g2(value); 997*0Sstevel@tonic-gate } else if (roffset == STO_SPARC_REGISTER_G3) { 998*0Sstevel@tonic-gate set_sparc_g3(value); 999*0Sstevel@tonic-gate } else if (roffset == STO_SPARC_REGISTER_G4) { 1000*0Sstevel@tonic-gate set_sparc_g4(value); 1001*0Sstevel@tonic-gate } else if (roffset == STO_SPARC_REGISTER_G5) { 1002*0Sstevel@tonic-gate set_sparc_g5(value); 1003*0Sstevel@tonic-gate } else if (roffset == STO_SPARC_REGISTER_G6) { 1004*0Sstevel@tonic-gate set_sparc_g6(value); 1005*0Sstevel@tonic-gate } else if (roffset == STO_SPARC_REGISTER_G7) { 1006*0Sstevel@tonic-gate set_sparc_g7(value); 1007*0Sstevel@tonic-gate } else { 1008*0Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_REL_BADREG), 1009*0Sstevel@tonic-gate NAME(lmp), EC_ADDR(roffset)); 1010*0Sstevel@tonic-gate ret = 0; 1011*0Sstevel@tonic-gate break; 1012*0Sstevel@tonic-gate } 1013*0Sstevel@tonic-gate 1014*0Sstevel@tonic-gate DBG_CALL(Dbg_reloc_reg_apply((Xword)roffset, 1015*0Sstevel@tonic-gate (Xword)value)); 1016*0Sstevel@tonic-gate break; 1017*0Sstevel@tonic-gate case R_SPARC_COPY: 1018*0Sstevel@tonic-gate if (elf_copy_reloc(name, symref, lmp, (void *)roffset, 1019*0Sstevel@tonic-gate symdef, _lmp, (const void *)value) == 0) 1020*0Sstevel@tonic-gate ret = 0; 1021*0Sstevel@tonic-gate break; 1022*0Sstevel@tonic-gate case R_SPARC_JMP_SLOT: 1023*0Sstevel@tonic-gate pltndx = ((ulong_t)rel - 1024*0Sstevel@tonic-gate (uintptr_t)JMPREL(lmp)) / relsiz; 1025*0Sstevel@tonic-gate 1026*0Sstevel@tonic-gate if (FLAGS(lmp) & FLG_RT_FIXED) 1027*0Sstevel@tonic-gate vaddr = 0; 1028*0Sstevel@tonic-gate else 1029*0Sstevel@tonic-gate vaddr = ADDR(lmp); 1030*0Sstevel@tonic-gate 1031*0Sstevel@tonic-gate if (((LIST(lmp)->lm_tflags | FLAGS1(lmp)) & 1032*0Sstevel@tonic-gate (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) && 1033*0Sstevel@tonic-gate AUDINFO(lmp)->ai_dynplts) { 1034*0Sstevel@tonic-gate int fail = 0; 1035*0Sstevel@tonic-gate ulong_t symndx = (((uintptr_t)symdef - 1036*0Sstevel@tonic-gate (uintptr_t)SYMTAB(_lmp)) / 1037*0Sstevel@tonic-gate SYMENT(_lmp)); 1038*0Sstevel@tonic-gate 1039*0Sstevel@tonic-gate (void) elf_plt_trace_write((caddr_t)vaddr, 1040*0Sstevel@tonic-gate (Rela *)rel, lmp, _lmp, symdef, symndx, 1041*0Sstevel@tonic-gate pltndx, (caddr_t)value, sb_flags, &fail); 1042*0Sstevel@tonic-gate if (fail) 1043*0Sstevel@tonic-gate ret = 0; 1044*0Sstevel@tonic-gate } else { 1045*0Sstevel@tonic-gate /* 1046*0Sstevel@tonic-gate * Write standard PLT entry to jump directly 1047*0Sstevel@tonic-gate * to newly bound function. 1048*0Sstevel@tonic-gate */ 1049*0Sstevel@tonic-gate DBG_CALL(Dbg_reloc_apply((Xword)roffset, 1050*0Sstevel@tonic-gate (Xword)value)); 1051*0Sstevel@tonic-gate pbtype = elf_plt_write((uintptr_t)vaddr, 1052*0Sstevel@tonic-gate (uintptr_t)vaddr, (void *)rel, value, 1053*0Sstevel@tonic-gate pltndx); 1054*0Sstevel@tonic-gate } 1055*0Sstevel@tonic-gate break; 1056*0Sstevel@tonic-gate default: 1057*0Sstevel@tonic-gate value += reladd; 1058*0Sstevel@tonic-gate 1059*0Sstevel@tonic-gate /* 1060*0Sstevel@tonic-gate * Write the relocation out. If this relocation is a 1061*0Sstevel@tonic-gate * common basic write, skip the doreloc() engine. 1062*0Sstevel@tonic-gate */ 1063*0Sstevel@tonic-gate if ((rtype == R_SPARC_GLOB_DAT) || 1064*0Sstevel@tonic-gate (rtype == R_SPARC_32)) { 1065*0Sstevel@tonic-gate if (roffset & 0x3) { 1066*0Sstevel@tonic-gate eprintf(ERR_FATAL, 1067*0Sstevel@tonic-gate MSG_INTL(MSG_REL_NONALIGN), 1068*0Sstevel@tonic-gate conv_reloc_SPARC_type_str(rtype), 1069*0Sstevel@tonic-gate NAME(lmp), demangle(name), 1070*0Sstevel@tonic-gate EC_OFF(roffset)); 1071*0Sstevel@tonic-gate ret = 0; 1072*0Sstevel@tonic-gate } else 1073*0Sstevel@tonic-gate *(uint_t *)roffset += value; 1074*0Sstevel@tonic-gate } else { 1075*0Sstevel@tonic-gate if (do_reloc(rtype, (uchar_t *)roffset, 1076*0Sstevel@tonic-gate (Xword *)&value, name, NAME(lmp)) == 0) 1077*0Sstevel@tonic-gate ret = 0; 1078*0Sstevel@tonic-gate } 1079*0Sstevel@tonic-gate 1080*0Sstevel@tonic-gate /* 1081*0Sstevel@tonic-gate * The value now contains the 'bit-shifted' value that 1082*0Sstevel@tonic-gate * was or'ed into memory (this was set by do_reloc()). 1083*0Sstevel@tonic-gate */ 1084*0Sstevel@tonic-gate DBG_CALL(Dbg_reloc_apply((Xword)roffset, 1085*0Sstevel@tonic-gate (Xword)value)); 1086*0Sstevel@tonic-gate 1087*0Sstevel@tonic-gate /* 1088*0Sstevel@tonic-gate * If this relocation is against a text segment, make 1089*0Sstevel@tonic-gate * sure that the instruction cache is flushed. 1090*0Sstevel@tonic-gate */ 1091*0Sstevel@tonic-gate if (textrel) 1092*0Sstevel@tonic-gate iflush_range((caddr_t)roffset, 0x4); 1093*0Sstevel@tonic-gate } 1094*0Sstevel@tonic-gate 1095*0Sstevel@tonic-gate if ((ret == 0) && 1096*0Sstevel@tonic-gate ((LIST(lmp)->lm_flags & LML_FLG_TRC_WARN) == 0)) 1097*0Sstevel@tonic-gate break; 1098*0Sstevel@tonic-gate 1099*0Sstevel@tonic-gate if (binfo) { 1100*0Sstevel@tonic-gate DBG_CALL(Dbg_bind_global(NAME(lmp), (caddr_t)roffset, 1101*0Sstevel@tonic-gate (caddr_t)(roffset - basebgn), pltndx, pbtype, 1102*0Sstevel@tonic-gate NAME(_lmp), (caddr_t)value, 1103*0Sstevel@tonic-gate (caddr_t)symdef->st_value, name, binfo)); 1104*0Sstevel@tonic-gate } 1105*0Sstevel@tonic-gate } 1106*0Sstevel@tonic-gate 1107*0Sstevel@tonic-gate return (relocate_finish(lmp, bound, textrel, ret)); 1108*0Sstevel@tonic-gate } 1109*0Sstevel@tonic-gate 1110*0Sstevel@tonic-gate /* 1111*0Sstevel@tonic-gate * Provide a machine specific interface to the conversion routine. By calling 1112*0Sstevel@tonic-gate * the machine specific version, rather than the generic version, we insure that 1113*0Sstevel@tonic-gate * the data tables/strings for all known machine versions aren't dragged into 1114*0Sstevel@tonic-gate * ld.so.1. 1115*0Sstevel@tonic-gate */ 1116*0Sstevel@tonic-gate const char * 1117*0Sstevel@tonic-gate _conv_reloc_type_str(uint_t rel) 1118*0Sstevel@tonic-gate { 1119*0Sstevel@tonic-gate return (conv_reloc_SPARC_type_str(rel)); 1120*0Sstevel@tonic-gate } 1121