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 55aefb655Srie * Common Development and Distribution License (the "License"). 65aefb655Srie * 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 */ 215aefb655Srie 227c478bd9Sstevel@tonic-gate /* 23f441771bSRod Evans * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 24*38f4bdddSBryan Cantrill * Copyright (c) 2012, Joyent, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate */ 267257d1b4Sraf 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * SPARC V9 machine dependent and ELF file class dependent functions. 297c478bd9Sstevel@tonic-gate * Contains routines for performing function binding and symbol relocations. 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <stdio.h> 337c478bd9Sstevel@tonic-gate #include <sys/elf.h> 347c478bd9Sstevel@tonic-gate #include <sys/elf_SPARC.h> 357c478bd9Sstevel@tonic-gate #include <sys/mman.h> 367c478bd9Sstevel@tonic-gate #include <dlfcn.h> 377c478bd9Sstevel@tonic-gate #include <synch.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 395aefb655Srie #include <debug.h> 405aefb655Srie #include <reloc.h> 415aefb655Srie #include <conv.h> 427c478bd9Sstevel@tonic-gate #include "_rtld.h" 437c478bd9Sstevel@tonic-gate #include "_audit.h" 447c478bd9Sstevel@tonic-gate #include "_elf.h" 45f441771bSRod Evans #include "_inline_gen.h" 46f441771bSRod Evans #include "_inline_reloc.h" 477c478bd9Sstevel@tonic-gate #include "msg.h" 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate extern void iflush_range(caddr_t, size_t); 507c478bd9Sstevel@tonic-gate extern void plt_upper_32(uintptr_t, uintptr_t); 517c478bd9Sstevel@tonic-gate extern void plt_upper_44(uintptr_t, uintptr_t); 527c478bd9Sstevel@tonic-gate extern void plt_full_range(uintptr_t, uintptr_t); 537c478bd9Sstevel@tonic-gate extern void elf_rtbndr(Rt_map *, ulong_t, caddr_t); 547c478bd9Sstevel@tonic-gate extern void elf_rtbndr_far(Rt_map *, ulong_t, caddr_t); 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate int 577c478bd9Sstevel@tonic-gate elf_mach_flags_check(Rej_desc *rej, Ehdr *ehdr) 587c478bd9Sstevel@tonic-gate { 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * Check machine type and flags. 617c478bd9Sstevel@tonic-gate */ 627c478bd9Sstevel@tonic-gate if (ehdr->e_flags & EF_SPARC_EXT_MASK) { 637c478bd9Sstevel@tonic-gate /* 647c478bd9Sstevel@tonic-gate * Check vendor-specific extensions. 657c478bd9Sstevel@tonic-gate */ 667c478bd9Sstevel@tonic-gate if (ehdr->e_flags & EF_SPARC_HAL_R1) { 677c478bd9Sstevel@tonic-gate rej->rej_type = SGS_REJ_HAL; 687c478bd9Sstevel@tonic-gate rej->rej_info = (uint_t)ehdr->e_flags; 697c478bd9Sstevel@tonic-gate return (0); 707c478bd9Sstevel@tonic-gate } 717c478bd9Sstevel@tonic-gate if ((ehdr->e_flags & EF_SPARC_SUN_US3) & ~at_flags) { 727c478bd9Sstevel@tonic-gate rej->rej_type = SGS_REJ_US3; 737c478bd9Sstevel@tonic-gate rej->rej_info = (uint_t)ehdr->e_flags; 747c478bd9Sstevel@tonic-gate return (0); 757c478bd9Sstevel@tonic-gate } 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* 787c478bd9Sstevel@tonic-gate * Generic check. 797c478bd9Sstevel@tonic-gate * All of our 64-bit SPARC's support the US1 (UltraSPARC 1) 807c478bd9Sstevel@tonic-gate * instructions so that bit isn't worth checking for explicitly. 817c478bd9Sstevel@tonic-gate */ 827c478bd9Sstevel@tonic-gate if ((ehdr->e_flags & EF_SPARC_EXT_MASK) & ~at_flags) { 837c478bd9Sstevel@tonic-gate rej->rej_type = SGS_REJ_BADFLAG; 847c478bd9Sstevel@tonic-gate rej->rej_info = (uint_t)ehdr->e_flags; 857c478bd9Sstevel@tonic-gate return (0); 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate } else if ((ehdr->e_flags & ~EF_SPARCV9_MM) != 0) { 887c478bd9Sstevel@tonic-gate rej->rej_type = SGS_REJ_BADFLAG; 897c478bd9Sstevel@tonic-gate rej->rej_info = (uint_t)ehdr->e_flags; 907c478bd9Sstevel@tonic-gate return (0); 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate return (1); 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate void 977c478bd9Sstevel@tonic-gate ldso_plt_init(Rt_map *lmp) 987c478bd9Sstevel@tonic-gate { 997c478bd9Sstevel@tonic-gate /* 1007c478bd9Sstevel@tonic-gate * There is no need to analyze ld.so because we don't map in any of 1017c478bd9Sstevel@tonic-gate * its dependencies. However we may map these dependencies in later 1027c478bd9Sstevel@tonic-gate * (as if ld.so had dlopened them), so initialize the plt and the 1037c478bd9Sstevel@tonic-gate * permission information. 1047c478bd9Sstevel@tonic-gate */ 1057c478bd9Sstevel@tonic-gate if (PLTGOT(lmp)) { 1067c478bd9Sstevel@tonic-gate Xword pltoff; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate /* 1097c478bd9Sstevel@tonic-gate * Install the lm pointer in .PLT2 as per the ABI. 1107c478bd9Sstevel@tonic-gate */ 1117c478bd9Sstevel@tonic-gate pltoff = (2 * M_PLT_ENTSIZE) / M_PLT_INSSIZE; 1127c478bd9Sstevel@tonic-gate elf_plt2_init(PLTGOT(lmp) + pltoff, lmp); 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* 1157c478bd9Sstevel@tonic-gate * The V9 ABI states that the first 32k PLT entries 1167c478bd9Sstevel@tonic-gate * use .PLT1, with .PLT0 used by the "latter" entries. 1177c478bd9Sstevel@tonic-gate * We don't currently implement the extendend format, 1187c478bd9Sstevel@tonic-gate * so install an error handler in .PLT0 to catch anyone 1197c478bd9Sstevel@tonic-gate * trying to use it. 1207c478bd9Sstevel@tonic-gate */ 1217c478bd9Sstevel@tonic-gate elf_plt_init(PLTGOT(lmp), (caddr_t)elf_rtbndr_far); 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * Initialize .PLT1 1257c478bd9Sstevel@tonic-gate */ 1267c478bd9Sstevel@tonic-gate pltoff = M_PLT_ENTSIZE / M_PLT_INSSIZE; 1277c478bd9Sstevel@tonic-gate elf_plt_init(PLTGOT(lmp) + pltoff, (caddr_t)elf_rtbndr); 1287c478bd9Sstevel@tonic-gate } 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * elf_plt_write() will test to see how far away our destination 1337c478bd9Sstevel@tonic-gate * address lies. If it is close enough that a branch can 1347c478bd9Sstevel@tonic-gate * be used instead of a jmpl - we will fill the plt in with 1357c478bd9Sstevel@tonic-gate * single branch. The branches are much quicker then 1367c478bd9Sstevel@tonic-gate * a jmpl instruction - see bug#4356879 for further 1377c478bd9Sstevel@tonic-gate * details. 1387c478bd9Sstevel@tonic-gate * 1397c478bd9Sstevel@tonic-gate * NOTE: we pass in both a 'pltaddr' and a 'vpltaddr' since 1407c478bd9Sstevel@tonic-gate * librtld/dldump update PLT's who's physical 1417c478bd9Sstevel@tonic-gate * address is not the same as the 'virtual' runtime 1427c478bd9Sstevel@tonic-gate * address. 1437c478bd9Sstevel@tonic-gate */ 1447c478bd9Sstevel@tonic-gate Pltbindtype 1457c478bd9Sstevel@tonic-gate elf_plt_write(uintptr_t addr, uintptr_t vaddr, void *rptr, uintptr_t symval, 1467c478bd9Sstevel@tonic-gate Xword pltndx) 1477c478bd9Sstevel@tonic-gate { 1487c478bd9Sstevel@tonic-gate Rela *rel = (Rela *)rptr; 1497c478bd9Sstevel@tonic-gate uintptr_t nsym = ~symval; 1507c478bd9Sstevel@tonic-gate uintptr_t vpltaddr, pltaddr; 1517c478bd9Sstevel@tonic-gate long disp; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate pltaddr = addr + rel->r_offset; 1557c478bd9Sstevel@tonic-gate vpltaddr = vaddr + rel->r_offset; 1567c478bd9Sstevel@tonic-gate disp = symval - vpltaddr - 4; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate if (pltndx >= (M64_PLT_NEARPLTS - M_PLT_XNumber)) { 1597c478bd9Sstevel@tonic-gate *((Sxword *)pltaddr) = (uintptr_t)symval + 1607c478bd9Sstevel@tonic-gate (uintptr_t)rel->r_addend - vaddr; 1617c478bd9Sstevel@tonic-gate DBG_CALL(pltcntfar++); 1627c478bd9Sstevel@tonic-gate return (PLT_T_FAR); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * Test if the destination address is close enough to use 1677c478bd9Sstevel@tonic-gate * a ba,a... instruction to reach it. 1687c478bd9Sstevel@tonic-gate */ 1697c478bd9Sstevel@tonic-gate if (S_INRANGE(disp, 23) && !(rtld_flags & RT_FL_NOBAPLT)) { 1707c478bd9Sstevel@tonic-gate uint_t *pltent, bainstr; 1717c478bd9Sstevel@tonic-gate Pltbindtype rc; 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate pltent = (uint_t *)pltaddr; 17456deab07SRod Evans 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * The 1777c478bd9Sstevel@tonic-gate * 1787c478bd9Sstevel@tonic-gate * ba,a,pt %icc, <dest> 1797c478bd9Sstevel@tonic-gate * 1807c478bd9Sstevel@tonic-gate * is the most efficient of the PLT's. If we 1817c478bd9Sstevel@tonic-gate * are within +-20 bits - use that branch. 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate if (S_INRANGE(disp, 20)) { 1847c478bd9Sstevel@tonic-gate bainstr = M_BA_A_PT; /* ba,a,pt %icc,<dest> */ 1857c478bd9Sstevel@tonic-gate /* LINTED */ 1867c478bd9Sstevel@tonic-gate bainstr |= (uint_t)(S_MASK(19) & (disp >> 2)); 1877c478bd9Sstevel@tonic-gate rc = PLT_T_21D; 1887c478bd9Sstevel@tonic-gate DBG_CALL(pltcnt21d++); 1897c478bd9Sstevel@tonic-gate } else { 1907c478bd9Sstevel@tonic-gate /* 1917c478bd9Sstevel@tonic-gate * Otherwise - we fall back to the good old 1927c478bd9Sstevel@tonic-gate * 1937c478bd9Sstevel@tonic-gate * ba,a <dest> 1947c478bd9Sstevel@tonic-gate * 1957c478bd9Sstevel@tonic-gate * Which still beats a jmpl instruction. 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate bainstr = M_BA_A; /* ba,a <dest> */ 1987c478bd9Sstevel@tonic-gate /* LINTED */ 1997c478bd9Sstevel@tonic-gate bainstr |= (uint_t)(S_MASK(22) & (disp >> 2)); 2007c478bd9Sstevel@tonic-gate rc = PLT_T_24D; 2017c478bd9Sstevel@tonic-gate DBG_CALL(pltcnt24d++); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate pltent[2] = M_NOP; /* nop instr */ 2057c478bd9Sstevel@tonic-gate pltent[1] = bainstr; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate iflush_range((char *)(&pltent[1]), 4); 2087c478bd9Sstevel@tonic-gate pltent[0] = M_NOP; /* nop instr */ 2097c478bd9Sstevel@tonic-gate iflush_range((char *)(&pltent[0]), 4); 2107c478bd9Sstevel@tonic-gate return (rc); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate if ((nsym >> 32) == 0) { 2147c478bd9Sstevel@tonic-gate plt_upper_32(pltaddr, symval); 2157c478bd9Sstevel@tonic-gate DBG_CALL(pltcntu32++); 2167c478bd9Sstevel@tonic-gate return (PLT_T_U32); 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate if ((nsym >> 44) == 0) { 2207c478bd9Sstevel@tonic-gate plt_upper_44(pltaddr, symval); 2217c478bd9Sstevel@tonic-gate DBG_CALL(pltcntu44++); 2227c478bd9Sstevel@tonic-gate return (PLT_T_U44); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* 2267c478bd9Sstevel@tonic-gate * The PLT destination is not in reach of 2277c478bd9Sstevel@tonic-gate * a branch instruction - so we fall back 2287c478bd9Sstevel@tonic-gate * to a 'jmpl' sequence. 2297c478bd9Sstevel@tonic-gate */ 2307c478bd9Sstevel@tonic-gate plt_full_range(pltaddr, symval); 2317c478bd9Sstevel@tonic-gate DBG_CALL(pltcntfull++); 2327c478bd9Sstevel@tonic-gate return (PLT_T_FULL); 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate 235a364a791Sab196087 /* 236a364a791Sab196087 * Once relocated, the following 6 instruction sequence moves 237a364a791Sab196087 * a 64-bit immediate value into register %g1 238a364a791Sab196087 */ 239a364a791Sab196087 #define VAL64_TO_G1 \ 240a364a791Sab196087 /* 0x00 */ 0x0b, 0x00, 0x00, 0x00, /* sethi %hh(value), %g5 */ \ 241a364a791Sab196087 /* 0x04 */ 0x8a, 0x11, 0x60, 0x00, /* or %g5, %hm(value), %g5 */ \ 242a364a791Sab196087 /* 0x08 */ 0x8b, 0x29, 0x70, 0x20, /* sllx %g5, 32, %g5 */ \ 243a364a791Sab196087 /* 0x0c */ 0x03, 0x00, 0x00, 0x00, /* sethi %lm(value), %g1 */ \ 244a364a791Sab196087 /* 0x10 */ 0x82, 0x10, 0x60, 0x00, /* or %g1, %lo(value), %g1 */ \ 245a364a791Sab196087 /* 0x14 */ 0x82, 0x10, 0x40, 0x05 /* or %g1, %g5, %g1 */ 246a364a791Sab196087 2477c478bd9Sstevel@tonic-gate /* 2487c478bd9Sstevel@tonic-gate * Local storage space created on the stack created for this glue 2497c478bd9Sstevel@tonic-gate * code includes space for: 2507c478bd9Sstevel@tonic-gate * 0x8 pointer to dyn_data 2517c478bd9Sstevel@tonic-gate * 0x8 size prev stack frame 2527c478bd9Sstevel@tonic-gate */ 2537c478bd9Sstevel@tonic-gate static const Byte dyn_plt_template[] = { 2547c478bd9Sstevel@tonic-gate /* 0x0 */ 0x2a, 0xcf, 0x80, 0x03, /* brnz,a,pt %fp, 0xc */ 2557c478bd9Sstevel@tonic-gate /* 0x4 */ 0x82, 0x27, 0x80, 0x0e, /* sub %fp, %sp, %g1 */ 2567c478bd9Sstevel@tonic-gate /* 0x8 */ 0x82, 0x10, 0x20, 0xb0, /* mov 176, %g1 */ 2577c478bd9Sstevel@tonic-gate /* 0xc */ 0x9d, 0xe3, 0xbf, 0x40, /* save %sp, -192, %sp */ 2587c478bd9Sstevel@tonic-gate /* 0x10 */ 0xc2, 0x77, 0xa7, 0xef, /* stx %g1, [%fp + 2031] */ 259a364a791Sab196087 260a364a791Sab196087 /* store prev stack size */ 261a364a791Sab196087 /* 0x14 */ VAL64_TO_G1, /* dyn_data to g1 */ 262a364a791Sab196087 /* 0x2c */ 0xc2, 0x77, 0xa7, 0xf7, /* stx %g1, [%fp + 2039] */ 263a364a791Sab196087 264a364a791Sab196087 /* 0x30 */ VAL64_TO_G1, /* elf_plt_trace() addr to g1 */ 265a364a791Sab196087 266a364a791Sab196087 /* Call to elf_plt_trace() via g1 */ 267a364a791Sab196087 /* 0x48 */ 0x9f, 0xc0, 0x60, 0x00, /* jmpl ! link r[15] to addr in g1 */ 268a364a791Sab196087 /* 0x4c */ 0x01, 0x00, 0x00, 0x00 /* nop ! for jmpl delay slot *AND* */ 269a364a791Sab196087 /* to get 8-byte alignment */ 2707c478bd9Sstevel@tonic-gate }; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate int dyn_plt_ent_size = sizeof (dyn_plt_template) + 2737c478bd9Sstevel@tonic-gate sizeof (Addr) + /* reflmp */ 2747c478bd9Sstevel@tonic-gate sizeof (Addr) + /* deflmp */ 2757c478bd9Sstevel@tonic-gate sizeof (Word) + /* symndx */ 2767c478bd9Sstevel@tonic-gate sizeof (Word) + /* sb_flags */ 2777c478bd9Sstevel@tonic-gate sizeof (Sym); /* symdef */ 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * the dynamic plt entry is: 2817c478bd9Sstevel@tonic-gate * 2827c478bd9Sstevel@tonic-gate * brnz,a,pt %fp, 1f 2837c478bd9Sstevel@tonic-gate * sub %sp, %fp, %g1 2847c478bd9Sstevel@tonic-gate * mov SA(MINFRAME), %g1 2857c478bd9Sstevel@tonic-gate * 1: 2867c478bd9Sstevel@tonic-gate * save %sp, -(SA(MINFRAME) + (2 * CLONGSIZE)), %sp 2877c478bd9Sstevel@tonic-gate * 2887c478bd9Sstevel@tonic-gate * ! store prev stack size 2897c478bd9Sstevel@tonic-gate * stx %g1, [%fp + STACK_BIAS - (2 * CLONGSIZE)] 2907c478bd9Sstevel@tonic-gate * 291a364a791Sab196087 * 2: 292a364a791Sab196087 * ! move dyn_data to %g1 2937c478bd9Sstevel@tonic-gate * sethi %hh(dyn_data), %g5 2947c478bd9Sstevel@tonic-gate * or %g5, %hm(dyn_data), %g5 2957c478bd9Sstevel@tonic-gate * sllx %g5, 32, %g5 2967c478bd9Sstevel@tonic-gate * sethi %lm(dyn_data), %g1 2977c478bd9Sstevel@tonic-gate * or %g1, %lo(dyn_data), %g1 2987c478bd9Sstevel@tonic-gate * or %g1, %g5, %g1 2997c478bd9Sstevel@tonic-gate * 300a364a791Sab196087 * ! store dyn_data ptr on frame (from %g1) 3017c478bd9Sstevel@tonic-gate * stx %g1, [%fp + STACK_BIAS - CLONGSIZE] 302a364a791Sab196087 * 303a364a791Sab196087 * ! Move address of elf_plt_trace() into %g1 304a364a791Sab196087 * [Uses same 6 instructions as shown at label 2: above. Not shown.] 305a364a791Sab196087 * 306a364a791Sab196087 * ! Use JMPL to make call. CALL instruction is limited to 30-bits. 307a364a791Sab196087 * ! of displacement. 308a364a791Sab196087 * jmp1 %g1, %o7 309a364a791Sab196087 * 310a364a791Sab196087 * ! JMPL has a delay slot that must be filled. And, the sequence 311a364a791Sab196087 * ! of instructions needs to have 8-byte alignment. This NOP does both. 312a364a791Sab196087 * ! The alignment is needed for the data we put following the 313a364a791Sab196087 * ! instruction. 3147c478bd9Sstevel@tonic-gate * nop 315a364a791Sab196087 * 316a364a791Sab196087 * dyn data: 3177c478bd9Sstevel@tonic-gate * Addr reflmp 3187c478bd9Sstevel@tonic-gate * Addr deflmp 3197c478bd9Sstevel@tonic-gate * Word symndx 3207c478bd9Sstevel@tonic-gate * Word sb_flags 3217c478bd9Sstevel@tonic-gate * Sym symdef (Elf64_Sym = 24-bytes) 3227c478bd9Sstevel@tonic-gate */ 323a364a791Sab196087 324a364a791Sab196087 /* 325a364a791Sab196087 * Relocate the instructions given by the VAL64_TO_G1 macro above. 326f3324781Sab196087 * The arguments parallel those of do_reloc_rtld(). 327a364a791Sab196087 * 328a364a791Sab196087 * entry: 32910a4fa49Srie * off - Address of 1st instruction in sequence. 33010a4fa49Srie * value - Value being relocated (addend) 33110a4fa49Srie * sym - Name of value being relocated. 332a364a791Sab196087 * lml - link map list 333a364a791Sab196087 * 334a364a791Sab196087 * exit: 335a364a791Sab196087 * Returns TRUE for success, FALSE for failure. 336a364a791Sab196087 */ 337a364a791Sab196087 static int 33856deab07SRod Evans reloc_val64_to_g1(uchar_t *off, Addr *value, const char *sym, Lm_list *lml) 339a364a791Sab196087 { 34010a4fa49Srie Xword tmp_value; 341a364a791Sab196087 342a364a791Sab196087 /* 343a364a791Sab196087 * relocating: 34410a4fa49Srie * sethi %hh(value), %g5 345a364a791Sab196087 */ 34610a4fa49Srie tmp_value = (Xword)value; 347f3324781Sab196087 if (do_reloc_rtld(R_SPARC_HH22, off, &tmp_value, sym, 348a364a791Sab196087 MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) { 349a364a791Sab196087 return (0); 350a364a791Sab196087 } 351a364a791Sab196087 352a364a791Sab196087 /* 353a364a791Sab196087 * relocating: 35410a4fa49Srie * or %g5, %hm(value), %g5 355a364a791Sab196087 */ 35610a4fa49Srie tmp_value = (Xword)value; 357f3324781Sab196087 if (do_reloc_rtld(R_SPARC_HM10, off + 4, &tmp_value, sym, 358a364a791Sab196087 MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) { 359a364a791Sab196087 return (0); 360a364a791Sab196087 } 361a364a791Sab196087 362a364a791Sab196087 /* 363a364a791Sab196087 * relocating: 36410a4fa49Srie * sethi %lm(value), %g1 365a364a791Sab196087 */ 36610a4fa49Srie tmp_value = (Xword)value; 367f3324781Sab196087 if (do_reloc_rtld(R_SPARC_LM22, off + 12, &tmp_value, sym, 368a364a791Sab196087 MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) { 369a364a791Sab196087 return (0); 370a364a791Sab196087 } 371a364a791Sab196087 372a364a791Sab196087 /* 373a364a791Sab196087 * relocating: 37410a4fa49Srie * or %g1, %lo(value), %g1 375a364a791Sab196087 */ 37610a4fa49Srie tmp_value = (Xword)value; 377f3324781Sab196087 if (do_reloc_rtld(R_SPARC_LO10, off + 16, &tmp_value, sym, 378a364a791Sab196087 MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) { 379a364a791Sab196087 return (0); 380a364a791Sab196087 } 381a364a791Sab196087 382a364a791Sab196087 return (1); 383a364a791Sab196087 } 384a364a791Sab196087 3857c478bd9Sstevel@tonic-gate static caddr_t 3867c478bd9Sstevel@tonic-gate elf_plt_trace_write(caddr_t addr, Rela *rptr, Rt_map *rlmp, Rt_map *dlmp, 3877c478bd9Sstevel@tonic-gate Sym *sym, uint_t symndx, ulong_t pltndx, caddr_t to, uint_t sb_flags, 3887c478bd9Sstevel@tonic-gate int *fail) 3897c478bd9Sstevel@tonic-gate { 3907c478bd9Sstevel@tonic-gate extern ulong_t elf_plt_trace(); 39156deab07SRod Evans uchar_t *dyn_plt; 39256deab07SRod Evans uintptr_t *dyndata; 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate /* 3957c478bd9Sstevel@tonic-gate * If both pltenter & pltexit have been disabled there 3967c478bd9Sstevel@tonic-gate * there is no reason to even create the glue code. 3977c478bd9Sstevel@tonic-gate */ 3987c478bd9Sstevel@tonic-gate if ((sb_flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) == 3997c478bd9Sstevel@tonic-gate (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) { 4007c478bd9Sstevel@tonic-gate (void) elf_plt_write((uintptr_t)addr, (uintptr_t)addr, 4017c478bd9Sstevel@tonic-gate rptr, (uintptr_t)to, pltndx); 4027c478bd9Sstevel@tonic-gate return (to); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate /* 4067c478bd9Sstevel@tonic-gate * We only need to add the glue code if there is an auditing 4077c478bd9Sstevel@tonic-gate * library that is interested in this binding. 4087c478bd9Sstevel@tonic-gate */ 40956deab07SRod Evans dyn_plt = (uchar_t *)((uintptr_t)AUDINFO(rlmp)->ai_dynplts + 41056deab07SRod Evans (pltndx * dyn_plt_ent_size)); 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate /* 4137c478bd9Sstevel@tonic-gate * Have we initialized this dynamic plt entry yet? If we haven't do it 4147c478bd9Sstevel@tonic-gate * now. Otherwise this function has been called before, but from a 4157c478bd9Sstevel@tonic-gate * different plt (ie. from another shared object). In that case 4167c478bd9Sstevel@tonic-gate * we just set the plt to point to the new dyn_plt. 4177c478bd9Sstevel@tonic-gate */ 41856deab07SRod Evans if (*dyn_plt == 0) { 4197c478bd9Sstevel@tonic-gate Sym *symp; 4205aefb655Srie Lm_list *lml = LIST(rlmp); 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate (void) memcpy((void *)dyn_plt, dyn_plt_template, 4237c478bd9Sstevel@tonic-gate sizeof (dyn_plt_template)); 42456deab07SRod Evans dyndata = (uintptr_t *)((uintptr_t)dyn_plt + 42556deab07SRod Evans sizeof (dyn_plt_template)); 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate /* 4287c478bd9Sstevel@tonic-gate * relocating: 429a364a791Sab196087 * VAL64_TO_G1(dyndata) 430a364a791Sab196087 * VAL64_TO_G1(&elf_plt_trace) 4317c478bd9Sstevel@tonic-gate */ 43256deab07SRod Evans if (!(reloc_val64_to_g1((dyn_plt + 0x14), dyndata, 43310a4fa49Srie MSG_ORIG(MSG_SYM_LADYNDATA), lml) && 43456deab07SRod Evans reloc_val64_to_g1((dyn_plt + 0x30), (Addr *)&elf_plt_trace, 43556deab07SRod Evans MSG_ORIG(MSG_SYM_ELFPLTTRACE), lml))) { 4367c478bd9Sstevel@tonic-gate *fail = 1; 4377c478bd9Sstevel@tonic-gate return (0); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate *dyndata++ = (Addr)rlmp; 4417c478bd9Sstevel@tonic-gate *dyndata++ = (Addr)dlmp; 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate /* 4447c478bd9Sstevel@tonic-gate * symndx in the high word, sb_flags in the low. 4457c478bd9Sstevel@tonic-gate */ 4467c478bd9Sstevel@tonic-gate *dyndata = (Addr)sb_flags; 4477c478bd9Sstevel@tonic-gate *(Word *)dyndata = symndx; 4487c478bd9Sstevel@tonic-gate dyndata++; 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate symp = (Sym *)dyndata; 4517c478bd9Sstevel@tonic-gate *symp = *sym; 4527c478bd9Sstevel@tonic-gate symp->st_value = (Addr)to; 4537c478bd9Sstevel@tonic-gate iflush_range((void *)dyn_plt, sizeof (dyn_plt_template)); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate 4565aefb655Srie (void) elf_plt_write((uintptr_t)addr, (uintptr_t)addr, rptr, 4575aefb655Srie (uintptr_t)dyn_plt, pltndx); 4587c478bd9Sstevel@tonic-gate return ((caddr_t)dyn_plt); 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate /* 4627c478bd9Sstevel@tonic-gate * Function binding routine - invoked on the first call to a function through 4637c478bd9Sstevel@tonic-gate * the procedure linkage table; 4647c478bd9Sstevel@tonic-gate * passes first through an assembly language interface. 4657c478bd9Sstevel@tonic-gate * 4667c478bd9Sstevel@tonic-gate * Takes the address of the PLT entry where the call originated, 4677c478bd9Sstevel@tonic-gate * the offset into the relocation table of the associated 4687c478bd9Sstevel@tonic-gate * relocation entry and the address of the link map (rt_private_map struct) 4697c478bd9Sstevel@tonic-gate * for the entry. 4707c478bd9Sstevel@tonic-gate * 4717c478bd9Sstevel@tonic-gate * Returns the address of the function referenced after re-writing the PLT 4727c478bd9Sstevel@tonic-gate * entry to invoke the function directly. 4737c478bd9Sstevel@tonic-gate * 4747c478bd9Sstevel@tonic-gate * On error, causes process to terminate with a signal. 4757c478bd9Sstevel@tonic-gate */ 4767c478bd9Sstevel@tonic-gate ulong_t 4777c478bd9Sstevel@tonic-gate elf_bndr(Rt_map *lmp, ulong_t pltoff, caddr_t from) 4787c478bd9Sstevel@tonic-gate { 4797c478bd9Sstevel@tonic-gate Rt_map *nlmp, *llmp; 4807c478bd9Sstevel@tonic-gate Addr addr, vaddr, reloff, symval; 4817c478bd9Sstevel@tonic-gate char *name; 4827c478bd9Sstevel@tonic-gate Rela *rptr; 48360758829Srie Sym *rsym, *nsym; 4847c478bd9Sstevel@tonic-gate Xword pltndx; 48556deab07SRod Evans uint_t binfo, sb_flags = 0, dbg_class; 4867c478bd9Sstevel@tonic-gate ulong_t rsymndx; 4877c478bd9Sstevel@tonic-gate Slookup sl; 48808278a5eSRod Evans Sresult sr; 4897c478bd9Sstevel@tonic-gate Pltbindtype pbtype; 4905aefb655Srie int entry, lmflags, farplt = 0; 49156deab07SRod Evans Lm_list *lml; 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate /* 4947c478bd9Sstevel@tonic-gate * For compatibility with libthread (TI_VERSION 1) we track the entry 4957c478bd9Sstevel@tonic-gate * value. A zero value indicates we have recursed into ld.so.1 to 4967c478bd9Sstevel@tonic-gate * further process a locking request. Under this recursion we disable 4977c478bd9Sstevel@tonic-gate * tsort and cleanup activities. 4987c478bd9Sstevel@tonic-gate */ 4998cd45542Sraf entry = enter(0); 5007c478bd9Sstevel@tonic-gate 50156deab07SRod Evans lml = LIST(lmp); 5025aefb655Srie if ((lmflags = lml->lm_flags) & LML_FLG_RTLDLM) { 5035aefb655Srie dbg_class = dbg_desc->d_class; 5045aefb655Srie dbg_desc->d_class = 0; 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate /* 5087c478bd9Sstevel@tonic-gate * Must calculate true plt relocation address from reloc. 5097c478bd9Sstevel@tonic-gate * Take offset, subtract number of reserved PLT entries, and divide 5107c478bd9Sstevel@tonic-gate * by PLT entry size, which should give the index of the plt 5117c478bd9Sstevel@tonic-gate * entry (and relocation entry since they have been defined to be 5127c478bd9Sstevel@tonic-gate * in the same order). Then we must multiply by the size of 5137c478bd9Sstevel@tonic-gate * a relocation entry, which will give us the offset of the 5147c478bd9Sstevel@tonic-gate * plt relocation entry from the start of them given by JMPREL(lm). 5157c478bd9Sstevel@tonic-gate */ 5167c478bd9Sstevel@tonic-gate addr = pltoff - M_PLT_RESERVSZ; 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate if (pltoff < (M64_PLT_NEARPLTS * M_PLT_ENTSIZE)) { 5197c478bd9Sstevel@tonic-gate pltndx = addr / M_PLT_ENTSIZE; 5207c478bd9Sstevel@tonic-gate } else { 5217c478bd9Sstevel@tonic-gate ulong_t pltblockoff; 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate pltblockoff = pltoff - (M64_PLT_NEARPLTS * M_PLT_ENTSIZE); 5247c478bd9Sstevel@tonic-gate pltndx = M64_PLT_NEARPLTS + 5257c478bd9Sstevel@tonic-gate ((pltblockoff / M64_PLT_FBLOCKSZ) * M64_PLT_FBLKCNTS) + 5267c478bd9Sstevel@tonic-gate ((pltblockoff % M64_PLT_FBLOCKSZ) / M64_PLT_FENTSIZE) - 5277c478bd9Sstevel@tonic-gate M_PLT_XNumber; 5287c478bd9Sstevel@tonic-gate farplt = 1; 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate /* 5327c478bd9Sstevel@tonic-gate * Perform some basic sanity checks. If we didn't get a load map 5337c478bd9Sstevel@tonic-gate * or the plt offset is invalid then its possible someone has walked 5347c478bd9Sstevel@tonic-gate * over the plt entries or jumped to plt[01] out of the blue. 5357c478bd9Sstevel@tonic-gate */ 5367c478bd9Sstevel@tonic-gate if (!lmp || (!farplt && (addr % M_PLT_ENTSIZE) != 0) || 5377c478bd9Sstevel@tonic-gate (farplt && (addr % M_PLT_INSSIZE))) { 538de777a60Sab196087 Conv_inv_buf_t inv_buf; 539de777a60Sab196087 5405aefb655Srie eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_PLTREF), 541de777a60Sab196087 conv_reloc_SPARC_type(R_SPARC_JMP_SLOT, 0, &inv_buf), 5425aefb655Srie EC_NATPTR(lmp), EC_XWORD(pltoff), EC_NATPTR(from)); 5435aefb655Srie rtldexit(lml, 1); 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate reloff = pltndx * sizeof (Rela); 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate /* 5487c478bd9Sstevel@tonic-gate * Use relocation entry to get symbol table entry and symbol name. 5497c478bd9Sstevel@tonic-gate */ 5507c478bd9Sstevel@tonic-gate addr = (ulong_t)JMPREL(lmp); 5517c478bd9Sstevel@tonic-gate rptr = (Rela *)(addr + reloff); 5527c478bd9Sstevel@tonic-gate rsymndx = ELF_R_SYM(rptr->r_info); 55360758829Srie rsym = (Sym *)((ulong_t)SYMTAB(lmp) + (rsymndx * SYMENT(lmp))); 55460758829Srie name = (char *)(STRTAB(lmp) + rsym->st_name); 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate /* 5577c478bd9Sstevel@tonic-gate * Determine the last link-map of this list, this'll be the starting 5587c478bd9Sstevel@tonic-gate * point for any tsort() processing. 5597c478bd9Sstevel@tonic-gate */ 5605aefb655Srie llmp = lml->lm_tail; 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate /* 56308278a5eSRod Evans * Find definition for symbol. Initialize the symbol lookup, and symbol 56408278a5eSRod Evans * result, data structures. 5657c478bd9Sstevel@tonic-gate */ 56675e7992aSrie SLOOKUP_INIT(sl, name, lmp, lml->lm_head, ld_entry_cnt, 0, 56775e7992aSrie rsymndx, rsym, 0, LKUP_DEFT); 56808278a5eSRod Evans SRESULT_INIT(sr, name); 56975e7992aSrie 57008278a5eSRod Evans if (lookup_sym(&sl, &sr, &binfo, NULL) == 0) { 5715aefb655Srie eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), 5727c478bd9Sstevel@tonic-gate demangle(name)); 5735aefb655Srie rtldexit(lml, 1); 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate 57608278a5eSRod Evans name = (char *)sr.sr_name; 57708278a5eSRod Evans nlmp = sr.sr_dmap; 57808278a5eSRod Evans nsym = sr.sr_sym; 57908278a5eSRod Evans 5807c478bd9Sstevel@tonic-gate symval = nsym->st_value; 58108278a5eSRod Evans 5827c478bd9Sstevel@tonic-gate if (!(FLAGS(nlmp) & FLG_RT_FIXED) && 5837c478bd9Sstevel@tonic-gate (nsym->st_shndx != SHN_ABS)) 5847c478bd9Sstevel@tonic-gate symval += ADDR(nlmp); 5857c478bd9Sstevel@tonic-gate if ((lmp != nlmp) && ((FLAGS1(nlmp) & FL1_RT_NOINIFIN) == 0)) { 5867c478bd9Sstevel@tonic-gate /* 5877c478bd9Sstevel@tonic-gate * Record that this new link map is now bound to the caller. 5887c478bd9Sstevel@tonic-gate */ 5897c478bd9Sstevel@tonic-gate if (bind_one(lmp, nlmp, BND_REFER) == 0) 5905aefb655Srie rtldexit(lml, 1); 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 593*38f4bdddSBryan Cantrill if ((lml->lm_tflags | AFLAGS(lmp) | AFLAGS(nlmp)) & 594*38f4bdddSBryan Cantrill LML_TFLG_AUD_SYMBIND) { 5957c478bd9Sstevel@tonic-gate /* LINTED */ 5967c478bd9Sstevel@tonic-gate uint_t symndx = (uint_t)(((uintptr_t)nsym - 5977c478bd9Sstevel@tonic-gate (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp)); 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate symval = audit_symbind(lmp, nlmp, nsym, symndx, symval, 6007c478bd9Sstevel@tonic-gate &sb_flags); 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate if (FLAGS(lmp) & FLG_RT_FIXED) 6047c478bd9Sstevel@tonic-gate vaddr = 0; 6057c478bd9Sstevel@tonic-gate else 6067c478bd9Sstevel@tonic-gate vaddr = ADDR(lmp); 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate pbtype = PLT_T_NONE; 6097c478bd9Sstevel@tonic-gate if (!(rtld_flags & RT_FL_NOBIND)) { 61056deab07SRod Evans if (((lml->lm_tflags | AFLAGS(lmp)) & 6117c478bd9Sstevel@tonic-gate (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) && 6127c478bd9Sstevel@tonic-gate AUDINFO(lmp)->ai_dynplts) { 6137c478bd9Sstevel@tonic-gate int fail = 0; 6147c478bd9Sstevel@tonic-gate /* LINTED */ 6157c478bd9Sstevel@tonic-gate uint_t symndx = (uint_t)(((uintptr_t)nsym - 6167c478bd9Sstevel@tonic-gate (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp)); 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate symval = (ulong_t)elf_plt_trace_write((caddr_t)vaddr, 6197c478bd9Sstevel@tonic-gate rptr, lmp, nlmp, nsym, symndx, pltndx, 6207c478bd9Sstevel@tonic-gate (caddr_t)symval, sb_flags, &fail); 6217c478bd9Sstevel@tonic-gate if (fail) 6225aefb655Srie rtldexit(lml, 1); 6237c478bd9Sstevel@tonic-gate } else { 6247c478bd9Sstevel@tonic-gate /* 6257c478bd9Sstevel@tonic-gate * Write standard PLT entry to jump directly 6267c478bd9Sstevel@tonic-gate * to newly bound function. 6277c478bd9Sstevel@tonic-gate */ 6287c478bd9Sstevel@tonic-gate pbtype = elf_plt_write((uintptr_t)vaddr, 6297c478bd9Sstevel@tonic-gate (uintptr_t)vaddr, rptr, symval, pltndx); 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate } 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate /* 6347c478bd9Sstevel@tonic-gate * Print binding information and rebuild PLT entry. 6357c478bd9Sstevel@tonic-gate */ 6365aefb655Srie DBG_CALL(Dbg_bind_global(lmp, (Addr)from, (Off)(from - ADDR(lmp)), 6375aefb655Srie (Xword)pltndx, pbtype, nlmp, (Addr)symval, nsym->st_value, 6385aefb655Srie name, binfo)); 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate /* 6417c478bd9Sstevel@tonic-gate * Complete any processing for newly loaded objects. Note we don't 6427c478bd9Sstevel@tonic-gate * know exactly where any new objects are loaded (we know the object 6437c478bd9Sstevel@tonic-gate * that supplied the symbol, but others may have been loaded lazily as 6447c478bd9Sstevel@tonic-gate * we searched for the symbol), so sorting starts from the last 6457c478bd9Sstevel@tonic-gate * link-map know on entry to this routine. 6467c478bd9Sstevel@tonic-gate */ 6477c478bd9Sstevel@tonic-gate if (entry) 6487247f888Srie load_completion(llmp); 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate /* 6517c478bd9Sstevel@tonic-gate * Some operations like dldump() or dlopen()'ing a relocatable object 6527c478bd9Sstevel@tonic-gate * result in objects being loaded on rtld's link-map, make sure these 6537c478bd9Sstevel@tonic-gate * objects are initialized also. 6547c478bd9Sstevel@tonic-gate */ 6557c478bd9Sstevel@tonic-gate if ((LIST(nlmp)->lm_flags & LML_FLG_RTLDLM) && LIST(nlmp)->lm_init) 6567247f888Srie load_completion(nlmp); 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate /* 6597c478bd9Sstevel@tonic-gate * Make sure the object to which we've bound has had it's .init fired. 6607c478bd9Sstevel@tonic-gate * Cleanup before return to user code. 6617c478bd9Sstevel@tonic-gate */ 6627c478bd9Sstevel@tonic-gate if (entry) { 6637c478bd9Sstevel@tonic-gate is_dep_init(nlmp, lmp); 66456deab07SRod Evans leave(lml, 0); 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate if (lmflags & LML_FLG_RTLDLM) 6685aefb655Srie dbg_desc->d_class = dbg_class; 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate return (symval); 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate static int 67457ef7aa9SRod Evans bindpltpad(Rt_map *lmp, Alist **padlist, Addr value, void **pltaddr, 6757c478bd9Sstevel@tonic-gate const char *fname, const char *sname) 6767c478bd9Sstevel@tonic-gate { 67757ef7aa9SRod Evans Aliste idx = 0; 67857ef7aa9SRod Evans Pltpadinfo ppi, *ppip; 6797c478bd9Sstevel@tonic-gate void *plt; 6807c478bd9Sstevel@tonic-gate uintptr_t pltoff; 6817c478bd9Sstevel@tonic-gate Rela rel; 6827c478bd9Sstevel@tonic-gate int i; 6837c478bd9Sstevel@tonic-gate 68457ef7aa9SRod Evans for (ALIST_TRAVERSE(*padlist, idx, ppip)) { 68557ef7aa9SRod Evans if (ppip->pp_addr == value) { 68657ef7aa9SRod Evans *pltaddr = ppip->pp_plt; 6875aefb655Srie DBG_CALL(Dbg_bind_pltpad_from(lmp, (Addr)*pltaddr, 6885aefb655Srie sname)); 6897c478bd9Sstevel@tonic-gate return (1); 6907c478bd9Sstevel@tonic-gate } 69157ef7aa9SRod Evans if (ppip->pp_addr > value) 6927c478bd9Sstevel@tonic-gate break; 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate plt = PLTPAD(lmp); 6967c478bd9Sstevel@tonic-gate pltoff = (uintptr_t)plt - (uintptr_t)ADDR(lmp); 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate PLTPAD(lmp) = (void *)((uintptr_t)PLTPAD(lmp) + M_PLT_ENTSIZE); 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate if (PLTPAD(lmp) > PLTPADEND(lmp)) { 7017c478bd9Sstevel@tonic-gate /* 7027c478bd9Sstevel@tonic-gate * Just fail in usual relocation way 7037c478bd9Sstevel@tonic-gate */ 7047c478bd9Sstevel@tonic-gate *pltaddr = (void *)value; 7057c478bd9Sstevel@tonic-gate return (1); 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate rel.r_offset = pltoff; 7087c478bd9Sstevel@tonic-gate rel.r_info = 0; 7097c478bd9Sstevel@tonic-gate rel.r_addend = 0; 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate /* 7127c478bd9Sstevel@tonic-gate * elf_plt_write assumes the plt was previously filled 7137c478bd9Sstevel@tonic-gate * with NOP's, so fill it in now. 7147c478bd9Sstevel@tonic-gate */ 7157c478bd9Sstevel@tonic-gate for (i = 0; i < (M_PLT_ENTSIZE / sizeof (uint_t)); i++) { 7167c478bd9Sstevel@tonic-gate ((uint_t *)plt)[i] = M_NOP; 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate iflush_range((caddr_t)plt, M_PLT_ENTSIZE); 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate (void) elf_plt_write(ADDR(lmp), ADDR(lmp), &rel, value, 0); 7217c478bd9Sstevel@tonic-gate 72257ef7aa9SRod Evans ppi.pp_addr = value; 72357ef7aa9SRod Evans ppi.pp_plt = plt; 7247c478bd9Sstevel@tonic-gate 72557ef7aa9SRod Evans if (alist_insert(padlist, &ppi, sizeof (Pltpadinfo), 72657ef7aa9SRod Evans AL_CNT_PLTPAD, idx) == NULL) 7277c478bd9Sstevel@tonic-gate return (0); 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate *pltaddr = plt; 7305aefb655Srie DBG_CALL(Dbg_bind_pltpad_to(lmp, (Addr)*pltaddr, fname, sname)); 7317c478bd9Sstevel@tonic-gate return (1); 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate /* 7357c478bd9Sstevel@tonic-gate * Read and process the relocations for one link object, we assume all 7367c478bd9Sstevel@tonic-gate * relocation sections for loadable segments are stored contiguously in 7377c478bd9Sstevel@tonic-gate * the file. 7387c478bd9Sstevel@tonic-gate */ 7397c478bd9Sstevel@tonic-gate int 74056deab07SRod Evans elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) 7417c478bd9Sstevel@tonic-gate { 7427c478bd9Sstevel@tonic-gate ulong_t relbgn, relend, relsiz, basebgn, pltbgn, pltend; 74356deab07SRod Evans ulong_t pltndx, roffset, rsymndx, psymndx = 0; 7447c478bd9Sstevel@tonic-gate uint_t dsymndx, binfo, pbinfo; 745f441771bSRod Evans uchar_t rtype; 7467c478bd9Sstevel@tonic-gate long reladd; 7477c478bd9Sstevel@tonic-gate Addr value, pvalue; 7487c478bd9Sstevel@tonic-gate Sym *symref, *psymref, *symdef, *psymdef; 749f441771bSRod Evans Syminfo *sip; 7507c478bd9Sstevel@tonic-gate char *name, *pname; 7517c478bd9Sstevel@tonic-gate Rt_map *_lmp, *plmp; 75256deab07SRod Evans int ret = 1, noplt = 0; 7537c478bd9Sstevel@tonic-gate long relacount = RELACOUNT(lmp); 7547c478bd9Sstevel@tonic-gate Rela *rel; 7557c478bd9Sstevel@tonic-gate Pltbindtype pbtype; 75657ef7aa9SRod Evans Alist *pltpadlist = NULL; 757cce0e03bSab196087 APlist *bound = NULL; 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate /* 7607c478bd9Sstevel@tonic-gate * If an object has any DT_REGISTER entries associated with 7617c478bd9Sstevel@tonic-gate * it, they are processed now. 7627c478bd9Sstevel@tonic-gate */ 7637c478bd9Sstevel@tonic-gate if ((plt == 0) && (FLAGS(lmp) & FLG_RT_REGSYMS)) { 7647c478bd9Sstevel@tonic-gate if (elf_regsyms(lmp) == 0) 7657c478bd9Sstevel@tonic-gate return (0); 7667c478bd9Sstevel@tonic-gate } 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate /* 7697c478bd9Sstevel@tonic-gate * Although only necessary for lazy binding, initialize the first 7707c478bd9Sstevel@tonic-gate * procedure linkage table entry to go to elf_rtbndr(). dbx(1) seems 7717c478bd9Sstevel@tonic-gate * to find this useful. 7727c478bd9Sstevel@tonic-gate */ 7737c478bd9Sstevel@tonic-gate if ((plt == 0) && PLTGOT(lmp)) { 77456deab07SRod Evans mmapobj_result_t *mpp; 7757c478bd9Sstevel@tonic-gate Xword pltoff; 7767c478bd9Sstevel@tonic-gate 77756deab07SRod Evans /* 77856deab07SRod Evans * Make sure the segment is writable. 77956deab07SRod Evans */ 78056deab07SRod Evans if ((((mpp = 78156deab07SRod Evans find_segment((caddr_t)PLTGOT(lmp), lmp)) != NULL) && 78256deab07SRod Evans ((mpp->mr_prot & PROT_WRITE) == 0)) && 78356deab07SRod Evans ((set_prot(lmp, mpp, 1) == 0) || 78456deab07SRod Evans (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL))) 7857c478bd9Sstevel@tonic-gate return (0); 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate /* 7887c478bd9Sstevel@tonic-gate * Install the lm pointer in .PLT2 as per the ABI. 7897c478bd9Sstevel@tonic-gate */ 7907c478bd9Sstevel@tonic-gate pltoff = (2 * M_PLT_ENTSIZE) / M_PLT_INSSIZE; 7917c478bd9Sstevel@tonic-gate elf_plt2_init(PLTGOT(lmp) + pltoff, lmp); 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate /* 7947c478bd9Sstevel@tonic-gate * The V9 ABI states that the first 32k PLT entries 7957c478bd9Sstevel@tonic-gate * use .PLT1, with .PLT0 used by the "latter" entries. 7967c478bd9Sstevel@tonic-gate * We don't currently implement the extendend format, 7977c478bd9Sstevel@tonic-gate * so install an error handler in .PLT0 to catch anyone 7987c478bd9Sstevel@tonic-gate * trying to use it. 7997c478bd9Sstevel@tonic-gate */ 8007c478bd9Sstevel@tonic-gate elf_plt_init(PLTGOT(lmp), (caddr_t)elf_rtbndr_far); 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate /* 8037c478bd9Sstevel@tonic-gate * Initialize .PLT1 8047c478bd9Sstevel@tonic-gate */ 8057c478bd9Sstevel@tonic-gate pltoff = M_PLT_ENTSIZE / M_PLT_INSSIZE; 8067c478bd9Sstevel@tonic-gate elf_plt_init(PLTGOT(lmp) + pltoff, (caddr_t)elf_rtbndr); 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate /* 8107c478bd9Sstevel@tonic-gate * Initialize the plt start and end addresses. 8117c478bd9Sstevel@tonic-gate */ 8127c478bd9Sstevel@tonic-gate if ((pltbgn = (ulong_t)JMPREL(lmp)) != 0) 8137c478bd9Sstevel@tonic-gate pltend = pltbgn + (ulong_t)(PLTRELSZ(lmp)); 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate /* 8167c478bd9Sstevel@tonic-gate * If we've been called upon to promote an RTLD_LAZY object to an 8177c478bd9Sstevel@tonic-gate * RTLD_NOW then we're only interested in scaning the .plt table. 8187c478bd9Sstevel@tonic-gate */ 8197c478bd9Sstevel@tonic-gate if (plt) { 8207c478bd9Sstevel@tonic-gate relbgn = pltbgn; 8217c478bd9Sstevel@tonic-gate relend = pltend; 8227c478bd9Sstevel@tonic-gate } else { 8237c478bd9Sstevel@tonic-gate /* 8247c478bd9Sstevel@tonic-gate * The relocation sections appear to the run-time linker as a 8257c478bd9Sstevel@tonic-gate * single table. Determine the address of the beginning and end 8267c478bd9Sstevel@tonic-gate * of this table. There are two different interpretations of 8277c478bd9Sstevel@tonic-gate * the ABI at this point: 8287c478bd9Sstevel@tonic-gate * 8297c478bd9Sstevel@tonic-gate * o The REL table and its associated RELSZ indicate the 8307c478bd9Sstevel@tonic-gate * concatenation of *all* relocation sections (this is the 8317c478bd9Sstevel@tonic-gate * model our link-editor constructs). 8327c478bd9Sstevel@tonic-gate * 8337c478bd9Sstevel@tonic-gate * o The REL table and its associated RELSZ indicate the 8347c478bd9Sstevel@tonic-gate * concatenation of all *but* the .plt relocations. These 8357c478bd9Sstevel@tonic-gate * relocations are specified individually by the JMPREL and 8367c478bd9Sstevel@tonic-gate * PLTRELSZ entries. 8377c478bd9Sstevel@tonic-gate * 8387c478bd9Sstevel@tonic-gate * Determine from our knowledege of the relocation range and 8397c478bd9Sstevel@tonic-gate * .plt range, the range of the total relocation table. Note 8407c478bd9Sstevel@tonic-gate * that one other ABI assumption seems to be that the .plt 8417c478bd9Sstevel@tonic-gate * relocations always follow any other relocations, the 8427c478bd9Sstevel@tonic-gate * following range checking drops that assumption. 8437c478bd9Sstevel@tonic-gate */ 8447c478bd9Sstevel@tonic-gate relbgn = (ulong_t)(REL(lmp)); 8457c478bd9Sstevel@tonic-gate relend = relbgn + (ulong_t)(RELSZ(lmp)); 8467c478bd9Sstevel@tonic-gate if (pltbgn) { 8477c478bd9Sstevel@tonic-gate if (!relbgn || (relbgn > pltbgn)) 8487c478bd9Sstevel@tonic-gate relbgn = pltbgn; 8497c478bd9Sstevel@tonic-gate if (!relbgn || (relend < pltend)) 8507c478bd9Sstevel@tonic-gate relend = pltend; 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate if (!relbgn || (relbgn == relend)) { 8545aefb655Srie DBG_CALL(Dbg_reloc_run(lmp, 0, plt, DBG_REL_NONE)); 8557c478bd9Sstevel@tonic-gate return (1); 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate relsiz = (ulong_t)(RELENT(lmp)); 8597c478bd9Sstevel@tonic-gate basebgn = ADDR(lmp); 8607c478bd9Sstevel@tonic-gate 8615aefb655Srie DBG_CALL(Dbg_reloc_run(lmp, M_REL_SHT_TYPE, plt, DBG_REL_START)); 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate /* 8647c478bd9Sstevel@tonic-gate * If we're processing in lazy mode there is no need to scan the 8657c478bd9Sstevel@tonic-gate * .rela.plt table. 8667c478bd9Sstevel@tonic-gate */ 8677c478bd9Sstevel@tonic-gate if (pltbgn && ((MODE(lmp) & RTLD_NOW) == 0)) 8687c478bd9Sstevel@tonic-gate noplt = 1; 8697c478bd9Sstevel@tonic-gate 870f441771bSRod Evans sip = SYMINFO(lmp); 8717c478bd9Sstevel@tonic-gate /* 8727c478bd9Sstevel@tonic-gate * Loop through relocations. 8737c478bd9Sstevel@tonic-gate */ 8747c478bd9Sstevel@tonic-gate while (relbgn < relend) { 87556deab07SRod Evans mmapobj_result_t *mpp; 8767c478bd9Sstevel@tonic-gate uint_t sb_flags = 0; 87756deab07SRod Evans Addr vaddr; 8787c478bd9Sstevel@tonic-gate 879f441771bSRod Evans rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH); 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate /* 8827c478bd9Sstevel@tonic-gate * If this is a RELATIVE relocation in a shared object 8837c478bd9Sstevel@tonic-gate * (the common case), and if we are not debugging, then 8847c478bd9Sstevel@tonic-gate * jump into a tighter relocaiton loop (elf_reloc_relacount) 8857c478bd9Sstevel@tonic-gate * Only make the jump if we've been given a hint on the 8867c478bd9Sstevel@tonic-gate * number of relocations. 8877c478bd9Sstevel@tonic-gate */ 8887c478bd9Sstevel@tonic-gate if ((rtype == R_SPARC_RELATIVE) && 8895aefb655Srie ((FLAGS(lmp) & FLG_RT_FIXED) == 0) && (DBG_ENABLED == 0)) { 8907c478bd9Sstevel@tonic-gate if (relacount) { 89156deab07SRod Evans relbgn = elf_reloc_relative_count(relbgn, 892f441771bSRod Evans relacount, relsiz, basebgn, lmp, 893f441771bSRod Evans textrel, 0); 8947c478bd9Sstevel@tonic-gate relacount = 0; 8957c478bd9Sstevel@tonic-gate } else { 8967c478bd9Sstevel@tonic-gate relbgn = elf_reloc_relative(relbgn, relend, 897f441771bSRod Evans relsiz, basebgn, lmp, textrel, 0); 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate if (relbgn >= relend) 9007c478bd9Sstevel@tonic-gate break; 901f441771bSRod Evans rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH); 9027c478bd9Sstevel@tonic-gate } 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate roffset = ((Rela *)relbgn)->r_offset; 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate reladd = (long)(((Rela *)relbgn)->r_addend); 9077c478bd9Sstevel@tonic-gate rsymndx = ELF_R_SYM(((Rela *)relbgn)->r_info); 9087c478bd9Sstevel@tonic-gate rel = (Rela *)relbgn; 9097c478bd9Sstevel@tonic-gate relbgn += relsiz; 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate /* 9127c478bd9Sstevel@tonic-gate * Optimizations. 9137c478bd9Sstevel@tonic-gate */ 9147c478bd9Sstevel@tonic-gate if (rtype == R_SPARC_NONE) 9157c478bd9Sstevel@tonic-gate continue; 9167c478bd9Sstevel@tonic-gate if (noplt && ((ulong_t)rel >= pltbgn) && 9177c478bd9Sstevel@tonic-gate ((ulong_t)rel < pltend)) { 9187c478bd9Sstevel@tonic-gate relbgn = pltend; 9197c478bd9Sstevel@tonic-gate continue; 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate if (rtype != R_SPARC_REGISTER) { 9237c478bd9Sstevel@tonic-gate /* 9247c478bd9Sstevel@tonic-gate * If this is a shared object, add the base address 9257c478bd9Sstevel@tonic-gate * to offset. 9267c478bd9Sstevel@tonic-gate */ 9277c478bd9Sstevel@tonic-gate if (!(FLAGS(lmp) & FLG_RT_FIXED)) 9287c478bd9Sstevel@tonic-gate roffset += basebgn; 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate /* 9317c478bd9Sstevel@tonic-gate * If this relocation is not against part of the image 9327c478bd9Sstevel@tonic-gate * mapped into memory we skip it. 9337c478bd9Sstevel@tonic-gate */ 93456deab07SRod Evans if ((mpp = find_segment((caddr_t)roffset, 93556deab07SRod Evans lmp)) == NULL) { 9367c478bd9Sstevel@tonic-gate elf_reloc_bad(lmp, (void *)rel, rtype, roffset, 9377c478bd9Sstevel@tonic-gate rsymndx); 9387c478bd9Sstevel@tonic-gate continue; 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate /* 94356deab07SRod Evans * If we're promoting plts, determine if this one has already 9447c478bd9Sstevel@tonic-gate * been written. An uninitialized plts' second instruction is a 9457c478bd9Sstevel@tonic-gate * branch. 9467c478bd9Sstevel@tonic-gate */ 9477c478bd9Sstevel@tonic-gate if (plt) { 9487c478bd9Sstevel@tonic-gate uchar_t *_roffset = (uchar_t *)roffset; 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate _roffset += M_PLT_INSSIZE; 9517c478bd9Sstevel@tonic-gate /* LINTED */ 9527c478bd9Sstevel@tonic-gate if ((*(uint_t *)_roffset & 9537c478bd9Sstevel@tonic-gate (~(S_MASK(19)))) != M_BA_A_XCC) 9547c478bd9Sstevel@tonic-gate continue; 9557c478bd9Sstevel@tonic-gate } 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate binfo = 0; 9587c478bd9Sstevel@tonic-gate pltndx = (ulong_t)-1; 9597c478bd9Sstevel@tonic-gate pbtype = PLT_T_NONE; 96056deab07SRod Evans 9617c478bd9Sstevel@tonic-gate /* 9627c478bd9Sstevel@tonic-gate * If a symbol index is specified then get the symbol table 9637c478bd9Sstevel@tonic-gate * entry, locate the symbol definition, and determine its 9647c478bd9Sstevel@tonic-gate * address. 9657c478bd9Sstevel@tonic-gate */ 9667c478bd9Sstevel@tonic-gate if (rsymndx) { 9677c478bd9Sstevel@tonic-gate /* 968f441771bSRod Evans * If a Syminfo section is provided, determine if this 969f441771bSRod Evans * symbol is deferred, and if so, skip this relocation. 970f441771bSRod Evans */ 971f441771bSRod Evans if (sip && is_sym_deferred((ulong_t)rel, basebgn, lmp, 972f441771bSRod Evans textrel, sip, rsymndx)) 973f441771bSRod Evans continue; 974f441771bSRod Evans 975f441771bSRod Evans /* 9767c478bd9Sstevel@tonic-gate * Get the local symbol table entry. 9777c478bd9Sstevel@tonic-gate */ 9787c478bd9Sstevel@tonic-gate symref = (Sym *)((ulong_t)SYMTAB(lmp) + 9797c478bd9Sstevel@tonic-gate (rsymndx * SYMENT(lmp))); 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate /* 9827c478bd9Sstevel@tonic-gate * If this is a local symbol, just use the base address. 9837c478bd9Sstevel@tonic-gate * (we should have no local relocations in the 9847c478bd9Sstevel@tonic-gate * executable). 9857c478bd9Sstevel@tonic-gate */ 9867c478bd9Sstevel@tonic-gate if (ELF_ST_BIND(symref->st_info) == STB_LOCAL) { 9877c478bd9Sstevel@tonic-gate value = basebgn; 98808278a5eSRod Evans name = NULL; 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate /* 991d326b23bSrie * Special case TLS relocations. 9927c478bd9Sstevel@tonic-gate */ 993d326b23bSrie if ((rtype == R_SPARC_TLS_DTPMOD32) || 994d326b23bSrie (rtype == R_SPARC_TLS_DTPMOD64)) { 995d326b23bSrie /* 996d326b23bSrie * Use the TLS modid. 997d326b23bSrie */ 9987c478bd9Sstevel@tonic-gate value = TLSMODID(lmp); 999d326b23bSrie 1000d326b23bSrie } else if ((rtype == R_SPARC_TLS_TPOFF32) || 1001d326b23bSrie (rtype == R_SPARC_TLS_TPOFF64)) { 1002d326b23bSrie if ((value = elf_static_tls(lmp, symref, 1003d326b23bSrie rel, rtype, 0, roffset, 0)) == 0) { 1004d326b23bSrie ret = 0; 1005d326b23bSrie break; 1006d326b23bSrie } 1007d326b23bSrie } 10087c478bd9Sstevel@tonic-gate } else { 10097c478bd9Sstevel@tonic-gate /* 10107c478bd9Sstevel@tonic-gate * If the symbol index is equal to the previous 10117c478bd9Sstevel@tonic-gate * symbol index relocation we processed then 10127c478bd9Sstevel@tonic-gate * reuse the previous values. (Note that there 10137c478bd9Sstevel@tonic-gate * have been cases where a relocation exists 10147c478bd9Sstevel@tonic-gate * against a copy relocation symbol, our ld(1) 10157c478bd9Sstevel@tonic-gate * should optimize this away, but make sure we 10167c478bd9Sstevel@tonic-gate * don't use the same symbol information should 10177c478bd9Sstevel@tonic-gate * this case exist). 10187c478bd9Sstevel@tonic-gate */ 10197c478bd9Sstevel@tonic-gate if ((rsymndx == psymndx) && 10207c478bd9Sstevel@tonic-gate (rtype != R_SPARC_COPY)) { 10217c478bd9Sstevel@tonic-gate /* LINTED */ 10227c478bd9Sstevel@tonic-gate if (psymdef == 0) { 10235aefb655Srie DBG_CALL(Dbg_bind_weak(lmp, 10245aefb655Srie (Addr)roffset, (Addr) 10257c478bd9Sstevel@tonic-gate (roffset - basebgn), name)); 10267c478bd9Sstevel@tonic-gate continue; 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate /* LINTED */ 10297c478bd9Sstevel@tonic-gate value = pvalue; 10307c478bd9Sstevel@tonic-gate /* LINTED */ 10317c478bd9Sstevel@tonic-gate name = pname; 10327c478bd9Sstevel@tonic-gate symdef = psymdef; 10337c478bd9Sstevel@tonic-gate /* LINTED */ 10347c478bd9Sstevel@tonic-gate symref = psymref; 10357c478bd9Sstevel@tonic-gate /* LINTED */ 10367c478bd9Sstevel@tonic-gate _lmp = plmp; 10377c478bd9Sstevel@tonic-gate /* LINTED */ 10387c478bd9Sstevel@tonic-gate binfo = pbinfo; 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate if ((LIST(_lmp)->lm_tflags | 104156deab07SRod Evans AFLAGS(_lmp)) & 10427c478bd9Sstevel@tonic-gate LML_TFLG_AUD_SYMBIND) { 10437c478bd9Sstevel@tonic-gate value = audit_symbind(lmp, _lmp, 10447c478bd9Sstevel@tonic-gate /* LINTED */ 10457c478bd9Sstevel@tonic-gate symdef, dsymndx, value, 10467c478bd9Sstevel@tonic-gate &sb_flags); 10477c478bd9Sstevel@tonic-gate } 10487c478bd9Sstevel@tonic-gate } else { 10497c478bd9Sstevel@tonic-gate Slookup sl; 105008278a5eSRod Evans Sresult sr; 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate /* 10537c478bd9Sstevel@tonic-gate * Lookup the symbol definition. 105408278a5eSRod Evans * Initialize the symbol lookup, and 105508278a5eSRod Evans * symbol result, data structures. 10567c478bd9Sstevel@tonic-gate */ 10577c478bd9Sstevel@tonic-gate name = (char *)(STRTAB(lmp) + 10587c478bd9Sstevel@tonic-gate symref->st_name); 10597c478bd9Sstevel@tonic-gate 106075e7992aSrie SLOOKUP_INIT(sl, name, lmp, 0, 106175e7992aSrie ld_entry_cnt, 0, rsymndx, symref, 106275e7992aSrie rtype, LKUP_STDRELOC); 106308278a5eSRod Evans SRESULT_INIT(sr, name); 106408278a5eSRod Evans symdef = NULL; 10657c478bd9Sstevel@tonic-gate 106608278a5eSRod Evans if (lookup_sym(&sl, &sr, &binfo, 106708278a5eSRod Evans in_nfavl)) { 106808278a5eSRod Evans name = (char *)sr.sr_name; 106908278a5eSRod Evans _lmp = sr.sr_dmap; 107008278a5eSRod Evans symdef = sr.sr_sym; 107108278a5eSRod Evans } 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate /* 10747c478bd9Sstevel@tonic-gate * If the symbol is not found and the 10757c478bd9Sstevel@tonic-gate * reference was not to a weak symbol, 10767c478bd9Sstevel@tonic-gate * report an error. Weak references 10777c478bd9Sstevel@tonic-gate * may be unresolved. 10787c478bd9Sstevel@tonic-gate */ 10797247f888Srie /* BEGIN CSTYLED */ 10807c478bd9Sstevel@tonic-gate if (symdef == 0) { 108160758829Srie if (sl.sl_bind != STB_WEAK) { 1082dae2dfb7Srie if (elf_reloc_error(lmp, name, 1083dae2dfb7Srie rel, binfo)) 10847c478bd9Sstevel@tonic-gate continue; 1085dae2dfb7Srie 10867c478bd9Sstevel@tonic-gate ret = 0; 10877c478bd9Sstevel@tonic-gate break; 1088dae2dfb7Srie 10897c478bd9Sstevel@tonic-gate } else { 10907c478bd9Sstevel@tonic-gate psymndx = rsymndx; 10917c478bd9Sstevel@tonic-gate psymdef = 0; 10927c478bd9Sstevel@tonic-gate 10935aefb655Srie DBG_CALL(Dbg_bind_weak(lmp, 10945aefb655Srie (Addr)roffset, (Addr) 10957c478bd9Sstevel@tonic-gate (roffset - basebgn), name)); 10967c478bd9Sstevel@tonic-gate continue; 10977c478bd9Sstevel@tonic-gate } 10987c478bd9Sstevel@tonic-gate } 10997247f888Srie /* END CSTYLED */ 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate /* 11027c478bd9Sstevel@tonic-gate * If symbol was found in an object 11037c478bd9Sstevel@tonic-gate * other than the referencing object 11047c478bd9Sstevel@tonic-gate * then record the binding. 11057c478bd9Sstevel@tonic-gate */ 11067c478bd9Sstevel@tonic-gate if ((lmp != _lmp) && ((FLAGS1(_lmp) & 11077c478bd9Sstevel@tonic-gate FL1_RT_NOINIFIN) == 0)) { 1108cce0e03bSab196087 if (aplist_test(&bound, _lmp, 11097c478bd9Sstevel@tonic-gate AL_CNT_RELBIND) == 0) { 11107c478bd9Sstevel@tonic-gate ret = 0; 11117c478bd9Sstevel@tonic-gate break; 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate /* 11167c478bd9Sstevel@tonic-gate * Calculate the location of definition; 11177c478bd9Sstevel@tonic-gate * symbol value plus base address of 11187c478bd9Sstevel@tonic-gate * containing shared object. 11197c478bd9Sstevel@tonic-gate */ 11202926dd2eSrie if (IS_SIZE(rtype)) 11212926dd2eSrie value = symdef->st_size; 11222926dd2eSrie else 11237c478bd9Sstevel@tonic-gate value = symdef->st_value; 11242926dd2eSrie 11257c478bd9Sstevel@tonic-gate if (!(FLAGS(_lmp) & FLG_RT_FIXED) && 11262926dd2eSrie !(IS_SIZE(rtype)) && 11277c478bd9Sstevel@tonic-gate (symdef->st_shndx != SHN_ABS) && 11287c478bd9Sstevel@tonic-gate (ELF_ST_TYPE(symdef->st_info) != 11297c478bd9Sstevel@tonic-gate STT_TLS)) 11307c478bd9Sstevel@tonic-gate value += ADDR(_lmp); 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate /* 11337c478bd9Sstevel@tonic-gate * Retain this symbol index and the 11347c478bd9Sstevel@tonic-gate * value in case it can be used for the 11357c478bd9Sstevel@tonic-gate * subsequent relocations. 11367c478bd9Sstevel@tonic-gate */ 11377c478bd9Sstevel@tonic-gate if (rtype != R_SPARC_COPY) { 11387c478bd9Sstevel@tonic-gate psymndx = rsymndx; 11397c478bd9Sstevel@tonic-gate pvalue = value; 11407c478bd9Sstevel@tonic-gate pname = name; 11417c478bd9Sstevel@tonic-gate psymdef = symdef; 11427c478bd9Sstevel@tonic-gate psymref = symref; 11437c478bd9Sstevel@tonic-gate plmp = _lmp; 11447c478bd9Sstevel@tonic-gate pbinfo = binfo; 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate if ((LIST(_lmp)->lm_tflags | 114756deab07SRod Evans AFLAGS(_lmp)) & 11487c478bd9Sstevel@tonic-gate LML_TFLG_AUD_SYMBIND) { 11497c478bd9Sstevel@tonic-gate /* LINTED */ 11507c478bd9Sstevel@tonic-gate dsymndx = (((uintptr_t)symdef - 11517c478bd9Sstevel@tonic-gate (uintptr_t)SYMTAB(_lmp)) / 11527c478bd9Sstevel@tonic-gate SYMENT(_lmp)); 11537c478bd9Sstevel@tonic-gate value = audit_symbind(lmp, _lmp, 11547c478bd9Sstevel@tonic-gate symdef, dsymndx, value, 11557c478bd9Sstevel@tonic-gate &sb_flags); 11567c478bd9Sstevel@tonic-gate } 11577c478bd9Sstevel@tonic-gate } 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate /* 11607c478bd9Sstevel@tonic-gate * If relocation is PC-relative, subtract 11617c478bd9Sstevel@tonic-gate * offset address. 11627c478bd9Sstevel@tonic-gate */ 11637c478bd9Sstevel@tonic-gate if (IS_PC_RELATIVE(rtype)) 11647c478bd9Sstevel@tonic-gate value -= roffset; 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate /* 1167d326b23bSrie * Special case TLS relocations. 11687c478bd9Sstevel@tonic-gate */ 1169d326b23bSrie if ((rtype == R_SPARC_TLS_DTPMOD32) || 1170d326b23bSrie (rtype == R_SPARC_TLS_DTPMOD64)) { 1171d326b23bSrie /* 1172d326b23bSrie * Relocation value is the TLS modid. 1173d326b23bSrie */ 11747c478bd9Sstevel@tonic-gate value = TLSMODID(_lmp); 1175d326b23bSrie 1176d326b23bSrie } else if ((rtype == R_SPARC_TLS_TPOFF64) || 1177d326b23bSrie (rtype == R_SPARC_TLS_TPOFF32)) { 1178d326b23bSrie if ((value = elf_static_tls(_lmp, 1179d326b23bSrie symdef, rel, rtype, name, roffset, 1180d326b23bSrie value)) == 0) { 1181d326b23bSrie ret = 0; 1182d326b23bSrie break; 1183d326b23bSrie } 1184d326b23bSrie } 11857c478bd9Sstevel@tonic-gate } 11867c478bd9Sstevel@tonic-gate } else { 11877c478bd9Sstevel@tonic-gate /* 1188d326b23bSrie * Special cases. 11897c478bd9Sstevel@tonic-gate */ 1190d326b23bSrie if (rtype == R_SPARC_REGISTER) { 1191d326b23bSrie /* 1192d326b23bSrie * A register symbol associated with symbol 1193d326b23bSrie * index 0 is initialized (i.e. relocated) to 1194d326b23bSrie * a constant in the r_addend field rather than 1195d326b23bSrie * to a symbol value. 1196d326b23bSrie */ 11977c478bd9Sstevel@tonic-gate value = 0; 1198d326b23bSrie 1199d326b23bSrie } else if ((rtype == R_SPARC_TLS_DTPMOD32) || 1200d326b23bSrie (rtype == R_SPARC_TLS_DTPMOD64)) { 1201d326b23bSrie /* 1202d326b23bSrie * TLS relocation value is the TLS modid. 1203d326b23bSrie */ 12047c478bd9Sstevel@tonic-gate value = TLSMODID(lmp); 1205d326b23bSrie } else 12067c478bd9Sstevel@tonic-gate value = basebgn; 120708278a5eSRod Evans 120808278a5eSRod Evans name = NULL; 12097c478bd9Sstevel@tonic-gate } 12107c478bd9Sstevel@tonic-gate 1211d326b23bSrie DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, 1212e23c41c9SAli Bahrami M_REL_SHT_TYPE, rel, NULL, 0, name)); 1213d326b23bSrie 12147c478bd9Sstevel@tonic-gate /* 121556deab07SRod Evans * Make sure the segment is writable. 12167c478bd9Sstevel@tonic-gate */ 121756deab07SRod Evans if ((rtype != R_SPARC_REGISTER) && 121856deab07SRod Evans ((mpp->mr_prot & PROT_WRITE) == 0) && 121956deab07SRod Evans ((set_prot(lmp, mpp, 1) == 0) || 122056deab07SRod Evans (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL))) { 12217c478bd9Sstevel@tonic-gate ret = 0; 12227c478bd9Sstevel@tonic-gate break; 12237c478bd9Sstevel@tonic-gate } 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate /* 12267c478bd9Sstevel@tonic-gate * Call relocation routine to perform required relocation. 12277c478bd9Sstevel@tonic-gate */ 12287c478bd9Sstevel@tonic-gate switch (rtype) { 12297c478bd9Sstevel@tonic-gate case R_SPARC_REGISTER: 12307c478bd9Sstevel@tonic-gate /* 12317c478bd9Sstevel@tonic-gate * The v9 ABI 4.2.4 says that system objects may, 12327c478bd9Sstevel@tonic-gate * but are not required to, use register symbols 12337c478bd9Sstevel@tonic-gate * to inidcate how they use global registers. Thus 12347c478bd9Sstevel@tonic-gate * at least %g6, %g7 must be allowed in addition 12357c478bd9Sstevel@tonic-gate * to %g2 and %g3. 12367c478bd9Sstevel@tonic-gate */ 12377c478bd9Sstevel@tonic-gate value += reladd; 12387c478bd9Sstevel@tonic-gate if (roffset == STO_SPARC_REGISTER_G1) { 12397c478bd9Sstevel@tonic-gate set_sparc_g1(value); 12407c478bd9Sstevel@tonic-gate } else if (roffset == STO_SPARC_REGISTER_G2) { 12417c478bd9Sstevel@tonic-gate set_sparc_g2(value); 12427c478bd9Sstevel@tonic-gate } else if (roffset == STO_SPARC_REGISTER_G3) { 12437c478bd9Sstevel@tonic-gate set_sparc_g3(value); 12447c478bd9Sstevel@tonic-gate } else if (roffset == STO_SPARC_REGISTER_G4) { 12457c478bd9Sstevel@tonic-gate set_sparc_g4(value); 12467c478bd9Sstevel@tonic-gate } else if (roffset == STO_SPARC_REGISTER_G5) { 12477c478bd9Sstevel@tonic-gate set_sparc_g5(value); 12487c478bd9Sstevel@tonic-gate } else if (roffset == STO_SPARC_REGISTER_G6) { 12497c478bd9Sstevel@tonic-gate set_sparc_g6(value); 12507c478bd9Sstevel@tonic-gate } else if (roffset == STO_SPARC_REGISTER_G7) { 12517c478bd9Sstevel@tonic-gate set_sparc_g7(value); 12527c478bd9Sstevel@tonic-gate } else { 12535aefb655Srie eprintf(LIST(lmp), ERR_FATAL, 12545aefb655Srie MSG_INTL(MSG_REL_BADREG), NAME(lmp), 12555aefb655Srie EC_ADDR(roffset)); 12567c478bd9Sstevel@tonic-gate ret = 0; 12577c478bd9Sstevel@tonic-gate break; 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate 12605aefb655Srie DBG_CALL(Dbg_reloc_apply_reg(LIST(lmp), ELF_DBG_RTLD, 12615aefb655Srie M_MACH, (Xword)roffset, (Xword)value)); 12627c478bd9Sstevel@tonic-gate break; 12637c478bd9Sstevel@tonic-gate case R_SPARC_COPY: 12647c478bd9Sstevel@tonic-gate if (elf_copy_reloc(name, symref, lmp, (void *)roffset, 12657c478bd9Sstevel@tonic-gate symdef, _lmp, (const void *)value) == 0) 12667c478bd9Sstevel@tonic-gate ret = 0; 12677c478bd9Sstevel@tonic-gate break; 12687c478bd9Sstevel@tonic-gate case R_SPARC_JMP_SLOT: 12697c478bd9Sstevel@tonic-gate pltndx = ((uintptr_t)rel - 12707c478bd9Sstevel@tonic-gate (uintptr_t)JMPREL(lmp)) / relsiz; 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate if (FLAGS(lmp) & FLG_RT_FIXED) 12737c478bd9Sstevel@tonic-gate vaddr = 0; 12747c478bd9Sstevel@tonic-gate else 12757c478bd9Sstevel@tonic-gate vaddr = ADDR(lmp); 12767c478bd9Sstevel@tonic-gate 127756deab07SRod Evans if (((LIST(lmp)->lm_tflags | AFLAGS(lmp)) & 12787c478bd9Sstevel@tonic-gate (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) && 12797c478bd9Sstevel@tonic-gate AUDINFO(lmp)->ai_dynplts) { 12807c478bd9Sstevel@tonic-gate int fail = 0; 12817c478bd9Sstevel@tonic-gate /* LINTED */ 12827c478bd9Sstevel@tonic-gate uint_t symndx = (uint_t)(((uintptr_t)symdef - 12837247f888Srie (uintptr_t)SYMTAB(_lmp)) / SYMENT(_lmp)); 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate (void) elf_plt_trace_write((caddr_t)vaddr, 12867c478bd9Sstevel@tonic-gate (Rela *)rel, lmp, _lmp, symdef, symndx, 12877c478bd9Sstevel@tonic-gate pltndx, (caddr_t)value, sb_flags, &fail); 12887c478bd9Sstevel@tonic-gate if (fail) 12897c478bd9Sstevel@tonic-gate ret = 0; 12907c478bd9Sstevel@tonic-gate } else { 12917c478bd9Sstevel@tonic-gate /* 12927c478bd9Sstevel@tonic-gate * Write standard PLT entry to jump directly 12937c478bd9Sstevel@tonic-gate * to newly bound function. 12947c478bd9Sstevel@tonic-gate */ 12955aefb655Srie DBG_CALL(Dbg_reloc_apply_val(LIST(lmp), 12965aefb655Srie ELF_DBG_RTLD, (Xword)roffset, 12975aefb655Srie (Xword)value)); 12987c478bd9Sstevel@tonic-gate pbtype = elf_plt_write((uintptr_t)vaddr, 12997c478bd9Sstevel@tonic-gate (uintptr_t)vaddr, (void *)rel, value, 13007c478bd9Sstevel@tonic-gate pltndx); 13017c478bd9Sstevel@tonic-gate } 13027c478bd9Sstevel@tonic-gate break; 13037c478bd9Sstevel@tonic-gate case R_SPARC_WDISP30: 13047c478bd9Sstevel@tonic-gate if (PLTPAD(lmp) && 13057c478bd9Sstevel@tonic-gate (S_INRANGE((Sxword)value, 29) == 0)) { 13067c478bd9Sstevel@tonic-gate void * plt = 0; 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate if (bindpltpad(lmp, &pltpadlist, 13097c478bd9Sstevel@tonic-gate value + roffset, &plt, 13107c478bd9Sstevel@tonic-gate NAME(_lmp), name) == 0) { 13117c478bd9Sstevel@tonic-gate ret = 0; 13127c478bd9Sstevel@tonic-gate break; 13137c478bd9Sstevel@tonic-gate } 13147c478bd9Sstevel@tonic-gate value = (Addr)((Addr)plt - roffset); 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 13177c478bd9Sstevel@tonic-gate default: 13187c478bd9Sstevel@tonic-gate value += reladd; 13197c478bd9Sstevel@tonic-gate if (IS_EXTOFFSET(rtype)) 13207c478bd9Sstevel@tonic-gate value += (Word)ELF_R_TYPE_DATA(rel->r_info); 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate /* 13237c478bd9Sstevel@tonic-gate * Write the relocation out. If this relocation is a 13247c478bd9Sstevel@tonic-gate * common basic write, skip the doreloc() engine. 13257c478bd9Sstevel@tonic-gate */ 13267c478bd9Sstevel@tonic-gate if ((rtype == R_SPARC_GLOB_DAT) || 13277c478bd9Sstevel@tonic-gate (rtype == R_SPARC_64)) { 13287c478bd9Sstevel@tonic-gate if (roffset & 0x7) { 1329de777a60Sab196087 Conv_inv_buf_t inv_buf; 1330de777a60Sab196087 13315aefb655Srie eprintf(LIST(lmp), ERR_FATAL, 13327c478bd9Sstevel@tonic-gate MSG_INTL(MSG_REL_NONALIGN), 1333de777a60Sab196087 conv_reloc_SPARC_type(rtype, 1334de777a60Sab196087 0, &inv_buf), 13357c478bd9Sstevel@tonic-gate NAME(lmp), demangle(name), 13367c478bd9Sstevel@tonic-gate EC_OFF(roffset)); 13377c478bd9Sstevel@tonic-gate ret = 0; 13387c478bd9Sstevel@tonic-gate } else 13397c478bd9Sstevel@tonic-gate *(ulong_t *)roffset += value; 13407c478bd9Sstevel@tonic-gate } else { 1341f3324781Sab196087 if (do_reloc_rtld(rtype, (uchar_t *)roffset, 13425aefb655Srie (Xword *)&value, name, 13435aefb655Srie NAME(lmp), LIST(lmp)) == 0) 13447c478bd9Sstevel@tonic-gate ret = 0; 13457c478bd9Sstevel@tonic-gate } 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate /* 13487c478bd9Sstevel@tonic-gate * The value now contains the 'bit-shifted' value that 1349f3324781Sab196087 * was or'ed into memory (this was set by 1350f3324781Sab196087 * do_reloc_rtld()). 13517c478bd9Sstevel@tonic-gate */ 13525aefb655Srie DBG_CALL(Dbg_reloc_apply_val(LIST(lmp), ELF_DBG_RTLD, 13535aefb655Srie (Xword)roffset, (Xword)value)); 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate /* 13567c478bd9Sstevel@tonic-gate * If this relocation is against a text segment, make 13577c478bd9Sstevel@tonic-gate * sure that the instruction cache is flushed. 13587c478bd9Sstevel@tonic-gate */ 13597c478bd9Sstevel@tonic-gate if (textrel) 13607c478bd9Sstevel@tonic-gate iflush_range((caddr_t)roffset, 0x4); 13617c478bd9Sstevel@tonic-gate } 13627c478bd9Sstevel@tonic-gate 13637c478bd9Sstevel@tonic-gate if ((ret == 0) && 13647c478bd9Sstevel@tonic-gate ((LIST(lmp)->lm_flags & LML_FLG_TRC_WARN) == 0)) 13657c478bd9Sstevel@tonic-gate break; 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate if (binfo) { 13685aefb655Srie DBG_CALL(Dbg_bind_global(lmp, (Addr)roffset, 13695aefb655Srie (Off)(roffset - basebgn), pltndx, pbtype, 13705aefb655Srie _lmp, (Addr)value, symdef->st_value, name, binfo)); 13717c478bd9Sstevel@tonic-gate } 13727c478bd9Sstevel@tonic-gate } 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate /* 13757c478bd9Sstevel@tonic-gate * Free up any items on the pltpadlist if it was allocated 13767c478bd9Sstevel@tonic-gate */ 137757ef7aa9SRod Evans if (pltpadlist) 137857ef7aa9SRod Evans free(pltpadlist); 13797c478bd9Sstevel@tonic-gate 138056deab07SRod Evans return (relocate_finish(lmp, bound, ret)); 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate 13837c478bd9Sstevel@tonic-gate /* 13847c478bd9Sstevel@tonic-gate * Provide a machine specific interface to the conversion routine. By calling 13857c478bd9Sstevel@tonic-gate * the machine specific version, rather than the generic version, we insure that 13867c478bd9Sstevel@tonic-gate * the data tables/strings for all known machine versions aren't dragged into 13877c478bd9Sstevel@tonic-gate * ld.so.1. 13887c478bd9Sstevel@tonic-gate */ 13897c478bd9Sstevel@tonic-gate const char * 13905aefb655Srie _conv_reloc_type(uint_t rel) 13917c478bd9Sstevel@tonic-gate { 1392de777a60Sab196087 static Conv_inv_buf_t inv_buf; 1393de777a60Sab196087 1394de777a60Sab196087 return (conv_reloc_SPARC_type(rel, 0, &inv_buf)); 13957c478bd9Sstevel@tonic-gate } 1396