xref: /illumos-gate/usr/src/cmd/sgs/rtld/common/move.c (revision 1979231e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Object file dependent support for ELF objects.
30  */
31 #include	"_synonyms.h"
32 
33 #include	<stdio.h>
34 #include	<sys/procfs.h>
35 #include	<sys/mman.h>
36 #include	<dlfcn.h>
37 #include	<debug.h>
38 #include	<conv.h>
39 #include	"_rtld.h"
40 #include	"_audit.h"
41 #include	"_elf.h"
42 #include	"msg.h"
43 
44 /*
45  * Move data
46  */
47 void
48 move_data(Rt_map *lmp)
49 {
50 	Lm_list	*lml = LIST(lmp);
51 	Move	*mv = MOVETAB(lmp);
52 	Phdr	*pptr = SUNWBSS(lmp);
53 	ulong_t	num, mvnum = MOVESZ(lmp) / MOVEENT(lmp);
54 
55 	DBG_CALL(Dbg_move_data(lmp));
56 	for (num = 0; num < mvnum; num++, mv++) {
57 		Addr	taddr;
58 		Half 	rep, stride;
59 		Sym	*sym;
60 
61 		/*
62 		 * If the target address needs to be mapped in,
63 		 * map it first.
64 		 *	(You have to protect the code, thread safe)
65 		 */
66 		if (FLAGS(lmp) & FLG_RT_SUNWBSS) {
67 			long	zlen;
68 			Off	foff;
69 			caddr_t	zaddr, eaddr;
70 
71 			foff = (Off) (pptr->p_vaddr + ADDR(lmp));
72 			zaddr = (caddr_t)M_PROUND(foff);
73 			eaddr = pptr->p_vaddr + ADDR(lmp) +
74 			    (caddr_t)pptr->p_memsz;
75 			zero((caddr_t)foff, (long)(zaddr - foff));
76 			zlen = eaddr - zaddr;
77 			if (zlen > 0) {
78 				if (dz_map(lml, zaddr, zlen,
79 				    (PROT_READ | PROT_WRITE),
80 				    (MAP_FIXED | MAP_PRIVATE)) == MAP_FAILED)
81 					return;
82 			}
83 
84 			FLAGS(lmp) &= ~FLG_RT_SUNWBSS;
85 		}
86 
87 		if ((sym = (Sym *)SYMTAB(lmp) + ELF_M_SYM(mv->m_info)) == 0)
88 			continue;
89 
90 		stride = mv->m_stride + 1;
91 		taddr = sym->st_value;
92 		if (FLAGS(lmp) & FLG_RT_FIXED)
93 			taddr = taddr + mv->m_poffset;
94 		else
95 			taddr = taddr + mv->m_poffset + ADDR(lmp);
96 
97 		DBG_CALL(Dbg_move_entry2(lml, mv, sym->st_name,
98 		    (const char *)(sym->st_name + STRTAB(lmp))));
99 
100 		for (rep = 0; rep < mv->m_repeat; rep++) {
101 			DBG_CALL(Dbg_move_expand(lml, mv, taddr));
102 
103 			switch (ELF_M_SIZE(mv->m_info)) {
104 			case 1:
105 				*((char *)taddr) = (char)mv->m_value;
106 				taddr += stride;
107 				break;
108 			case 2:
109 				/* LINTED */
110 				*((Half *)taddr) = (Half)mv->m_value;
111 				taddr += 2 * stride;
112 				break;
113 			case 4:
114 				/* LINTED */
115 				*((Word *)taddr) = (Word)mv->m_value;
116 				taddr += 4 * stride;
117 				break;
118 			case 8:
119 				/* LINTED */
120 				*((unsigned long long *)taddr) = mv->m_value;
121 				taddr += 8 * stride;
122 				break;
123 			default:
124 				eprintf(lml, ERR_NONE, MSG_INTL(MSG_MOVE_ERR1));
125 				break;
126 			}
127 		}
128 	}
129 }
130