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 /* 237257d1b4Sraf * Copyright (c) 1988 AT&T 247257d1b4Sraf * All Rights Reserved 25*f441771bSRod Evans * 26*f441771bSRod Evans * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. 277257d1b4Sraf */ 287257d1b4Sraf 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * SPARC machine dependent and a.out format file class dependent functions. 317c478bd9Sstevel@tonic-gate * Contains routines for performing function binding and symbol relocations. 327c478bd9Sstevel@tonic-gate */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include <stdio.h> 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 367c478bd9Sstevel@tonic-gate #include <sys/mman.h> 377c478bd9Sstevel@tonic-gate #include <synch.h> 387c478bd9Sstevel@tonic-gate #include <dlfcn.h> 395aefb655Srie #include <debug.h> 407c478bd9Sstevel@tonic-gate #include "_a.out.h" 417c478bd9Sstevel@tonic-gate #include "_rtld.h" 427c478bd9Sstevel@tonic-gate #include "_audit.h" 43*f441771bSRod Evans #include "_inline_gen.h" 447c478bd9Sstevel@tonic-gate #include "msg.h" 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate extern void iflush_range(caddr_t, size_t); 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate /* 497c478bd9Sstevel@tonic-gate * Function binding routine - invoked on the first call to a function through 507c478bd9Sstevel@tonic-gate * the procedure linkage table; 517c478bd9Sstevel@tonic-gate * passes first through an assembly language interface. 527c478bd9Sstevel@tonic-gate * 537c478bd9Sstevel@tonic-gate * Takes the address of the PLT entry where the call originated, 547c478bd9Sstevel@tonic-gate * the offset into the relocation table of the associated 557c478bd9Sstevel@tonic-gate * relocation entry and the address of the link map (rt_private_map struct) 567c478bd9Sstevel@tonic-gate * for the entry. 577c478bd9Sstevel@tonic-gate * 587c478bd9Sstevel@tonic-gate * Returns the address of the function referenced after re-writing the PLT 597c478bd9Sstevel@tonic-gate * entry to invoke the function directly. 607c478bd9Sstevel@tonic-gate * 617c478bd9Sstevel@tonic-gate * On error, causes process to terminate with a signal. 627c478bd9Sstevel@tonic-gate */ 637c478bd9Sstevel@tonic-gate ulong_t 647c478bd9Sstevel@tonic-gate aout_bndr(caddr_t pc) 657c478bd9Sstevel@tonic-gate { 667c478bd9Sstevel@tonic-gate Rt_map *lmp, *nlmp, *llmp; 677c478bd9Sstevel@tonic-gate struct relocation_info *rp; 687c478bd9Sstevel@tonic-gate struct nlist *sp; 697c478bd9Sstevel@tonic-gate Sym *sym; 707c478bd9Sstevel@tonic-gate char *name; 717c478bd9Sstevel@tonic-gate int rndx, entry; 727c478bd9Sstevel@tonic-gate ulong_t symval; 737c478bd9Sstevel@tonic-gate Slookup sl; 7408278a5eSRod Evans Sresult sr; 757c478bd9Sstevel@tonic-gate uint_t binfo; 765aefb655Srie Lm_list *lml; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate /* 797c478bd9Sstevel@tonic-gate * For compatibility with libthread (TI_VERSION 1) we track the entry 807c478bd9Sstevel@tonic-gate * value. A zero value indicates we have recursed into ld.so.1 to 817c478bd9Sstevel@tonic-gate * further process a locking request (see comments in completion()). 827c478bd9Sstevel@tonic-gate * Under this recursion we disable tsort and cleanup activities. 837c478bd9Sstevel@tonic-gate */ 848cd45542Sraf entry = enter(0); 857c478bd9Sstevel@tonic-gate 86cb511613SAli Bahrami for (lmp = lml_main.lm_head; lmp; lmp = NEXT_RT_MAP(lmp)) { 8756deab07SRod Evans if (THIS_IS_AOUT(lmp)) { 887c478bd9Sstevel@tonic-gate if (pc > (caddr_t)(LM2LP(lmp)->lp_plt) && 897c478bd9Sstevel@tonic-gate pc < (caddr_t)((int)LM2LP(lmp)->lp_plt + 907c478bd9Sstevel@tonic-gate AOUTDYN(lmp)->v2->ld_plt_sz)) { 917c478bd9Sstevel@tonic-gate break; 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate #define LAST22BITS 0x3fffff 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* LINTED */ 997c478bd9Sstevel@tonic-gate rndx = *(int *)(pc + (sizeof (ulong_t *) * 2)) & LAST22BITS; 1007c478bd9Sstevel@tonic-gate rp = &LM2LP(lmp)->lp_rp[rndx]; 1017c478bd9Sstevel@tonic-gate sp = &LM2LP(lmp)->lp_symtab[rp->r_symbolnum]; 1027c478bd9Sstevel@tonic-gate name = &LM2LP(lmp)->lp_symstr[sp->n_un.n_strx]; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* 1057c478bd9Sstevel@tonic-gate * Determine the last link-map of this list, this'll be the starting 1067c478bd9Sstevel@tonic-gate * point for any tsort() processing. 1077c478bd9Sstevel@tonic-gate */ 1085aefb655Srie lml = LIST(lmp); 1095aefb655Srie llmp = lml->lm_tail; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* 11275e7992aSrie * Find definition for symbol. Initialize the symbol lookup data 11375e7992aSrie * structure. 1147c478bd9Sstevel@tonic-gate */ 11575e7992aSrie SLOOKUP_INIT(sl, name, lmp, lml->lm_head, ld_entry_cnt, 0, 0, 0, 0, 11675e7992aSrie LKUP_DEFT); 11708278a5eSRod Evans SRESULT_INIT(sr, name); 1187c478bd9Sstevel@tonic-gate 11908278a5eSRod Evans if (aout_lookup_sym(&sl, &sr, &binfo, NULL) == 0) { 1205aefb655Srie eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), 1217c478bd9Sstevel@tonic-gate demangle(name)); 1225aefb655Srie rtldexit(lml, 1); 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate 12508278a5eSRod Evans name = (char *)sr.sr_name; 12608278a5eSRod Evans nlmp = sr.sr_dmap; 12708278a5eSRod Evans sym = sr.sr_sym; 12808278a5eSRod Evans 1297c478bd9Sstevel@tonic-gate symval = sym->st_value; 13008278a5eSRod Evans 1317c478bd9Sstevel@tonic-gate if (!(FLAGS(nlmp) & FLG_RT_FIXED) && 1327c478bd9Sstevel@tonic-gate (sym->st_shndx != SHN_ABS)) 1337c478bd9Sstevel@tonic-gate symval += (int)(ADDR(nlmp)); 1347c478bd9Sstevel@tonic-gate if ((lmp != nlmp) && ((FLAGS1(nlmp) & FL1_RT_NOINIFIN) == 0)) { 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * Record that this new link map is now bound to the caller. 1377c478bd9Sstevel@tonic-gate */ 1387c478bd9Sstevel@tonic-gate if (bind_one(lmp, nlmp, BND_REFER) == 0) 1395aefb655Srie rtldexit(lml, 1); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * Print binding information and rebuild PLT entry. 1447c478bd9Sstevel@tonic-gate */ 1455aefb655Srie DBG_CALL(Dbg_bind_global(lmp, (Addr)(ADDR(lmp) + rp->r_address), 1465aefb655Srie (Off)rp->r_address, (Xword)(-1), PLT_T_NONE, nlmp, 1475aefb655Srie (Addr)symval, sym->st_value, name, binfo)); 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate if (!(rtld_flags & RT_FL_NOBIND)) 1507c478bd9Sstevel@tonic-gate aout_plt_write((caddr_t)(ADDR(lmp) + rp->r_address), symval); 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /* 1537c478bd9Sstevel@tonic-gate * Complete any processing for newly loaded objects. Note we don't 1547c478bd9Sstevel@tonic-gate * know exactly where any new objects are loaded (we know the object 1557c478bd9Sstevel@tonic-gate * that supplied the symbol, but others may have been loaded lazily as 1567c478bd9Sstevel@tonic-gate * we searched for the symbol), so sorting starts from the last 1577c478bd9Sstevel@tonic-gate * link-map know on entry to this routine. 1587c478bd9Sstevel@tonic-gate */ 1597c478bd9Sstevel@tonic-gate if (entry) 1607247f888Srie load_completion(llmp); 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate /* 1637c478bd9Sstevel@tonic-gate * Make sure the object to which we've bound has had it's .init fired. 1647c478bd9Sstevel@tonic-gate * Cleanup before return to user code. 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate if (entry) { 1677c478bd9Sstevel@tonic-gate is_dep_init(nlmp, lmp); 1688cd45542Sraf leave(lml, 0); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate return (symval); 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate #define IS_PC_RELATIVE(X) (pc_rel_type[(X)] == 1) 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate static const uchar_t pc_rel_type[] = { 1787c478bd9Sstevel@tonic-gate 0, /* RELOC_8 */ 1797c478bd9Sstevel@tonic-gate 0, /* RELOC_16 */ 1807c478bd9Sstevel@tonic-gate 0, /* RELOC_32 */ 1817c478bd9Sstevel@tonic-gate 1, /* RELOC_DISP8 */ 1827c478bd9Sstevel@tonic-gate 1, /* RELOC_DISP16 */ 1837c478bd9Sstevel@tonic-gate 1, /* RELOC_DISP32 */ 1847c478bd9Sstevel@tonic-gate 1, /* RELOC_WDISP30 */ 1857c478bd9Sstevel@tonic-gate 1, /* RELOC_WDISP22 */ 1867c478bd9Sstevel@tonic-gate 0, /* RELOC_HI22 */ 1877c478bd9Sstevel@tonic-gate 0, /* RELOC_22 */ 1887c478bd9Sstevel@tonic-gate 0, /* RELOC_13 */ 1897c478bd9Sstevel@tonic-gate 0, /* RELOC_LO10 */ 1907c478bd9Sstevel@tonic-gate 0, /* RELOC_SFA_BASE */ 1917c478bd9Sstevel@tonic-gate 0, /* RELOC_SFA_OFF13 */ 1927c478bd9Sstevel@tonic-gate 0, /* RELOC_BASE10 */ 1937c478bd9Sstevel@tonic-gate 0, /* RELOC_BASE13 */ 1947c478bd9Sstevel@tonic-gate 0, /* RELOC_BASE22 */ 1957c478bd9Sstevel@tonic-gate 0, /* RELOC_PC10 */ 1967c478bd9Sstevel@tonic-gate 0, /* RELOC_PC22 */ 1977c478bd9Sstevel@tonic-gate 0, /* RELOC_JMP_TBL */ 1987c478bd9Sstevel@tonic-gate 0, /* RELOC_SEGOFF16 */ 1997c478bd9Sstevel@tonic-gate 0, /* RELOC_GLOB_DAT */ 2007c478bd9Sstevel@tonic-gate 0, /* RELOC_JMP_SLOT */ 2017c478bd9Sstevel@tonic-gate 0 /* RELOC_RELATIVE */ 2027c478bd9Sstevel@tonic-gate }; 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate int 20556deab07SRod Evans aout_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) 2067c478bd9Sstevel@tonic-gate { 2077c478bd9Sstevel@tonic-gate int k; /* loop temporary */ 2087c478bd9Sstevel@tonic-gate int nr; /* number of relocations */ 2097c478bd9Sstevel@tonic-gate char *name; /* symbol being searched for */ 2107c478bd9Sstevel@tonic-gate long value; /* relocation temporary */ 2117c478bd9Sstevel@tonic-gate long *ra; /* cached relocation address */ 2127c478bd9Sstevel@tonic-gate struct relocation_info *rp; /* current relocation */ 2137c478bd9Sstevel@tonic-gate struct nlist *sp; /* symbol table of "symbol" */ 2147c478bd9Sstevel@tonic-gate Rt_map * _lmp; /* lm which holds symbol definition */ 2157c478bd9Sstevel@tonic-gate Sym * sym; /* symbol definition */ 21656deab07SRod Evans int ret = 1; 217cce0e03bSab196087 APlist *bound = NULL; 2185aefb655Srie Lm_list *lml = LIST(lmp); 2197c478bd9Sstevel@tonic-gate 2205aefb655Srie DBG_CALL(Dbg_reloc_run(lmp, SHT_RELA, plt, DBG_REL_START)); 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /* 2237c478bd9Sstevel@tonic-gate * If we've been called upon to promote an RTLD_LAZY object to an 2247c478bd9Sstevel@tonic-gate * RTLD_NOW don't bother to do anything - a.out's are bound as if 2257c478bd9Sstevel@tonic-gate * RTLD_NOW regardless. 2267c478bd9Sstevel@tonic-gate */ 2277c478bd9Sstevel@tonic-gate if (plt) 2287c478bd9Sstevel@tonic-gate return (1); 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate rp = LM2LP(lmp)->lp_rp; 2317c478bd9Sstevel@tonic-gate nr = GETRELSZ(AOUTDYN(lmp)) / sizeof (struct relocation_info); 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate /* 2347c478bd9Sstevel@tonic-gate * Initialize _PLT_, if any. 2357c478bd9Sstevel@tonic-gate */ 2367c478bd9Sstevel@tonic-gate if (AOUTDYN(lmp)->v2->ld_plt_sz) 2377c478bd9Sstevel@tonic-gate aout_plt_write((caddr_t)LM2LP(lmp)->lp_plt->jb_inst, 2387c478bd9Sstevel@tonic-gate (ulong_t)aout_rtbndr); 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* 2417c478bd9Sstevel@tonic-gate * Loop through relocations. 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate for (k = 0; k < nr; k++, rp++) { 24456deab07SRod Evans mmapobj_result_t *mpp; 24556deab07SRod Evans 2467c478bd9Sstevel@tonic-gate /* LINTED */ 2477c478bd9Sstevel@tonic-gate ra = (long *)&((char *)ADDR(lmp))[rp->r_address]; 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate /* 25056deab07SRod Evans * Make sure the segment is writable. 2517c478bd9Sstevel@tonic-gate */ 25256deab07SRod Evans if (((mpp = find_segment((caddr_t)ra, lmp)) != NULL) && 25356deab07SRod Evans ((mpp->mr_prot & PROT_WRITE) == 0)) { 25456deab07SRod Evans if ((set_prot(lmp, mpp, 1) == 0) || 25556deab07SRod Evans (aplist_append(textrel, mpp, 25656deab07SRod Evans AL_CNT_TEXTREL) == NULL)) { 2577c478bd9Sstevel@tonic-gate ret = 0; 2587c478bd9Sstevel@tonic-gate break; 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* 2637c478bd9Sstevel@tonic-gate * Perform the relocation. 2647c478bd9Sstevel@tonic-gate */ 2657c478bd9Sstevel@tonic-gate if (rp->r_extern == 0) { 26608278a5eSRod Evans name = NULL; 2677c478bd9Sstevel@tonic-gate value = ADDR(lmp); 2687c478bd9Sstevel@tonic-gate } else { 2697c478bd9Sstevel@tonic-gate Slookup sl; 27008278a5eSRod Evans Sresult sr; 2717c478bd9Sstevel@tonic-gate uint_t binfo; 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate if (rp->r_type == RELOC_JMP_SLOT) 2747c478bd9Sstevel@tonic-gate continue; 2757c478bd9Sstevel@tonic-gate sp = &LM2LP(lmp)->lp_symtab[rp->r_symbolnum]; 2767c478bd9Sstevel@tonic-gate name = &LM2LP(lmp)->lp_symstr[sp->n_un.n_strx]; 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate /* 27975e7992aSrie * Locate symbol. Initialize the symbol lookup data 28075e7992aSrie * structure. 2817c478bd9Sstevel@tonic-gate */ 28256deab07SRod Evans SLOOKUP_INIT(sl, name, lmp, 0, ld_entry_cnt, 28356deab07SRod Evans 0, 0, 0, 0, LKUP_STDRELOC); 28408278a5eSRod Evans SRESULT_INIT(sr, name); 2857c478bd9Sstevel@tonic-gate 28608278a5eSRod Evans if (aout_lookup_sym(&sl, &sr, &binfo, in_nfavl) == 0) { 2875aefb655Srie if (lml->lm_flags & LML_FLG_TRC_WARN) { 2887c478bd9Sstevel@tonic-gate (void) 2897c478bd9Sstevel@tonic-gate printf(MSG_INTL(MSG_LDD_SYM_NFOUND), 2907c478bd9Sstevel@tonic-gate demangle(name), NAME(lmp)); 2917c478bd9Sstevel@tonic-gate continue; 2927c478bd9Sstevel@tonic-gate } else { 2935aefb655Srie eprintf(lml, ERR_FATAL, 2947c478bd9Sstevel@tonic-gate MSG_INTL(MSG_REL_NOSYM), NAME(lmp), 2957c478bd9Sstevel@tonic-gate demangle(name)); 2967c478bd9Sstevel@tonic-gate ret = 0; 2977c478bd9Sstevel@tonic-gate break; 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate /* 3027c478bd9Sstevel@tonic-gate * If symbol was found in an object other than the 3037c478bd9Sstevel@tonic-gate * referencing object then record the binding. 3047c478bd9Sstevel@tonic-gate */ 30508278a5eSRod Evans name = (char *)sr.sr_name; 30608278a5eSRod Evans _lmp = sr.sr_dmap; 30708278a5eSRod Evans sym = sr.sr_sym; 30808278a5eSRod Evans 3097c478bd9Sstevel@tonic-gate if ((lmp != _lmp) && 3107c478bd9Sstevel@tonic-gate ((FLAGS1(_lmp) & FL1_RT_NOINIFIN) == 0)) { 311cce0e03bSab196087 if (aplist_test(&bound, _lmp, 3127c478bd9Sstevel@tonic-gate AL_CNT_RELBIND) == 0) { 3137c478bd9Sstevel@tonic-gate ret = 0; 3147c478bd9Sstevel@tonic-gate break; 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate value = sym->st_value + rp->r_addend; 3197c478bd9Sstevel@tonic-gate if (!(FLAGS(_lmp) & FLG_RT_FIXED) && 3207c478bd9Sstevel@tonic-gate (sym->st_shndx != SHN_COMMON) && 3217c478bd9Sstevel@tonic-gate (sym->st_shndx != SHN_ABS)) 3227c478bd9Sstevel@tonic-gate value += ADDR(_lmp); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate if (IS_PC_RELATIVE(rp->r_type)) 3257c478bd9Sstevel@tonic-gate value -= (long)ADDR(lmp); 3267c478bd9Sstevel@tonic-gate 3275aefb655Srie DBG_CALL(Dbg_bind_global(lmp, (Addr)ra, 3285aefb655Srie (Off)(ra - ADDR(lmp)), (Xword)(-1), PLT_T_NONE, 3295aefb655Srie _lmp, (Addr)value, sym->st_value, name, binfo)); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate /* 3337c478bd9Sstevel@tonic-gate * Perform a specific relocation operation. 3347c478bd9Sstevel@tonic-gate */ 3357c478bd9Sstevel@tonic-gate switch (rp->r_type) { 3367c478bd9Sstevel@tonic-gate case RELOC_RELATIVE: 3377c478bd9Sstevel@tonic-gate value += *ra << (32-22); 3387c478bd9Sstevel@tonic-gate *(long *)ra = (*(long *)ra & ~S_MASK(22)) | 3397c478bd9Sstevel@tonic-gate ((value >> (32 - 22)) & S_MASK(22)); 3407c478bd9Sstevel@tonic-gate ra++; 3417c478bd9Sstevel@tonic-gate value += (*ra & S_MASK(10)); 3427c478bd9Sstevel@tonic-gate *(long *)ra = (*(long *)ra & ~S_MASK(10)) | 3437c478bd9Sstevel@tonic-gate (value & S_MASK(10)); 3447c478bd9Sstevel@tonic-gate break; 3457c478bd9Sstevel@tonic-gate case RELOC_8: 3467c478bd9Sstevel@tonic-gate case RELOC_DISP8: 3477c478bd9Sstevel@tonic-gate value += *ra & S_MASK(8); 3487247f888Srie if (!S_INRANGE(value, 8)) { 3497247f888Srie eprintf(lml, ERR_FATAL, 3507247f888Srie MSG_INTL(MSG_REL_OVERFLOW), NAME(lmp), 3517247f888Srie (name ? demangle(name) : 3527c478bd9Sstevel@tonic-gate MSG_INTL(MSG_STR_UNKNOWN)), (int)value, 8, 3537c478bd9Sstevel@tonic-gate (uint_t)ra); 3547247f888Srie } 3557c478bd9Sstevel@tonic-gate *ra = value; 3567c478bd9Sstevel@tonic-gate break; 3577c478bd9Sstevel@tonic-gate case RELOC_LO10: 3587c478bd9Sstevel@tonic-gate case RELOC_BASE10: 3597c478bd9Sstevel@tonic-gate value += *ra & S_MASK(10); 3607c478bd9Sstevel@tonic-gate *(long *)ra = (*(long *)ra & ~S_MASK(10)) | 3617c478bd9Sstevel@tonic-gate (value & S_MASK(10)); 3627c478bd9Sstevel@tonic-gate break; 3637c478bd9Sstevel@tonic-gate case RELOC_BASE13: 3647c478bd9Sstevel@tonic-gate case RELOC_13: 3657c478bd9Sstevel@tonic-gate value += *ra & S_MASK(13); 3667c478bd9Sstevel@tonic-gate *(long *)ra = (*(long *)ra & ~S_MASK(13)) | 3677c478bd9Sstevel@tonic-gate (value & S_MASK(13)); 3687c478bd9Sstevel@tonic-gate break; 3697c478bd9Sstevel@tonic-gate case RELOC_16: 3707c478bd9Sstevel@tonic-gate case RELOC_DISP16: 3717c478bd9Sstevel@tonic-gate value += *ra & S_MASK(16); 3727247f888Srie if (!S_INRANGE(value, 16)) { 3737247f888Srie eprintf(lml, ERR_FATAL, 3747247f888Srie MSG_INTL(MSG_REL_OVERFLOW), NAME(lmp), 3757247f888Srie (name ? demangle(name) : 3767c478bd9Sstevel@tonic-gate MSG_INTL(MSG_STR_UNKNOWN)), (int)value, 16, 3777c478bd9Sstevel@tonic-gate (uint_t)ra); 3787247f888Srie } 3797c478bd9Sstevel@tonic-gate *(short *)ra = value; 3807c478bd9Sstevel@tonic-gate break; 3817c478bd9Sstevel@tonic-gate case RELOC_22: 3827c478bd9Sstevel@tonic-gate case RELOC_BASE22: 3837c478bd9Sstevel@tonic-gate value += *ra & S_MASK(22); 3847247f888Srie if (!S_INRANGE(value, 22)) { 3857247f888Srie eprintf(lml, ERR_FATAL, 3867247f888Srie MSG_INTL(MSG_REL_OVERFLOW), NAME(lmp), 3877247f888Srie (name ? demangle(name) : 3887c478bd9Sstevel@tonic-gate MSG_INTL(MSG_STR_UNKNOWN)), (int)value, 22, 3897c478bd9Sstevel@tonic-gate (uint_t)ra); 3907247f888Srie } 3917c478bd9Sstevel@tonic-gate *(long *)ra = (*(long *)ra & ~S_MASK(22)) | 3927c478bd9Sstevel@tonic-gate (value & S_MASK(22)); 3937c478bd9Sstevel@tonic-gate break; 3947c478bd9Sstevel@tonic-gate case RELOC_HI22: 3957c478bd9Sstevel@tonic-gate value += (*ra & S_MASK(22)) << (32 - 22); 3967c478bd9Sstevel@tonic-gate *(long *)ra = (*(long *)ra & ~S_MASK(22)) | 3977c478bd9Sstevel@tonic-gate ((value >> (32 - 22)) & S_MASK(22)); 3987c478bd9Sstevel@tonic-gate break; 3997c478bd9Sstevel@tonic-gate case RELOC_WDISP22: 4007c478bd9Sstevel@tonic-gate value += *ra & S_MASK(22); 4017c478bd9Sstevel@tonic-gate value >>= 2; 4027247f888Srie if (!S_INRANGE(value, 22)) { 4037247f888Srie eprintf(lml, ERR_FATAL, 4047247f888Srie MSG_INTL(MSG_REL_OVERFLOW), NAME(lmp), 4057247f888Srie (name ? demangle(name) : 4067c478bd9Sstevel@tonic-gate MSG_INTL(MSG_STR_UNKNOWN)), (int)value, 22, 4077c478bd9Sstevel@tonic-gate (uint_t)ra); 4087247f888Srie } 4097c478bd9Sstevel@tonic-gate *(long *)ra = (*(long *)ra & ~S_MASK(22)) | 4107c478bd9Sstevel@tonic-gate (value & S_MASK(22)); 4117c478bd9Sstevel@tonic-gate break; 4127c478bd9Sstevel@tonic-gate case RELOC_WDISP30: 4137c478bd9Sstevel@tonic-gate value += *ra & S_MASK(30); 4147c478bd9Sstevel@tonic-gate value >>= 2; 4157c478bd9Sstevel@tonic-gate *(long *)ra = (*(long *)ra & ~S_MASK(30)) | 4167c478bd9Sstevel@tonic-gate (value & S_MASK(30)); 4177c478bd9Sstevel@tonic-gate break; 4187c478bd9Sstevel@tonic-gate case RELOC_32: 4197c478bd9Sstevel@tonic-gate case RELOC_GLOB_DAT: 4207c478bd9Sstevel@tonic-gate case RELOC_DISP32: 4217c478bd9Sstevel@tonic-gate value += *ra; 4227c478bd9Sstevel@tonic-gate *(long *)ra = value; 4237c478bd9Sstevel@tonic-gate break; 4247c478bd9Sstevel@tonic-gate default: 4255aefb655Srie eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNIMPL), 4265aefb655Srie NAME(lmp), (name ? demangle(name) : 4275aefb655Srie MSG_INTL(MSG_STR_UNKNOWN)), rp->r_type); 4287c478bd9Sstevel@tonic-gate ret = 0; 4297c478bd9Sstevel@tonic-gate break; 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate * If this relocation is against a text segment we must make 4347c478bd9Sstevel@tonic-gate * sure that the instruction cache is flushed. 4357c478bd9Sstevel@tonic-gate */ 4367c478bd9Sstevel@tonic-gate if (textrel) { 4377c478bd9Sstevel@tonic-gate if (rp->r_type == RELOC_RELATIVE) 4387c478bd9Sstevel@tonic-gate iflush_range((caddr_t)(ra - 1), 0x8); 4397c478bd9Sstevel@tonic-gate else 4407c478bd9Sstevel@tonic-gate iflush_range((caddr_t)ra, 0x4); 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate 44456deab07SRod Evans return (relocate_finish(lmp, bound, ret)); 4457c478bd9Sstevel@tonic-gate } 446