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 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 * x86 relocation code.
31 */
32
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/sysmacros.h>
36 #include <sys/systm.h>
37 #include <sys/user.h>
38 #include <sys/bootconf.h>
39 #include <sys/modctl.h>
40 #include <sys/elf.h>
41 #include <sys/kobj.h>
42 #include <sys/kobj_impl.h>
43 #include <sys/tnf.h>
44 #include <sys/tnf_probe.h>
45
46 #include "reloc.h"
47
48
102 */
103 if (strncmp(symname, sdt_prefix, strlen(sdt_prefix)) != 0)
104 return (1);
105
106 symname += strlen(sdt_prefix);
107
108 sdp = kobj_alloc(sizeof (sdt_probedesc_t), KM_WAIT);
109 sdp->sdpd_name = kobj_alloc(strlen(symname) + 1, KM_WAIT);
110 bcopy(symname, sdp->sdpd_name, strlen(symname) + 1);
111
112 sdp->sdpd_offset = (uintptr_t)instr;
113 sdp->sdpd_next = mp->sdt_probes;
114 mp->sdt_probes = sdp;
115
116 for (i = 0; i < SDT_NOPS; i++)
117 instr[i - 1] = SDT_NOP;
118
119 return (0);
120 }
121
122 int
123 /* ARGSUSED2 */
124 do_relocate(struct module *mp, char *reltbl, Word relshtype, int nreloc,
125 int relocsize, Addr baseaddr)
126 {
127 unsigned long stndx;
128 unsigned long off; /* can't be register for tnf_reloc_resolve() */
129 register unsigned long reladdr, rend;
130 register unsigned int rtype;
131 unsigned long value;
132 Elf64_Sxword addend;
133 Sym *symref;
134 int err = 0;
135 tnf_probe_control_t *probelist = NULL;
136 tnf_tag_data_t *taglist = NULL;
137 int symnum;
138 reladdr = (unsigned long)reltbl;
139 rend = reladdr + nreloc * relocsize;
140
141 #ifdef KOBJ_DEBUG
142 if (kobj_debug & D_RELOCATIONS) {
143 _kobj_printf(ops, "krtld:\ttype\t\t\toffset\t addend"
204 * get symbol table entry - if symbol is local
205 * value is base address of this object
206 */
207 symref = (Sym *)
208 (mp->symtbl+(stndx * mp->symhdr->sh_entsize));
209
210 if (ELF_ST_BIND(symref->st_info) == STB_LOCAL) {
211 /* *** this is different for .o and .so */
212 value = symref->st_value;
213 } else {
214 /*
215 * It's global. Allow weak references. If
216 * the symbol is undefined, give TNF (the
217 * kernel probes facility) a chance to see
218 * if it's a probe site, and fix it up if so.
219 */
220 if (symref->st_shndx == SHN_UNDEF &&
221 sdt_reloc_resolve(mp, mp->strings +
222 symref->st_name, (uint8_t *)off) == 0)
223 continue;
224
225 if (symref->st_shndx == SHN_UNDEF &&
226 tnf_reloc_resolve(mp->strings +
227 symref->st_name, &symref->st_value,
228 &addend, off, &probelist, &taglist) != 0) {
229 if (ELF_ST_BIND(symref->st_info)
230 != STB_WEAK) {
231 _kobj_printf(ops,
232 "not found: %s\n",
233 mp->strings +
234 symref->st_name);
235 err = 1;
236 }
237 continue;
238 } else { /* symbol found - relocate */
239 /*
240 * calculate location of definition
241 * - symbol value plus base address of
242 * containing shared object
243 */
|
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 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26 /*
27 * Copyright 2019 Joyent, Inc.
28 */
29
30 /*
31 * x86 relocation code.
32 */
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/sysmacros.h>
37 #include <sys/systm.h>
38 #include <sys/user.h>
39 #include <sys/bootconf.h>
40 #include <sys/modctl.h>
41 #include <sys/elf.h>
42 #include <sys/kobj.h>
43 #include <sys/kobj_impl.h>
44 #include <sys/tnf.h>
45 #include <sys/tnf_probe.h>
46
47 #include "reloc.h"
48
49
103 */
104 if (strncmp(symname, sdt_prefix, strlen(sdt_prefix)) != 0)
105 return (1);
106
107 symname += strlen(sdt_prefix);
108
109 sdp = kobj_alloc(sizeof (sdt_probedesc_t), KM_WAIT);
110 sdp->sdpd_name = kobj_alloc(strlen(symname) + 1, KM_WAIT);
111 bcopy(symname, sdp->sdpd_name, strlen(symname) + 1);
112
113 sdp->sdpd_offset = (uintptr_t)instr;
114 sdp->sdpd_next = mp->sdt_probes;
115 mp->sdt_probes = sdp;
116
117 for (i = 0; i < SDT_NOPS; i++)
118 instr[i - 1] = SDT_NOP;
119
120 return (0);
121 }
122
123
124 /*
125 * We're relying on the fact that the call we're replacing is
126 * call (e8) plus 4 bytes of address, making a 5 byte instruction
127 */
128 #define NOP_INSTR 0x90
129 #define SMAP_NOPS 5
130
131 /*
132 * Currently the only call replaced as a hot inline
133 * is smap_enable() and smap_disable(). If more are needed
134 * we should probably come up with an sdt probe like prefix
135 * and look for those instead of exact call names.
136 */
137 static int
138 smap_reloc_resolve(struct module *mp, char *symname, uint8_t *instr)
139 {
140 uint_t symlen;
141 hotinline_desc_t *hid;
142
143 if (strcmp(symname, "smap_enable") == 0 ||
144 strcmp(symname, "smap_disable") == 0) {
145
146 #ifdef KOBJ_DEBUG
147 if (kobj_debug & D_RELOCATIONS) {
148 _kobj_printf(ops, "smap_reloc_resolve: %s relocating "
149 "enable/disable_smap\n", mp->filename);
150 }
151 #endif
152
153 hid = kobj_alloc(sizeof (hotinline_desc_t), KM_WAIT);
154 symlen = strlen(symname) + 1;
155 hid->hid_symname = kobj_alloc(symlen, KM_WAIT);
156 bcopy(symname, hid->hid_symname, symlen);
157
158 /*
159 * We backtrack one byte here to consume the call
160 * instruction itself.
161 */
162 hid->hid_instr_offset = (uintptr_t)instr - 1;
163 hid->hid_next = mp->hi_calls;
164 mp->hi_calls = hid;
165
166 memset((void *)hid->hid_instr_offset, NOP_INSTR, SMAP_NOPS);
167
168 return (0);
169 }
170
171 return (1);
172 }
173
174 int
175 do_relocate(struct module *mp, char *reltbl, Word relshtype, int nreloc,
176 int relocsize, Addr baseaddr)
177 {
178 unsigned long stndx;
179 unsigned long off; /* can't be register for tnf_reloc_resolve() */
180 register unsigned long reladdr, rend;
181 register unsigned int rtype;
182 unsigned long value;
183 Elf64_Sxword addend;
184 Sym *symref;
185 int err = 0;
186 tnf_probe_control_t *probelist = NULL;
187 tnf_tag_data_t *taglist = NULL;
188 int symnum;
189 reladdr = (unsigned long)reltbl;
190 rend = reladdr + nreloc * relocsize;
191
192 #ifdef KOBJ_DEBUG
193 if (kobj_debug & D_RELOCATIONS) {
194 _kobj_printf(ops, "krtld:\ttype\t\t\toffset\t addend"
255 * get symbol table entry - if symbol is local
256 * value is base address of this object
257 */
258 symref = (Sym *)
259 (mp->symtbl+(stndx * mp->symhdr->sh_entsize));
260
261 if (ELF_ST_BIND(symref->st_info) == STB_LOCAL) {
262 /* *** this is different for .o and .so */
263 value = symref->st_value;
264 } else {
265 /*
266 * It's global. Allow weak references. If
267 * the symbol is undefined, give TNF (the
268 * kernel probes facility) a chance to see
269 * if it's a probe site, and fix it up if so.
270 */
271 if (symref->st_shndx == SHN_UNDEF &&
272 sdt_reloc_resolve(mp, mp->strings +
273 symref->st_name, (uint8_t *)off) == 0)
274 continue;
275
276 if (symref->st_shndx == SHN_UNDEF &&
277 smap_reloc_resolve(mp, mp->strings +
278 symref->st_name, (uint8_t *)off) == 0)
279 continue;
280
281 if (symref->st_shndx == SHN_UNDEF &&
282 tnf_reloc_resolve(mp->strings +
283 symref->st_name, &symref->st_value,
284 &addend, off, &probelist, &taglist) != 0) {
285 if (ELF_ST_BIND(symref->st_info)
286 != STB_WEAK) {
287 _kobj_printf(ops,
288 "not found: %s\n",
289 mp->strings +
290 symref->st_name);
291 err = 1;
292 }
293 continue;
294 } else { /* symbol found - relocate */
295 /*
296 * calculate location of definition
297 * - symbol value plus base address of
298 * containing shared object
299 */
|