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
aout_bndr(caddr_t pc)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
aout_reloc(Rt_map * lmp,uint_t plt,int * in_nfavl,APlist ** textrel)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