Deleted Added
full compact
link_elf_obj.c (231949) link_elf_obj.c (241896)
1/*-
2 * Copyright (c) 1998-2000 Doug Rabson
3 * Copyright (c) 2004 Peter Wemm
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1998-2000 Doug Rabson
3 * Copyright (c) 2004 Peter Wemm
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/kern/link_elf_obj.c 231949 2012-02-21 01:05:12Z kib $");
29__FBSDID("$FreeBSD: head/sys/kern/link_elf_obj.c 241896 2012-10-22 17:50:54Z kib $");
30
31#include "opt_ddb.h"
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/kernel.h>
36#include <sys/lock.h>
37#include <sys/malloc.h>
38#include <sys/mutex.h>
39#include <sys/mount.h>
40#include <sys/proc.h>
41#include <sys/namei.h>
42#include <sys/fcntl.h>
43#include <sys/vnode.h>
44#include <sys/linker.h>
45
46#include <machine/elf.h>
47
48#include <net/vnet.h>
49
50#include <security/mac/mac_framework.h>
51
52#include <vm/vm.h>
53#include <vm/vm_param.h>
54#include <vm/vm_object.h>
55#include <vm/vm_kern.h>
56#include <vm/vm_extern.h>
57#include <vm/pmap.h>
58#include <vm/vm_map.h>
59
60#include <sys/link_elf.h>
61
62#ifdef DDB_CTF
63#include <net/zlib.h>
64#endif
65
66#include "linker_if.h"
67
68typedef struct {
69 void *addr;
70 Elf_Off size;
71 int flags;
72 int sec; /* Original section */
73 char *name;
74} Elf_progent;
75
76typedef struct {
77 Elf_Rel *rel;
78 int nrel;
79 int sec;
80} Elf_relent;
81
82typedef struct {
83 Elf_Rela *rela;
84 int nrela;
85 int sec;
86} Elf_relaent;
87
88
89typedef struct elf_file {
90 struct linker_file lf; /* Common fields */
91
92 int preloaded;
93 caddr_t address; /* Relocation address */
94 vm_object_t object; /* VM object to hold file pages */
95 Elf_Shdr *e_shdr;
96
97 Elf_progent *progtab;
98 int nprogtab;
99
100 Elf_relaent *relatab;
101 int nrelatab;
102
103 Elf_relent *reltab;
104 int nreltab;
105
106 Elf_Sym *ddbsymtab; /* The symbol table we are using */
107 long ddbsymcnt; /* Number of symbols */
108 caddr_t ddbstrtab; /* String table */
109 long ddbstrcnt; /* number of bytes in string table */
110
111 caddr_t shstrtab; /* Section name string table */
112 long shstrcnt; /* number of bytes in string table */
113
114 caddr_t ctftab; /* CTF table */
115 long ctfcnt; /* number of bytes in CTF table */
116 caddr_t ctfoff; /* CTF offset table */
117 caddr_t typoff; /* Type offset table */
118 long typlen; /* Number of type entries. */
119
120} *elf_file_t;
121
122#include <kern/kern_ctf.c>
123
124static int link_elf_link_preload(linker_class_t cls,
125 const char *, linker_file_t *);
126static int link_elf_link_preload_finish(linker_file_t);
127static int link_elf_load_file(linker_class_t, const char *, linker_file_t *);
128static int link_elf_lookup_symbol(linker_file_t, const char *,
129 c_linker_sym_t *);
130static int link_elf_symbol_values(linker_file_t, c_linker_sym_t,
131 linker_symval_t *);
132static int link_elf_search_symbol(linker_file_t, caddr_t value,
133 c_linker_sym_t *sym, long *diffp);
134
135static void link_elf_unload_file(linker_file_t);
136static int link_elf_lookup_set(linker_file_t, const char *,
137 void ***, void ***, int *);
138static int link_elf_each_function_name(linker_file_t,
139 int (*)(const char *, void *), void *);
140static int link_elf_each_function_nameval(linker_file_t,
141 linker_function_nameval_callback_t,
142 void *);
143static void link_elf_reloc_local(linker_file_t);
144static long link_elf_symtab_get(linker_file_t, const Elf_Sym **);
145static long link_elf_strtab_get(linker_file_t, caddr_t *);
146
147static Elf_Addr elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps);
148
149static kobj_method_t link_elf_methods[] = {
150 KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol),
151 KOBJMETHOD(linker_symbol_values, link_elf_symbol_values),
152 KOBJMETHOD(linker_search_symbol, link_elf_search_symbol),
153 KOBJMETHOD(linker_unload, link_elf_unload_file),
154 KOBJMETHOD(linker_load_file, link_elf_load_file),
155 KOBJMETHOD(linker_link_preload, link_elf_link_preload),
156 KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish),
157 KOBJMETHOD(linker_lookup_set, link_elf_lookup_set),
158 KOBJMETHOD(linker_each_function_name, link_elf_each_function_name),
159 KOBJMETHOD(linker_each_function_nameval, link_elf_each_function_nameval),
160 KOBJMETHOD(linker_ctf_get, link_elf_ctf_get),
161 KOBJMETHOD(linker_symtab_get, link_elf_symtab_get),
162 KOBJMETHOD(linker_strtab_get, link_elf_strtab_get),
163 { 0, 0 }
164};
165
166static struct linker_class link_elf_class = {
167#if ELF_TARG_CLASS == ELFCLASS32
168 "elf32_obj",
169#else
170 "elf64_obj",
171#endif
172 link_elf_methods, sizeof(struct elf_file)
173};
174
175static int relocate_file(elf_file_t ef);
176
177static void
178link_elf_error(const char *filename, const char *s)
179{
180 if (filename == NULL)
181 printf("kldload: %s\n", s);
182 else
183 printf("kldload: %s: %s\n", filename, s);
184}
185
186static void
187link_elf_init(void *arg)
188{
189
190 linker_add_class(&link_elf_class);
191}
192
193SYSINIT(link_elf_obj, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0);
194
195static int
196link_elf_link_preload(linker_class_t cls, const char *filename,
197 linker_file_t *result)
198{
199 Elf_Ehdr *hdr;
200 Elf_Shdr *shdr;
201 Elf_Sym *es;
202 void *modptr, *baseptr, *sizeptr;
203 char *type;
204 elf_file_t ef;
205 linker_file_t lf;
206 Elf_Addr off;
207 int error, i, j, pb, ra, rl, shstrindex, symstrindex, symtabindex;
208
209 /* Look to see if we have the file preloaded */
210 modptr = preload_search_by_name(filename);
211 if (modptr == NULL)
212 return ENOENT;
213
214 type = (char *)preload_search_info(modptr, MODINFO_TYPE);
215 baseptr = preload_search_info(modptr, MODINFO_ADDR);
216 sizeptr = preload_search_info(modptr, MODINFO_SIZE);
217 hdr = (Elf_Ehdr *)preload_search_info(modptr, MODINFO_METADATA |
218 MODINFOMD_ELFHDR);
219 shdr = (Elf_Shdr *)preload_search_info(modptr, MODINFO_METADATA |
220 MODINFOMD_SHDR);
221 if (type == NULL || (strcmp(type, "elf" __XSTRING(__ELF_WORD_SIZE)
222 " obj module") != 0 &&
223 strcmp(type, "elf obj module") != 0)) {
224 return (EFTYPE);
225 }
226 if (baseptr == NULL || sizeptr == NULL || hdr == NULL ||
227 shdr == NULL)
228 return (EINVAL);
229
230 lf = linker_make_file(filename, &link_elf_class);
231 if (lf == NULL)
232 return (ENOMEM);
233
234 ef = (elf_file_t)lf;
235 ef->preloaded = 1;
236 ef->address = *(caddr_t *)baseptr;
237 lf->address = *(caddr_t *)baseptr;
238 lf->size = *(size_t *)sizeptr;
239
240 if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
241 hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
242 hdr->e_ident[EI_VERSION] != EV_CURRENT ||
243 hdr->e_version != EV_CURRENT ||
244 hdr->e_type != ET_REL ||
245 hdr->e_machine != ELF_TARG_MACH) {
246 error = EFTYPE;
247 goto out;
248 }
249 ef->e_shdr = shdr;
250
251 /* Scan the section header for information and table sizing. */
252 symtabindex = -1;
253 symstrindex = -1;
254 for (i = 0; i < hdr->e_shnum; i++) {
255 switch (shdr[i].sh_type) {
256 case SHT_PROGBITS:
257 case SHT_NOBITS:
258 ef->nprogtab++;
259 break;
260 case SHT_SYMTAB:
261 symtabindex = i;
262 symstrindex = shdr[i].sh_link;
263 break;
264 case SHT_REL:
265 ef->nreltab++;
266 break;
267 case SHT_RELA:
268 ef->nrelatab++;
269 break;
270 }
271 }
272
273 shstrindex = hdr->e_shstrndx;
274 if (ef->nprogtab == 0 || symstrindex < 0 ||
275 symstrindex >= hdr->e_shnum ||
276 shdr[symstrindex].sh_type != SHT_STRTAB || shstrindex == 0 ||
277 shstrindex >= hdr->e_shnum ||
278 shdr[shstrindex].sh_type != SHT_STRTAB) {
279 printf("%s: bad/missing section headers\n", filename);
280 error = ENOEXEC;
281 goto out;
282 }
283
284 /* Allocate space for tracking the load chunks */
285 if (ef->nprogtab != 0)
286 ef->progtab = malloc(ef->nprogtab * sizeof(*ef->progtab),
287 M_LINKER, M_WAITOK | M_ZERO);
288 if (ef->nreltab != 0)
289 ef->reltab = malloc(ef->nreltab * sizeof(*ef->reltab),
290 M_LINKER, M_WAITOK | M_ZERO);
291 if (ef->nrelatab != 0)
292 ef->relatab = malloc(ef->nrelatab * sizeof(*ef->relatab),
293 M_LINKER, M_WAITOK | M_ZERO);
294 if ((ef->nprogtab != 0 && ef->progtab == NULL) ||
295 (ef->nreltab != 0 && ef->reltab == NULL) ||
296 (ef->nrelatab != 0 && ef->relatab == NULL)) {
297 error = ENOMEM;
298 goto out;
299 }
300
301 /* XXX, relocate the sh_addr fields saved by the loader. */
302 off = 0;
303 for (i = 0; i < hdr->e_shnum; i++) {
304 if (shdr[i].sh_addr != 0 && (off == 0 || shdr[i].sh_addr < off))
305 off = shdr[i].sh_addr;
306 }
307 for (i = 0; i < hdr->e_shnum; i++) {
308 if (shdr[i].sh_addr != 0)
309 shdr[i].sh_addr = shdr[i].sh_addr - off +
310 (Elf_Addr)ef->address;
311 }
312
313 ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym);
314 ef->ddbsymtab = (Elf_Sym *)shdr[symtabindex].sh_addr;
315 ef->ddbstrcnt = shdr[symstrindex].sh_size;
316 ef->ddbstrtab = (char *)shdr[symstrindex].sh_addr;
317 ef->shstrcnt = shdr[shstrindex].sh_size;
318 ef->shstrtab = (char *)shdr[shstrindex].sh_addr;
319
320 /* Now fill out progtab and the relocation tables. */
321 pb = 0;
322 rl = 0;
323 ra = 0;
324 for (i = 0; i < hdr->e_shnum; i++) {
325 switch (shdr[i].sh_type) {
326 case SHT_PROGBITS:
327 case SHT_NOBITS:
328 ef->progtab[pb].addr = (void *)shdr[i].sh_addr;
329 if (shdr[i].sh_type == SHT_PROGBITS)
330 ef->progtab[pb].name = "<<PROGBITS>>";
331 else
332 ef->progtab[pb].name = "<<NOBITS>>";
333 ef->progtab[pb].size = shdr[i].sh_size;
334 ef->progtab[pb].sec = i;
335 if (ef->shstrtab && shdr[i].sh_name != 0)
336 ef->progtab[pb].name =
337 ef->shstrtab + shdr[i].sh_name;
338 if (ef->progtab[pb].name != NULL &&
339 !strcmp(ef->progtab[pb].name, DPCPU_SETNAME)) {
340 void *dpcpu;
341
342 dpcpu = dpcpu_alloc(shdr[i].sh_size);
343 if (dpcpu == NULL) {
344 error = ENOSPC;
345 goto out;
346 }
347 memcpy(dpcpu, ef->progtab[pb].addr,
348 ef->progtab[pb].size);
349 dpcpu_copy(dpcpu, shdr[i].sh_size);
350 ef->progtab[pb].addr = dpcpu;
351#ifdef VIMAGE
352 } else if (ef->progtab[pb].name != NULL &&
353 !strcmp(ef->progtab[pb].name, VNET_SETNAME)) {
354 void *vnet_data;
355
356 vnet_data = vnet_data_alloc(shdr[i].sh_size);
357 if (vnet_data == NULL) {
358 error = ENOSPC;
359 goto out;
360 }
361 memcpy(vnet_data, ef->progtab[pb].addr,
362 ef->progtab[pb].size);
363 vnet_data_copy(vnet_data, shdr[i].sh_size);
364 ef->progtab[pb].addr = vnet_data;
365#endif
366 }
367
368 /* Update all symbol values with the offset. */
369 for (j = 0; j < ef->ddbsymcnt; j++) {
370 es = &ef->ddbsymtab[j];
371 if (es->st_shndx != i)
372 continue;
373 es->st_value += (Elf_Addr)ef->progtab[pb].addr;
374 }
375 pb++;
376 break;
377 case SHT_REL:
378 ef->reltab[rl].rel = (Elf_Rel *)shdr[i].sh_addr;
379 ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel);
380 ef->reltab[rl].sec = shdr[i].sh_info;
381 rl++;
382 break;
383 case SHT_RELA:
384 ef->relatab[ra].rela = (Elf_Rela *)shdr[i].sh_addr;
385 ef->relatab[ra].nrela =
386 shdr[i].sh_size / sizeof(Elf_Rela);
387 ef->relatab[ra].sec = shdr[i].sh_info;
388 ra++;
389 break;
390 }
391 }
392 if (pb != ef->nprogtab)
393 panic("lost progbits");
394 if (rl != ef->nreltab)
395 panic("lost reltab");
396 if (ra != ef->nrelatab)
397 panic("lost relatab");
398
399 /* Local intra-module relocations */
400 link_elf_reloc_local(lf);
401
402 *result = lf;
403 return (0);
404
405out:
406 /* preload not done this way */
407 linker_file_unload(lf, LINKER_UNLOAD_FORCE);
408 return (error);
409}
410
411static int
412link_elf_link_preload_finish(linker_file_t lf)
413{
414 elf_file_t ef;
415 int error;
416
417 ef = (elf_file_t)lf;
418 error = relocate_file(ef);
419 if (error)
420 return error;
421
422 /* Notify MD code that a module is being loaded. */
423 error = elf_cpu_load_file(lf);
424 if (error)
425 return (error);
426
427 return (0);
428}
429
430static int
431link_elf_load_file(linker_class_t cls, const char *filename,
432 linker_file_t *result)
433{
434 struct nameidata nd;
435 struct thread *td = curthread; /* XXX */
436 Elf_Ehdr *hdr;
437 Elf_Shdr *shdr;
438 Elf_Sym *es;
439 int nbytes, i, j;
440 vm_offset_t mapbase;
441 size_t mapsize;
442 int error = 0;
443 ssize_t resid;
444 int flags;
445 elf_file_t ef;
446 linker_file_t lf;
447 int symtabindex;
448 int symstrindex;
449 int shstrindex;
450 int nsym;
451 int pb, rl, ra;
452 int alignmask;
30
31#include "opt_ddb.h"
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/kernel.h>
36#include <sys/lock.h>
37#include <sys/malloc.h>
38#include <sys/mutex.h>
39#include <sys/mount.h>
40#include <sys/proc.h>
41#include <sys/namei.h>
42#include <sys/fcntl.h>
43#include <sys/vnode.h>
44#include <sys/linker.h>
45
46#include <machine/elf.h>
47
48#include <net/vnet.h>
49
50#include <security/mac/mac_framework.h>
51
52#include <vm/vm.h>
53#include <vm/vm_param.h>
54#include <vm/vm_object.h>
55#include <vm/vm_kern.h>
56#include <vm/vm_extern.h>
57#include <vm/pmap.h>
58#include <vm/vm_map.h>
59
60#include <sys/link_elf.h>
61
62#ifdef DDB_CTF
63#include <net/zlib.h>
64#endif
65
66#include "linker_if.h"
67
68typedef struct {
69 void *addr;
70 Elf_Off size;
71 int flags;
72 int sec; /* Original section */
73 char *name;
74} Elf_progent;
75
76typedef struct {
77 Elf_Rel *rel;
78 int nrel;
79 int sec;
80} Elf_relent;
81
82typedef struct {
83 Elf_Rela *rela;
84 int nrela;
85 int sec;
86} Elf_relaent;
87
88
89typedef struct elf_file {
90 struct linker_file lf; /* Common fields */
91
92 int preloaded;
93 caddr_t address; /* Relocation address */
94 vm_object_t object; /* VM object to hold file pages */
95 Elf_Shdr *e_shdr;
96
97 Elf_progent *progtab;
98 int nprogtab;
99
100 Elf_relaent *relatab;
101 int nrelatab;
102
103 Elf_relent *reltab;
104 int nreltab;
105
106 Elf_Sym *ddbsymtab; /* The symbol table we are using */
107 long ddbsymcnt; /* Number of symbols */
108 caddr_t ddbstrtab; /* String table */
109 long ddbstrcnt; /* number of bytes in string table */
110
111 caddr_t shstrtab; /* Section name string table */
112 long shstrcnt; /* number of bytes in string table */
113
114 caddr_t ctftab; /* CTF table */
115 long ctfcnt; /* number of bytes in CTF table */
116 caddr_t ctfoff; /* CTF offset table */
117 caddr_t typoff; /* Type offset table */
118 long typlen; /* Number of type entries. */
119
120} *elf_file_t;
121
122#include <kern/kern_ctf.c>
123
124static int link_elf_link_preload(linker_class_t cls,
125 const char *, linker_file_t *);
126static int link_elf_link_preload_finish(linker_file_t);
127static int link_elf_load_file(linker_class_t, const char *, linker_file_t *);
128static int link_elf_lookup_symbol(linker_file_t, const char *,
129 c_linker_sym_t *);
130static int link_elf_symbol_values(linker_file_t, c_linker_sym_t,
131 linker_symval_t *);
132static int link_elf_search_symbol(linker_file_t, caddr_t value,
133 c_linker_sym_t *sym, long *diffp);
134
135static void link_elf_unload_file(linker_file_t);
136static int link_elf_lookup_set(linker_file_t, const char *,
137 void ***, void ***, int *);
138static int link_elf_each_function_name(linker_file_t,
139 int (*)(const char *, void *), void *);
140static int link_elf_each_function_nameval(linker_file_t,
141 linker_function_nameval_callback_t,
142 void *);
143static void link_elf_reloc_local(linker_file_t);
144static long link_elf_symtab_get(linker_file_t, const Elf_Sym **);
145static long link_elf_strtab_get(linker_file_t, caddr_t *);
146
147static Elf_Addr elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps);
148
149static kobj_method_t link_elf_methods[] = {
150 KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol),
151 KOBJMETHOD(linker_symbol_values, link_elf_symbol_values),
152 KOBJMETHOD(linker_search_symbol, link_elf_search_symbol),
153 KOBJMETHOD(linker_unload, link_elf_unload_file),
154 KOBJMETHOD(linker_load_file, link_elf_load_file),
155 KOBJMETHOD(linker_link_preload, link_elf_link_preload),
156 KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish),
157 KOBJMETHOD(linker_lookup_set, link_elf_lookup_set),
158 KOBJMETHOD(linker_each_function_name, link_elf_each_function_name),
159 KOBJMETHOD(linker_each_function_nameval, link_elf_each_function_nameval),
160 KOBJMETHOD(linker_ctf_get, link_elf_ctf_get),
161 KOBJMETHOD(linker_symtab_get, link_elf_symtab_get),
162 KOBJMETHOD(linker_strtab_get, link_elf_strtab_get),
163 { 0, 0 }
164};
165
166static struct linker_class link_elf_class = {
167#if ELF_TARG_CLASS == ELFCLASS32
168 "elf32_obj",
169#else
170 "elf64_obj",
171#endif
172 link_elf_methods, sizeof(struct elf_file)
173};
174
175static int relocate_file(elf_file_t ef);
176
177static void
178link_elf_error(const char *filename, const char *s)
179{
180 if (filename == NULL)
181 printf("kldload: %s\n", s);
182 else
183 printf("kldload: %s: %s\n", filename, s);
184}
185
186static void
187link_elf_init(void *arg)
188{
189
190 linker_add_class(&link_elf_class);
191}
192
193SYSINIT(link_elf_obj, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0);
194
195static int
196link_elf_link_preload(linker_class_t cls, const char *filename,
197 linker_file_t *result)
198{
199 Elf_Ehdr *hdr;
200 Elf_Shdr *shdr;
201 Elf_Sym *es;
202 void *modptr, *baseptr, *sizeptr;
203 char *type;
204 elf_file_t ef;
205 linker_file_t lf;
206 Elf_Addr off;
207 int error, i, j, pb, ra, rl, shstrindex, symstrindex, symtabindex;
208
209 /* Look to see if we have the file preloaded */
210 modptr = preload_search_by_name(filename);
211 if (modptr == NULL)
212 return ENOENT;
213
214 type = (char *)preload_search_info(modptr, MODINFO_TYPE);
215 baseptr = preload_search_info(modptr, MODINFO_ADDR);
216 sizeptr = preload_search_info(modptr, MODINFO_SIZE);
217 hdr = (Elf_Ehdr *)preload_search_info(modptr, MODINFO_METADATA |
218 MODINFOMD_ELFHDR);
219 shdr = (Elf_Shdr *)preload_search_info(modptr, MODINFO_METADATA |
220 MODINFOMD_SHDR);
221 if (type == NULL || (strcmp(type, "elf" __XSTRING(__ELF_WORD_SIZE)
222 " obj module") != 0 &&
223 strcmp(type, "elf obj module") != 0)) {
224 return (EFTYPE);
225 }
226 if (baseptr == NULL || sizeptr == NULL || hdr == NULL ||
227 shdr == NULL)
228 return (EINVAL);
229
230 lf = linker_make_file(filename, &link_elf_class);
231 if (lf == NULL)
232 return (ENOMEM);
233
234 ef = (elf_file_t)lf;
235 ef->preloaded = 1;
236 ef->address = *(caddr_t *)baseptr;
237 lf->address = *(caddr_t *)baseptr;
238 lf->size = *(size_t *)sizeptr;
239
240 if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
241 hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
242 hdr->e_ident[EI_VERSION] != EV_CURRENT ||
243 hdr->e_version != EV_CURRENT ||
244 hdr->e_type != ET_REL ||
245 hdr->e_machine != ELF_TARG_MACH) {
246 error = EFTYPE;
247 goto out;
248 }
249 ef->e_shdr = shdr;
250
251 /* Scan the section header for information and table sizing. */
252 symtabindex = -1;
253 symstrindex = -1;
254 for (i = 0; i < hdr->e_shnum; i++) {
255 switch (shdr[i].sh_type) {
256 case SHT_PROGBITS:
257 case SHT_NOBITS:
258 ef->nprogtab++;
259 break;
260 case SHT_SYMTAB:
261 symtabindex = i;
262 symstrindex = shdr[i].sh_link;
263 break;
264 case SHT_REL:
265 ef->nreltab++;
266 break;
267 case SHT_RELA:
268 ef->nrelatab++;
269 break;
270 }
271 }
272
273 shstrindex = hdr->e_shstrndx;
274 if (ef->nprogtab == 0 || symstrindex < 0 ||
275 symstrindex >= hdr->e_shnum ||
276 shdr[symstrindex].sh_type != SHT_STRTAB || shstrindex == 0 ||
277 shstrindex >= hdr->e_shnum ||
278 shdr[shstrindex].sh_type != SHT_STRTAB) {
279 printf("%s: bad/missing section headers\n", filename);
280 error = ENOEXEC;
281 goto out;
282 }
283
284 /* Allocate space for tracking the load chunks */
285 if (ef->nprogtab != 0)
286 ef->progtab = malloc(ef->nprogtab * sizeof(*ef->progtab),
287 M_LINKER, M_WAITOK | M_ZERO);
288 if (ef->nreltab != 0)
289 ef->reltab = malloc(ef->nreltab * sizeof(*ef->reltab),
290 M_LINKER, M_WAITOK | M_ZERO);
291 if (ef->nrelatab != 0)
292 ef->relatab = malloc(ef->nrelatab * sizeof(*ef->relatab),
293 M_LINKER, M_WAITOK | M_ZERO);
294 if ((ef->nprogtab != 0 && ef->progtab == NULL) ||
295 (ef->nreltab != 0 && ef->reltab == NULL) ||
296 (ef->nrelatab != 0 && ef->relatab == NULL)) {
297 error = ENOMEM;
298 goto out;
299 }
300
301 /* XXX, relocate the sh_addr fields saved by the loader. */
302 off = 0;
303 for (i = 0; i < hdr->e_shnum; i++) {
304 if (shdr[i].sh_addr != 0 && (off == 0 || shdr[i].sh_addr < off))
305 off = shdr[i].sh_addr;
306 }
307 for (i = 0; i < hdr->e_shnum; i++) {
308 if (shdr[i].sh_addr != 0)
309 shdr[i].sh_addr = shdr[i].sh_addr - off +
310 (Elf_Addr)ef->address;
311 }
312
313 ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym);
314 ef->ddbsymtab = (Elf_Sym *)shdr[symtabindex].sh_addr;
315 ef->ddbstrcnt = shdr[symstrindex].sh_size;
316 ef->ddbstrtab = (char *)shdr[symstrindex].sh_addr;
317 ef->shstrcnt = shdr[shstrindex].sh_size;
318 ef->shstrtab = (char *)shdr[shstrindex].sh_addr;
319
320 /* Now fill out progtab and the relocation tables. */
321 pb = 0;
322 rl = 0;
323 ra = 0;
324 for (i = 0; i < hdr->e_shnum; i++) {
325 switch (shdr[i].sh_type) {
326 case SHT_PROGBITS:
327 case SHT_NOBITS:
328 ef->progtab[pb].addr = (void *)shdr[i].sh_addr;
329 if (shdr[i].sh_type == SHT_PROGBITS)
330 ef->progtab[pb].name = "<<PROGBITS>>";
331 else
332 ef->progtab[pb].name = "<<NOBITS>>";
333 ef->progtab[pb].size = shdr[i].sh_size;
334 ef->progtab[pb].sec = i;
335 if (ef->shstrtab && shdr[i].sh_name != 0)
336 ef->progtab[pb].name =
337 ef->shstrtab + shdr[i].sh_name;
338 if (ef->progtab[pb].name != NULL &&
339 !strcmp(ef->progtab[pb].name, DPCPU_SETNAME)) {
340 void *dpcpu;
341
342 dpcpu = dpcpu_alloc(shdr[i].sh_size);
343 if (dpcpu == NULL) {
344 error = ENOSPC;
345 goto out;
346 }
347 memcpy(dpcpu, ef->progtab[pb].addr,
348 ef->progtab[pb].size);
349 dpcpu_copy(dpcpu, shdr[i].sh_size);
350 ef->progtab[pb].addr = dpcpu;
351#ifdef VIMAGE
352 } else if (ef->progtab[pb].name != NULL &&
353 !strcmp(ef->progtab[pb].name, VNET_SETNAME)) {
354 void *vnet_data;
355
356 vnet_data = vnet_data_alloc(shdr[i].sh_size);
357 if (vnet_data == NULL) {
358 error = ENOSPC;
359 goto out;
360 }
361 memcpy(vnet_data, ef->progtab[pb].addr,
362 ef->progtab[pb].size);
363 vnet_data_copy(vnet_data, shdr[i].sh_size);
364 ef->progtab[pb].addr = vnet_data;
365#endif
366 }
367
368 /* Update all symbol values with the offset. */
369 for (j = 0; j < ef->ddbsymcnt; j++) {
370 es = &ef->ddbsymtab[j];
371 if (es->st_shndx != i)
372 continue;
373 es->st_value += (Elf_Addr)ef->progtab[pb].addr;
374 }
375 pb++;
376 break;
377 case SHT_REL:
378 ef->reltab[rl].rel = (Elf_Rel *)shdr[i].sh_addr;
379 ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel);
380 ef->reltab[rl].sec = shdr[i].sh_info;
381 rl++;
382 break;
383 case SHT_RELA:
384 ef->relatab[ra].rela = (Elf_Rela *)shdr[i].sh_addr;
385 ef->relatab[ra].nrela =
386 shdr[i].sh_size / sizeof(Elf_Rela);
387 ef->relatab[ra].sec = shdr[i].sh_info;
388 ra++;
389 break;
390 }
391 }
392 if (pb != ef->nprogtab)
393 panic("lost progbits");
394 if (rl != ef->nreltab)
395 panic("lost reltab");
396 if (ra != ef->nrelatab)
397 panic("lost relatab");
398
399 /* Local intra-module relocations */
400 link_elf_reloc_local(lf);
401
402 *result = lf;
403 return (0);
404
405out:
406 /* preload not done this way */
407 linker_file_unload(lf, LINKER_UNLOAD_FORCE);
408 return (error);
409}
410
411static int
412link_elf_link_preload_finish(linker_file_t lf)
413{
414 elf_file_t ef;
415 int error;
416
417 ef = (elf_file_t)lf;
418 error = relocate_file(ef);
419 if (error)
420 return error;
421
422 /* Notify MD code that a module is being loaded. */
423 error = elf_cpu_load_file(lf);
424 if (error)
425 return (error);
426
427 return (0);
428}
429
430static int
431link_elf_load_file(linker_class_t cls, const char *filename,
432 linker_file_t *result)
433{
434 struct nameidata nd;
435 struct thread *td = curthread; /* XXX */
436 Elf_Ehdr *hdr;
437 Elf_Shdr *shdr;
438 Elf_Sym *es;
439 int nbytes, i, j;
440 vm_offset_t mapbase;
441 size_t mapsize;
442 int error = 0;
443 ssize_t resid;
444 int flags;
445 elf_file_t ef;
446 linker_file_t lf;
447 int symtabindex;
448 int symstrindex;
449 int shstrindex;
450 int nsym;
451 int pb, rl, ra;
452 int alignmask;
453 int vfslocked;
454
455 shdr = NULL;
456 lf = NULL;
457 mapsize = 0;
458 hdr = NULL;
459
453
454 shdr = NULL;
455 lf = NULL;
456 mapsize = 0;
457 hdr = NULL;
458
460 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, filename, td);
459 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td);
461 flags = FREAD;
462 error = vn_open(&nd, &flags, 0, NULL);
463 if (error)
464 return error;
460 flags = FREAD;
461 error = vn_open(&nd, &flags, 0, NULL);
462 if (error)
463 return error;
465 vfslocked = NDHASGIANT(&nd);
466 NDFREE(&nd, NDF_ONLY_PNBUF);
467 if (nd.ni_vp->v_type != VREG) {
468 error = ENOEXEC;
469 goto out;
470 }
471#ifdef MAC
472 error = mac_kld_check_load(td->td_ucred, nd.ni_vp);
473 if (error) {
474 goto out;
475 }
476#endif
477
478 /* Read the elf header from the file. */
479 hdr = malloc(sizeof(*hdr), M_LINKER, M_WAITOK);
480 error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)hdr, sizeof(*hdr), 0,
481 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
482 &resid, td);
483 if (error)
484 goto out;
485 if (resid != 0){
486 error = ENOEXEC;
487 goto out;
488 }
489
490 if (!IS_ELF(*hdr)) {
491 error = ENOEXEC;
492 goto out;
493 }
494
495 if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS
496 || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
497 link_elf_error(filename, "Unsupported file layout");
498 error = ENOEXEC;
499 goto out;
500 }
501 if (hdr->e_ident[EI_VERSION] != EV_CURRENT
502 || hdr->e_version != EV_CURRENT) {
503 link_elf_error(filename, "Unsupported file version");
504 error = ENOEXEC;
505 goto out;
506 }
507 if (hdr->e_type != ET_REL) {
508 error = ENOSYS;
509 goto out;
510 }
511 if (hdr->e_machine != ELF_TARG_MACH) {
512 link_elf_error(filename, "Unsupported machine");
513 error = ENOEXEC;
514 goto out;
515 }
516
517 lf = linker_make_file(filename, &link_elf_class);
518 if (!lf) {
519 error = ENOMEM;
520 goto out;
521 }
522 ef = (elf_file_t) lf;
523 ef->nprogtab = 0;
524 ef->e_shdr = 0;
525 ef->nreltab = 0;
526 ef->nrelatab = 0;
527
528 /* Allocate and read in the section header */
529 nbytes = hdr->e_shnum * hdr->e_shentsize;
530 if (nbytes == 0 || hdr->e_shoff == 0 ||
531 hdr->e_shentsize != sizeof(Elf_Shdr)) {
532 error = ENOEXEC;
533 goto out;
534 }
535 shdr = malloc(nbytes, M_LINKER, M_WAITOK);
536 ef->e_shdr = shdr;
537 error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)shdr, nbytes, hdr->e_shoff,
538 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td);
539 if (error)
540 goto out;
541 if (resid) {
542 error = ENOEXEC;
543 goto out;
544 }
545
546 /* Scan the section header for information and table sizing. */
547 nsym = 0;
548 symtabindex = -1;
549 symstrindex = -1;
550 for (i = 0; i < hdr->e_shnum; i++) {
551 if (shdr[i].sh_size == 0)
552 continue;
553 switch (shdr[i].sh_type) {
554 case SHT_PROGBITS:
555 case SHT_NOBITS:
556 ef->nprogtab++;
557 break;
558 case SHT_SYMTAB:
559 nsym++;
560 symtabindex = i;
561 symstrindex = shdr[i].sh_link;
562 break;
563 case SHT_REL:
564 ef->nreltab++;
565 break;
566 case SHT_RELA:
567 ef->nrelatab++;
568 break;
569 case SHT_STRTAB:
570 break;
571 }
572 }
573 if (ef->nprogtab == 0) {
574 link_elf_error(filename, "file has no contents");
575 error = ENOEXEC;
576 goto out;
577 }
578 if (nsym != 1) {
579 /* Only allow one symbol table for now */
580 link_elf_error(filename, "file has no valid symbol table");
581 error = ENOEXEC;
582 goto out;
583 }
584 if (symstrindex < 0 || symstrindex > hdr->e_shnum ||
585 shdr[symstrindex].sh_type != SHT_STRTAB) {
586 link_elf_error(filename, "file has invalid symbol strings");
587 error = ENOEXEC;
588 goto out;
589 }
590
591 /* Allocate space for tracking the load chunks */
592 if (ef->nprogtab != 0)
593 ef->progtab = malloc(ef->nprogtab * sizeof(*ef->progtab),
594 M_LINKER, M_WAITOK | M_ZERO);
595 if (ef->nreltab != 0)
596 ef->reltab = malloc(ef->nreltab * sizeof(*ef->reltab),
597 M_LINKER, M_WAITOK | M_ZERO);
598 if (ef->nrelatab != 0)
599 ef->relatab = malloc(ef->nrelatab * sizeof(*ef->relatab),
600 M_LINKER, M_WAITOK | M_ZERO);
601
602 if (symtabindex == -1)
603 panic("lost symbol table index");
604 /* Allocate space for and load the symbol table */
605 ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym);
606 ef->ddbsymtab = malloc(shdr[symtabindex].sh_size, M_LINKER, M_WAITOK);
607 error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)ef->ddbsymtab,
608 shdr[symtabindex].sh_size, shdr[symtabindex].sh_offset,
609 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
610 &resid, td);
611 if (error)
612 goto out;
613 if (resid != 0){
614 error = EINVAL;
615 goto out;
616 }
617
618 if (symstrindex == -1)
619 panic("lost symbol string index");
620 /* Allocate space for and load the symbol strings */
621 ef->ddbstrcnt = shdr[symstrindex].sh_size;
622 ef->ddbstrtab = malloc(shdr[symstrindex].sh_size, M_LINKER, M_WAITOK);
623 error = vn_rdwr(UIO_READ, nd.ni_vp, ef->ddbstrtab,
624 shdr[symstrindex].sh_size, shdr[symstrindex].sh_offset,
625 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
626 &resid, td);
627 if (error)
628 goto out;
629 if (resid != 0){
630 error = EINVAL;
631 goto out;
632 }
633
634 /* Do we have a string table for the section names? */
635 shstrindex = -1;
636 if (hdr->e_shstrndx != 0 &&
637 shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) {
638 shstrindex = hdr->e_shstrndx;
639 ef->shstrcnt = shdr[shstrindex].sh_size;
640 ef->shstrtab = malloc(shdr[shstrindex].sh_size, M_LINKER,
641 M_WAITOK);
642 error = vn_rdwr(UIO_READ, nd.ni_vp, ef->shstrtab,
643 shdr[shstrindex].sh_size, shdr[shstrindex].sh_offset,
644 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
645 &resid, td);
646 if (error)
647 goto out;
648 if (resid != 0){
649 error = EINVAL;
650 goto out;
651 }
652 }
653
654 /* Size up code/data(progbits) and bss(nobits). */
655 alignmask = 0;
656 for (i = 0; i < hdr->e_shnum; i++) {
657 if (shdr[i].sh_size == 0)
658 continue;
659 switch (shdr[i].sh_type) {
660 case SHT_PROGBITS:
661 case SHT_NOBITS:
662 alignmask = shdr[i].sh_addralign - 1;
663 mapsize += alignmask;
664 mapsize &= ~alignmask;
665 mapsize += shdr[i].sh_size;
666 break;
667 }
668 }
669
670 /*
671 * We know how much space we need for the text/data/bss/etc.
672 * This stuff needs to be in a single chunk so that profiling etc
673 * can get the bounds and gdb can associate offsets with modules
674 */
675 ef->object = vm_object_allocate(OBJT_DEFAULT,
676 round_page(mapsize) >> PAGE_SHIFT);
677 if (ef->object == NULL) {
678 error = ENOMEM;
679 goto out;
680 }
681 ef->address = (caddr_t) vm_map_min(kernel_map);
682
683 /*
684 * In order to satisfy amd64's architectural requirements on the
685 * location of code and data in the kernel's address space, request a
686 * mapping that is above the kernel.
687 */
688#ifdef __amd64__
689 mapbase = KERNBASE;
690#else
691 mapbase = VM_MIN_KERNEL_ADDRESS;
692#endif
693 error = vm_map_find(kernel_map, ef->object, 0, &mapbase,
694 round_page(mapsize), TRUE, VM_PROT_ALL, VM_PROT_ALL, FALSE);
695 if (error) {
696 vm_object_deallocate(ef->object);
697 ef->object = 0;
698 goto out;
699 }
700
701 /* Wire the pages */
702 error = vm_map_wire(kernel_map, mapbase,
703 mapbase + round_page(mapsize),
704 VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES);
705 if (error != KERN_SUCCESS) {
706 error = ENOMEM;
707 goto out;
708 }
709
710 /* Inform the kld system about the situation */
711 lf->address = ef->address = (caddr_t)mapbase;
712 lf->size = mapsize;
713
714 /*
715 * Now load code/data(progbits), zero bss(nobits), allocate space for
716 * and load relocs
717 */
718 pb = 0;
719 rl = 0;
720 ra = 0;
721 alignmask = 0;
722 for (i = 0; i < hdr->e_shnum; i++) {
723 if (shdr[i].sh_size == 0)
724 continue;
725 switch (shdr[i].sh_type) {
726 case SHT_PROGBITS:
727 case SHT_NOBITS:
728 alignmask = shdr[i].sh_addralign - 1;
729 mapbase += alignmask;
730 mapbase &= ~alignmask;
731 if (ef->shstrtab && shdr[i].sh_name != 0)
732 ef->progtab[pb].name =
733 ef->shstrtab + shdr[i].sh_name;
734 else if (shdr[i].sh_type == SHT_PROGBITS)
735 ef->progtab[pb].name = "<<PROGBITS>>";
736 else
737 ef->progtab[pb].name = "<<NOBITS>>";
738 if (ef->progtab[pb].name != NULL &&
739 !strcmp(ef->progtab[pb].name, DPCPU_SETNAME))
740 ef->progtab[pb].addr =
741 dpcpu_alloc(shdr[i].sh_size);
742#ifdef VIMAGE
743 else if (ef->progtab[pb].name != NULL &&
744 !strcmp(ef->progtab[pb].name, VNET_SETNAME))
745 ef->progtab[pb].addr =
746 vnet_data_alloc(shdr[i].sh_size);
747#endif
748 else
749 ef->progtab[pb].addr =
750 (void *)(uintptr_t)mapbase;
751 if (ef->progtab[pb].addr == NULL) {
752 error = ENOSPC;
753 goto out;
754 }
755 ef->progtab[pb].size = shdr[i].sh_size;
756 ef->progtab[pb].sec = i;
757 if (shdr[i].sh_type == SHT_PROGBITS) {
758 error = vn_rdwr(UIO_READ, nd.ni_vp,
759 ef->progtab[pb].addr,
760 shdr[i].sh_size, shdr[i].sh_offset,
761 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred,
762 NOCRED, &resid, td);
763 if (error)
764 goto out;
765 if (resid != 0){
766 error = EINVAL;
767 goto out;
768 }
769 /* Initialize the per-cpu or vnet area. */
770 if (ef->progtab[pb].addr != (void *)mapbase &&
771 !strcmp(ef->progtab[pb].name, DPCPU_SETNAME))
772 dpcpu_copy(ef->progtab[pb].addr,
773 shdr[i].sh_size);
774#ifdef VIMAGE
775 else if (ef->progtab[pb].addr !=
776 (void *)mapbase &&
777 !strcmp(ef->progtab[pb].name, VNET_SETNAME))
778 vnet_data_copy(ef->progtab[pb].addr,
779 shdr[i].sh_size);
780#endif
781 } else
782 bzero(ef->progtab[pb].addr, shdr[i].sh_size);
783
784 /* Update all symbol values with the offset. */
785 for (j = 0; j < ef->ddbsymcnt; j++) {
786 es = &ef->ddbsymtab[j];
787 if (es->st_shndx != i)
788 continue;
789 es->st_value += (Elf_Addr)ef->progtab[pb].addr;
790 }
791 mapbase += shdr[i].sh_size;
792 pb++;
793 break;
794 case SHT_REL:
795 ef->reltab[rl].rel = malloc(shdr[i].sh_size, M_LINKER,
796 M_WAITOK);
797 ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel);
798 ef->reltab[rl].sec = shdr[i].sh_info;
799 error = vn_rdwr(UIO_READ, nd.ni_vp,
800 (void *)ef->reltab[rl].rel,
801 shdr[i].sh_size, shdr[i].sh_offset,
802 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
803 &resid, td);
804 if (error)
805 goto out;
806 if (resid != 0){
807 error = EINVAL;
808 goto out;
809 }
810 rl++;
811 break;
812 case SHT_RELA:
813 ef->relatab[ra].rela = malloc(shdr[i].sh_size, M_LINKER,
814 M_WAITOK);
815 ef->relatab[ra].nrela =
816 shdr[i].sh_size / sizeof(Elf_Rela);
817 ef->relatab[ra].sec = shdr[i].sh_info;
818 error = vn_rdwr(UIO_READ, nd.ni_vp,
819 (void *)ef->relatab[ra].rela,
820 shdr[i].sh_size, shdr[i].sh_offset,
821 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
822 &resid, td);
823 if (error)
824 goto out;
825 if (resid != 0){
826 error = EINVAL;
827 goto out;
828 }
829 ra++;
830 break;
831 }
832 }
833 if (pb != ef->nprogtab)
834 panic("lost progbits");
835 if (rl != ef->nreltab)
836 panic("lost reltab");
837 if (ra != ef->nrelatab)
838 panic("lost relatab");
839 if (mapbase != (vm_offset_t)ef->address + mapsize)
840 panic("mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n",
841 (u_long)mapbase, ef->address, (u_long)mapsize,
842 (u_long)(vm_offset_t)ef->address + mapsize);
843
844 /* Local intra-module relocations */
845 link_elf_reloc_local(lf);
846
847 /* Pull in dependencies */
848 VOP_UNLOCK(nd.ni_vp, 0);
849 error = linker_load_dependencies(lf);
850 vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY);
851 if (error)
852 goto out;
853
854 /* External relocations */
855 error = relocate_file(ef);
856 if (error)
857 goto out;
858
859 /* Notify MD code that a module is being loaded. */
860 error = elf_cpu_load_file(lf);
861 if (error)
862 goto out;
863
864 *result = lf;
865
866out:
867 VOP_UNLOCK(nd.ni_vp, 0);
868 vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
464 NDFREE(&nd, NDF_ONLY_PNBUF);
465 if (nd.ni_vp->v_type != VREG) {
466 error = ENOEXEC;
467 goto out;
468 }
469#ifdef MAC
470 error = mac_kld_check_load(td->td_ucred, nd.ni_vp);
471 if (error) {
472 goto out;
473 }
474#endif
475
476 /* Read the elf header from the file. */
477 hdr = malloc(sizeof(*hdr), M_LINKER, M_WAITOK);
478 error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)hdr, sizeof(*hdr), 0,
479 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
480 &resid, td);
481 if (error)
482 goto out;
483 if (resid != 0){
484 error = ENOEXEC;
485 goto out;
486 }
487
488 if (!IS_ELF(*hdr)) {
489 error = ENOEXEC;
490 goto out;
491 }
492
493 if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS
494 || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
495 link_elf_error(filename, "Unsupported file layout");
496 error = ENOEXEC;
497 goto out;
498 }
499 if (hdr->e_ident[EI_VERSION] != EV_CURRENT
500 || hdr->e_version != EV_CURRENT) {
501 link_elf_error(filename, "Unsupported file version");
502 error = ENOEXEC;
503 goto out;
504 }
505 if (hdr->e_type != ET_REL) {
506 error = ENOSYS;
507 goto out;
508 }
509 if (hdr->e_machine != ELF_TARG_MACH) {
510 link_elf_error(filename, "Unsupported machine");
511 error = ENOEXEC;
512 goto out;
513 }
514
515 lf = linker_make_file(filename, &link_elf_class);
516 if (!lf) {
517 error = ENOMEM;
518 goto out;
519 }
520 ef = (elf_file_t) lf;
521 ef->nprogtab = 0;
522 ef->e_shdr = 0;
523 ef->nreltab = 0;
524 ef->nrelatab = 0;
525
526 /* Allocate and read in the section header */
527 nbytes = hdr->e_shnum * hdr->e_shentsize;
528 if (nbytes == 0 || hdr->e_shoff == 0 ||
529 hdr->e_shentsize != sizeof(Elf_Shdr)) {
530 error = ENOEXEC;
531 goto out;
532 }
533 shdr = malloc(nbytes, M_LINKER, M_WAITOK);
534 ef->e_shdr = shdr;
535 error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)shdr, nbytes, hdr->e_shoff,
536 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td);
537 if (error)
538 goto out;
539 if (resid) {
540 error = ENOEXEC;
541 goto out;
542 }
543
544 /* Scan the section header for information and table sizing. */
545 nsym = 0;
546 symtabindex = -1;
547 symstrindex = -1;
548 for (i = 0; i < hdr->e_shnum; i++) {
549 if (shdr[i].sh_size == 0)
550 continue;
551 switch (shdr[i].sh_type) {
552 case SHT_PROGBITS:
553 case SHT_NOBITS:
554 ef->nprogtab++;
555 break;
556 case SHT_SYMTAB:
557 nsym++;
558 symtabindex = i;
559 symstrindex = shdr[i].sh_link;
560 break;
561 case SHT_REL:
562 ef->nreltab++;
563 break;
564 case SHT_RELA:
565 ef->nrelatab++;
566 break;
567 case SHT_STRTAB:
568 break;
569 }
570 }
571 if (ef->nprogtab == 0) {
572 link_elf_error(filename, "file has no contents");
573 error = ENOEXEC;
574 goto out;
575 }
576 if (nsym != 1) {
577 /* Only allow one symbol table for now */
578 link_elf_error(filename, "file has no valid symbol table");
579 error = ENOEXEC;
580 goto out;
581 }
582 if (symstrindex < 0 || symstrindex > hdr->e_shnum ||
583 shdr[symstrindex].sh_type != SHT_STRTAB) {
584 link_elf_error(filename, "file has invalid symbol strings");
585 error = ENOEXEC;
586 goto out;
587 }
588
589 /* Allocate space for tracking the load chunks */
590 if (ef->nprogtab != 0)
591 ef->progtab = malloc(ef->nprogtab * sizeof(*ef->progtab),
592 M_LINKER, M_WAITOK | M_ZERO);
593 if (ef->nreltab != 0)
594 ef->reltab = malloc(ef->nreltab * sizeof(*ef->reltab),
595 M_LINKER, M_WAITOK | M_ZERO);
596 if (ef->nrelatab != 0)
597 ef->relatab = malloc(ef->nrelatab * sizeof(*ef->relatab),
598 M_LINKER, M_WAITOK | M_ZERO);
599
600 if (symtabindex == -1)
601 panic("lost symbol table index");
602 /* Allocate space for and load the symbol table */
603 ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym);
604 ef->ddbsymtab = malloc(shdr[symtabindex].sh_size, M_LINKER, M_WAITOK);
605 error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)ef->ddbsymtab,
606 shdr[symtabindex].sh_size, shdr[symtabindex].sh_offset,
607 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
608 &resid, td);
609 if (error)
610 goto out;
611 if (resid != 0){
612 error = EINVAL;
613 goto out;
614 }
615
616 if (symstrindex == -1)
617 panic("lost symbol string index");
618 /* Allocate space for and load the symbol strings */
619 ef->ddbstrcnt = shdr[symstrindex].sh_size;
620 ef->ddbstrtab = malloc(shdr[symstrindex].sh_size, M_LINKER, M_WAITOK);
621 error = vn_rdwr(UIO_READ, nd.ni_vp, ef->ddbstrtab,
622 shdr[symstrindex].sh_size, shdr[symstrindex].sh_offset,
623 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
624 &resid, td);
625 if (error)
626 goto out;
627 if (resid != 0){
628 error = EINVAL;
629 goto out;
630 }
631
632 /* Do we have a string table for the section names? */
633 shstrindex = -1;
634 if (hdr->e_shstrndx != 0 &&
635 shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) {
636 shstrindex = hdr->e_shstrndx;
637 ef->shstrcnt = shdr[shstrindex].sh_size;
638 ef->shstrtab = malloc(shdr[shstrindex].sh_size, M_LINKER,
639 M_WAITOK);
640 error = vn_rdwr(UIO_READ, nd.ni_vp, ef->shstrtab,
641 shdr[shstrindex].sh_size, shdr[shstrindex].sh_offset,
642 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
643 &resid, td);
644 if (error)
645 goto out;
646 if (resid != 0){
647 error = EINVAL;
648 goto out;
649 }
650 }
651
652 /* Size up code/data(progbits) and bss(nobits). */
653 alignmask = 0;
654 for (i = 0; i < hdr->e_shnum; i++) {
655 if (shdr[i].sh_size == 0)
656 continue;
657 switch (shdr[i].sh_type) {
658 case SHT_PROGBITS:
659 case SHT_NOBITS:
660 alignmask = shdr[i].sh_addralign - 1;
661 mapsize += alignmask;
662 mapsize &= ~alignmask;
663 mapsize += shdr[i].sh_size;
664 break;
665 }
666 }
667
668 /*
669 * We know how much space we need for the text/data/bss/etc.
670 * This stuff needs to be in a single chunk so that profiling etc
671 * can get the bounds and gdb can associate offsets with modules
672 */
673 ef->object = vm_object_allocate(OBJT_DEFAULT,
674 round_page(mapsize) >> PAGE_SHIFT);
675 if (ef->object == NULL) {
676 error = ENOMEM;
677 goto out;
678 }
679 ef->address = (caddr_t) vm_map_min(kernel_map);
680
681 /*
682 * In order to satisfy amd64's architectural requirements on the
683 * location of code and data in the kernel's address space, request a
684 * mapping that is above the kernel.
685 */
686#ifdef __amd64__
687 mapbase = KERNBASE;
688#else
689 mapbase = VM_MIN_KERNEL_ADDRESS;
690#endif
691 error = vm_map_find(kernel_map, ef->object, 0, &mapbase,
692 round_page(mapsize), TRUE, VM_PROT_ALL, VM_PROT_ALL, FALSE);
693 if (error) {
694 vm_object_deallocate(ef->object);
695 ef->object = 0;
696 goto out;
697 }
698
699 /* Wire the pages */
700 error = vm_map_wire(kernel_map, mapbase,
701 mapbase + round_page(mapsize),
702 VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES);
703 if (error != KERN_SUCCESS) {
704 error = ENOMEM;
705 goto out;
706 }
707
708 /* Inform the kld system about the situation */
709 lf->address = ef->address = (caddr_t)mapbase;
710 lf->size = mapsize;
711
712 /*
713 * Now load code/data(progbits), zero bss(nobits), allocate space for
714 * and load relocs
715 */
716 pb = 0;
717 rl = 0;
718 ra = 0;
719 alignmask = 0;
720 for (i = 0; i < hdr->e_shnum; i++) {
721 if (shdr[i].sh_size == 0)
722 continue;
723 switch (shdr[i].sh_type) {
724 case SHT_PROGBITS:
725 case SHT_NOBITS:
726 alignmask = shdr[i].sh_addralign - 1;
727 mapbase += alignmask;
728 mapbase &= ~alignmask;
729 if (ef->shstrtab && shdr[i].sh_name != 0)
730 ef->progtab[pb].name =
731 ef->shstrtab + shdr[i].sh_name;
732 else if (shdr[i].sh_type == SHT_PROGBITS)
733 ef->progtab[pb].name = "<<PROGBITS>>";
734 else
735 ef->progtab[pb].name = "<<NOBITS>>";
736 if (ef->progtab[pb].name != NULL &&
737 !strcmp(ef->progtab[pb].name, DPCPU_SETNAME))
738 ef->progtab[pb].addr =
739 dpcpu_alloc(shdr[i].sh_size);
740#ifdef VIMAGE
741 else if (ef->progtab[pb].name != NULL &&
742 !strcmp(ef->progtab[pb].name, VNET_SETNAME))
743 ef->progtab[pb].addr =
744 vnet_data_alloc(shdr[i].sh_size);
745#endif
746 else
747 ef->progtab[pb].addr =
748 (void *)(uintptr_t)mapbase;
749 if (ef->progtab[pb].addr == NULL) {
750 error = ENOSPC;
751 goto out;
752 }
753 ef->progtab[pb].size = shdr[i].sh_size;
754 ef->progtab[pb].sec = i;
755 if (shdr[i].sh_type == SHT_PROGBITS) {
756 error = vn_rdwr(UIO_READ, nd.ni_vp,
757 ef->progtab[pb].addr,
758 shdr[i].sh_size, shdr[i].sh_offset,
759 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred,
760 NOCRED, &resid, td);
761 if (error)
762 goto out;
763 if (resid != 0){
764 error = EINVAL;
765 goto out;
766 }
767 /* Initialize the per-cpu or vnet area. */
768 if (ef->progtab[pb].addr != (void *)mapbase &&
769 !strcmp(ef->progtab[pb].name, DPCPU_SETNAME))
770 dpcpu_copy(ef->progtab[pb].addr,
771 shdr[i].sh_size);
772#ifdef VIMAGE
773 else if (ef->progtab[pb].addr !=
774 (void *)mapbase &&
775 !strcmp(ef->progtab[pb].name, VNET_SETNAME))
776 vnet_data_copy(ef->progtab[pb].addr,
777 shdr[i].sh_size);
778#endif
779 } else
780 bzero(ef->progtab[pb].addr, shdr[i].sh_size);
781
782 /* Update all symbol values with the offset. */
783 for (j = 0; j < ef->ddbsymcnt; j++) {
784 es = &ef->ddbsymtab[j];
785 if (es->st_shndx != i)
786 continue;
787 es->st_value += (Elf_Addr)ef->progtab[pb].addr;
788 }
789 mapbase += shdr[i].sh_size;
790 pb++;
791 break;
792 case SHT_REL:
793 ef->reltab[rl].rel = malloc(shdr[i].sh_size, M_LINKER,
794 M_WAITOK);
795 ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel);
796 ef->reltab[rl].sec = shdr[i].sh_info;
797 error = vn_rdwr(UIO_READ, nd.ni_vp,
798 (void *)ef->reltab[rl].rel,
799 shdr[i].sh_size, shdr[i].sh_offset,
800 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
801 &resid, td);
802 if (error)
803 goto out;
804 if (resid != 0){
805 error = EINVAL;
806 goto out;
807 }
808 rl++;
809 break;
810 case SHT_RELA:
811 ef->relatab[ra].rela = malloc(shdr[i].sh_size, M_LINKER,
812 M_WAITOK);
813 ef->relatab[ra].nrela =
814 shdr[i].sh_size / sizeof(Elf_Rela);
815 ef->relatab[ra].sec = shdr[i].sh_info;
816 error = vn_rdwr(UIO_READ, nd.ni_vp,
817 (void *)ef->relatab[ra].rela,
818 shdr[i].sh_size, shdr[i].sh_offset,
819 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
820 &resid, td);
821 if (error)
822 goto out;
823 if (resid != 0){
824 error = EINVAL;
825 goto out;
826 }
827 ra++;
828 break;
829 }
830 }
831 if (pb != ef->nprogtab)
832 panic("lost progbits");
833 if (rl != ef->nreltab)
834 panic("lost reltab");
835 if (ra != ef->nrelatab)
836 panic("lost relatab");
837 if (mapbase != (vm_offset_t)ef->address + mapsize)
838 panic("mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n",
839 (u_long)mapbase, ef->address, (u_long)mapsize,
840 (u_long)(vm_offset_t)ef->address + mapsize);
841
842 /* Local intra-module relocations */
843 link_elf_reloc_local(lf);
844
845 /* Pull in dependencies */
846 VOP_UNLOCK(nd.ni_vp, 0);
847 error = linker_load_dependencies(lf);
848 vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY);
849 if (error)
850 goto out;
851
852 /* External relocations */
853 error = relocate_file(ef);
854 if (error)
855 goto out;
856
857 /* Notify MD code that a module is being loaded. */
858 error = elf_cpu_load_file(lf);
859 if (error)
860 goto out;
861
862 *result = lf;
863
864out:
865 VOP_UNLOCK(nd.ni_vp, 0);
866 vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
869 VFS_UNLOCK_GIANT(vfslocked);
870 if (error && lf)
871 linker_file_unload(lf, LINKER_UNLOAD_FORCE);
872 if (hdr)
873 free(hdr, M_LINKER);
874
875 return error;
876}
877
878static void
879link_elf_unload_file(linker_file_t file)
880{
881 elf_file_t ef = (elf_file_t) file;
882 int i;
883
884 /* Notify MD code that a module is being unloaded. */
885 elf_cpu_unload_file(file);
886
887 if (ef->progtab) {
888 for (i = 0; i < ef->nprogtab; i++) {
889 if (ef->progtab[i].size == 0)
890 continue;
891 if (ef->progtab[i].name == NULL)
892 continue;
893 if (!strcmp(ef->progtab[i].name, DPCPU_SETNAME))
894 dpcpu_free(ef->progtab[i].addr,
895 ef->progtab[i].size);
896#ifdef VIMAGE
897 else if (!strcmp(ef->progtab[i].name, VNET_SETNAME))
898 vnet_data_free(ef->progtab[i].addr,
899 ef->progtab[i].size);
900#endif
901 }
902 }
903 if (ef->preloaded) {
904 if (ef->reltab)
905 free(ef->reltab, M_LINKER);
906 if (ef->relatab)
907 free(ef->relatab, M_LINKER);
908 if (ef->progtab)
909 free(ef->progtab, M_LINKER);
910 if (ef->ctftab)
911 free(ef->ctftab, M_LINKER);
912 if (ef->ctfoff)
913 free(ef->ctfoff, M_LINKER);
914 if (ef->typoff)
915 free(ef->typoff, M_LINKER);
916 if (file->filename != NULL)
917 preload_delete_name(file->filename);
918 /* XXX reclaim module memory? */
919 return;
920 }
921
922 for (i = 0; i < ef->nreltab; i++)
923 if (ef->reltab[i].rel)
924 free(ef->reltab[i].rel, M_LINKER);
925 for (i = 0; i < ef->nrelatab; i++)
926 if (ef->relatab[i].rela)
927 free(ef->relatab[i].rela, M_LINKER);
928 if (ef->reltab)
929 free(ef->reltab, M_LINKER);
930 if (ef->relatab)
931 free(ef->relatab, M_LINKER);
932 if (ef->progtab)
933 free(ef->progtab, M_LINKER);
934
935 if (ef->object) {
936 vm_map_remove(kernel_map, (vm_offset_t) ef->address,
937 (vm_offset_t) ef->address +
938 (ef->object->size << PAGE_SHIFT));
939 }
940 if (ef->e_shdr)
941 free(ef->e_shdr, M_LINKER);
942 if (ef->ddbsymtab)
943 free(ef->ddbsymtab, M_LINKER);
944 if (ef->ddbstrtab)
945 free(ef->ddbstrtab, M_LINKER);
946 if (ef->shstrtab)
947 free(ef->shstrtab, M_LINKER);
948 if (ef->ctftab)
949 free(ef->ctftab, M_LINKER);
950 if (ef->ctfoff)
951 free(ef->ctfoff, M_LINKER);
952 if (ef->typoff)
953 free(ef->typoff, M_LINKER);
954}
955
956static const char *
957symbol_name(elf_file_t ef, Elf_Size r_info)
958{
959 const Elf_Sym *ref;
960
961 if (ELF_R_SYM(r_info)) {
962 ref = ef->ddbsymtab + ELF_R_SYM(r_info);
963 return ef->ddbstrtab + ref->st_name;
964 } else
965 return NULL;
966}
967
968static Elf_Addr
969findbase(elf_file_t ef, int sec)
970{
971 int i;
972 Elf_Addr base = 0;
973
974 for (i = 0; i < ef->nprogtab; i++) {
975 if (sec == ef->progtab[i].sec) {
976 base = (Elf_Addr)ef->progtab[i].addr;
977 break;
978 }
979 }
980 return base;
981}
982
983static int
984relocate_file(elf_file_t ef)
985{
986 const Elf_Rel *rellim;
987 const Elf_Rel *rel;
988 const Elf_Rela *relalim;
989 const Elf_Rela *rela;
990 const char *symname;
991 const Elf_Sym *sym;
992 int i;
993 Elf_Size symidx;
994 Elf_Addr base;
995
996
997 /* Perform relocations without addend if there are any: */
998 for (i = 0; i < ef->nreltab; i++) {
999 rel = ef->reltab[i].rel;
1000 if (rel == NULL)
1001 panic("lost a reltab!");
1002 rellim = rel + ef->reltab[i].nrel;
1003 base = findbase(ef, ef->reltab[i].sec);
1004 if (base == 0)
1005 panic("lost base for reltab");
1006 for ( ; rel < rellim; rel++) {
1007 symidx = ELF_R_SYM(rel->r_info);
1008 if (symidx >= ef->ddbsymcnt)
1009 continue;
1010 sym = ef->ddbsymtab + symidx;
1011 /* Local relocs are already done */
1012 if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
1013 continue;
1014 if (elf_reloc(&ef->lf, base, rel, ELF_RELOC_REL,
1015 elf_obj_lookup)) {
1016 symname = symbol_name(ef, rel->r_info);
1017 printf("link_elf_obj: symbol %s undefined\n",
1018 symname);
1019 return ENOENT;
1020 }
1021 }
1022 }
1023
1024 /* Perform relocations with addend if there are any: */
1025 for (i = 0; i < ef->nrelatab; i++) {
1026 rela = ef->relatab[i].rela;
1027 if (rela == NULL)
1028 panic("lost a relatab!");
1029 relalim = rela + ef->relatab[i].nrela;
1030 base = findbase(ef, ef->relatab[i].sec);
1031 if (base == 0)
1032 panic("lost base for relatab");
1033 for ( ; rela < relalim; rela++) {
1034 symidx = ELF_R_SYM(rela->r_info);
1035 if (symidx >= ef->ddbsymcnt)
1036 continue;
1037 sym = ef->ddbsymtab + symidx;
1038 /* Local relocs are already done */
1039 if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
1040 continue;
1041 if (elf_reloc(&ef->lf, base, rela, ELF_RELOC_RELA,
1042 elf_obj_lookup)) {
1043 symname = symbol_name(ef, rela->r_info);
1044 printf("link_elf_obj: symbol %s undefined\n",
1045 symname);
1046 return ENOENT;
1047 }
1048 }
1049 }
1050
1051 return 0;
1052}
1053
1054static int
1055link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t *sym)
1056{
1057 elf_file_t ef = (elf_file_t) lf;
1058 const Elf_Sym *symp;
1059 const char *strp;
1060 int i;
1061
1062 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
1063 strp = ef->ddbstrtab + symp->st_name;
1064 if (symp->st_shndx != SHN_UNDEF && strcmp(name, strp) == 0) {
1065 *sym = (c_linker_sym_t) symp;
1066 return 0;
1067 }
1068 }
1069 return ENOENT;
1070}
1071
1072static int
1073link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
1074 linker_symval_t *symval)
1075{
1076 elf_file_t ef = (elf_file_t) lf;
1077 const Elf_Sym *es = (const Elf_Sym*) sym;
1078
1079 if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) {
1080 symval->name = ef->ddbstrtab + es->st_name;
1081 symval->value = (caddr_t)es->st_value;
1082 symval->size = es->st_size;
1083 return 0;
1084 }
1085 return ENOENT;
1086}
1087
1088static int
1089link_elf_search_symbol(linker_file_t lf, caddr_t value,
1090 c_linker_sym_t *sym, long *diffp)
1091{
1092 elf_file_t ef = (elf_file_t) lf;
1093 u_long off = (uintptr_t) (void *) value;
1094 u_long diff = off;
1095 u_long st_value;
1096 const Elf_Sym *es;
1097 const Elf_Sym *best = 0;
1098 int i;
1099
1100 for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) {
1101 if (es->st_name == 0)
1102 continue;
1103 st_value = es->st_value;
1104 if (off >= st_value) {
1105 if (off - st_value < diff) {
1106 diff = off - st_value;
1107 best = es;
1108 if (diff == 0)
1109 break;
1110 } else if (off - st_value == diff) {
1111 best = es;
1112 }
1113 }
1114 }
1115 if (best == 0)
1116 *diffp = off;
1117 else
1118 *diffp = diff;
1119 *sym = (c_linker_sym_t) best;
1120
1121 return 0;
1122}
1123
1124/*
1125 * Look up a linker set on an ELF system.
1126 */
1127static int
1128link_elf_lookup_set(linker_file_t lf, const char *name,
1129 void ***startp, void ***stopp, int *countp)
1130{
1131 elf_file_t ef = (elf_file_t)lf;
1132 void **start, **stop;
1133 int i, count;
1134
1135 /* Relative to section number */
1136 for (i = 0; i < ef->nprogtab; i++) {
1137 if ((strncmp(ef->progtab[i].name, "set_", 4) == 0) &&
1138 strcmp(ef->progtab[i].name + 4, name) == 0) {
1139 start = (void **)ef->progtab[i].addr;
1140 stop = (void **)((char *)ef->progtab[i].addr +
1141 ef->progtab[i].size);
1142 count = stop - start;
1143 if (startp)
1144 *startp = start;
1145 if (stopp)
1146 *stopp = stop;
1147 if (countp)
1148 *countp = count;
1149 return (0);
1150 }
1151 }
1152 return (ESRCH);
1153}
1154
1155static int
1156link_elf_each_function_name(linker_file_t file,
1157 int (*callback)(const char *, void *), void *opaque)
1158{
1159 elf_file_t ef = (elf_file_t)file;
1160 const Elf_Sym *symp;
1161 int i, error;
1162
1163 /* Exhaustive search */
1164 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
1165 if (symp->st_value != 0 &&
1166 ELF_ST_TYPE(symp->st_info) == STT_FUNC) {
1167 error = callback(ef->ddbstrtab + symp->st_name, opaque);
1168 if (error)
1169 return (error);
1170 }
1171 }
1172 return (0);
1173}
1174
1175static int
1176link_elf_each_function_nameval(linker_file_t file,
1177 linker_function_nameval_callback_t callback, void *opaque)
1178{
1179 linker_symval_t symval;
1180 elf_file_t ef = (elf_file_t)file;
1181 const Elf_Sym* symp;
1182 int i, error;
1183
1184 /* Exhaustive search */
1185 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
1186 if (symp->st_value != 0 &&
1187 ELF_ST_TYPE(symp->st_info) == STT_FUNC) {
1188 error = link_elf_symbol_values(file, (c_linker_sym_t) symp, &symval);
1189 if (error)
1190 return (error);
1191 error = callback(file, i, &symval, opaque);
1192 if (error)
1193 return (error);
1194 }
1195 }
1196 return (0);
1197}
1198
1199/*
1200 * Symbol lookup function that can be used when the symbol index is known (ie
1201 * in relocations). It uses the symbol index instead of doing a fully fledged
1202 * hash table based lookup when such is valid. For example for local symbols.
1203 * This is not only more efficient, it's also more correct. It's not always
1204 * the case that the symbol can be found through the hash table.
1205 */
1206static Elf_Addr
1207elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps)
1208{
1209 elf_file_t ef = (elf_file_t)lf;
1210 const Elf_Sym *sym;
1211 const char *symbol;
1212 Elf_Addr ret;
1213
1214 /* Don't even try to lookup the symbol if the index is bogus. */
1215 if (symidx >= ef->ddbsymcnt)
1216 return (0);
1217
1218 sym = ef->ddbsymtab + symidx;
1219
1220 /* Quick answer if there is a definition included. */
1221 if (sym->st_shndx != SHN_UNDEF)
1222 return (sym->st_value);
1223
1224 /* If we get here, then it is undefined and needs a lookup. */
1225 switch (ELF_ST_BIND(sym->st_info)) {
1226 case STB_LOCAL:
1227 /* Local, but undefined? huh? */
1228 return (0);
1229
1230 case STB_GLOBAL:
1231 /* Relative to Data or Function name */
1232 symbol = ef->ddbstrtab + sym->st_name;
1233
1234 /* Force a lookup failure if the symbol name is bogus. */
1235 if (*symbol == 0)
1236 return (0);
1237 ret = ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps));
1238 return ret;
1239
1240 case STB_WEAK:
1241 printf("link_elf_obj: Weak symbols not supported\n");
1242 return (0);
1243
1244 default:
1245 return (0);
1246 }
1247}
1248
1249static void
1250link_elf_fix_link_set(elf_file_t ef)
1251{
1252 static const char startn[] = "__start_";
1253 static const char stopn[] = "__stop_";
1254 Elf_Sym *sym;
1255 const char *sym_name, *linkset_name;
1256 Elf_Addr startp, stopp;
1257 Elf_Size symidx;
1258 int start, i;
1259
1260 startp = stopp = 0;
1261 for (symidx = 1 /* zero entry is special */;
1262 symidx < ef->ddbsymcnt; symidx++) {
1263 sym = ef->ddbsymtab + symidx;
1264 if (sym->st_shndx != SHN_UNDEF)
1265 continue;
1266
1267 sym_name = ef->ddbstrtab + sym->st_name;
1268 if (strncmp(sym_name, startn, sizeof(startn) - 1) == 0) {
1269 start = 1;
1270 linkset_name = sym_name + sizeof(startn) - 1;
1271 }
1272 else if (strncmp(sym_name, stopn, sizeof(stopn) - 1) == 0) {
1273 start = 0;
1274 linkset_name = sym_name + sizeof(stopn) - 1;
1275 }
1276 else
1277 continue;
1278
1279 for (i = 0; i < ef->nprogtab; i++) {
1280 if (strcmp(ef->progtab[i].name, linkset_name) == 0) {
1281 startp = (Elf_Addr)ef->progtab[i].addr;
1282 stopp = (Elf_Addr)(startp + ef->progtab[i].size);
1283 break;
1284 }
1285 }
1286 if (i == ef->nprogtab)
1287 continue;
1288
1289 sym->st_value = start ? startp : stopp;
1290 sym->st_shndx = i;
1291 }
1292}
1293
1294static void
1295link_elf_reloc_local(linker_file_t lf)
1296{
1297 elf_file_t ef = (elf_file_t)lf;
1298 const Elf_Rel *rellim;
1299 const Elf_Rel *rel;
1300 const Elf_Rela *relalim;
1301 const Elf_Rela *rela;
1302 const Elf_Sym *sym;
1303 Elf_Addr base;
1304 int i;
1305 Elf_Size symidx;
1306
1307 link_elf_fix_link_set(ef);
1308
1309 /* Perform relocations without addend if there are any: */
1310 for (i = 0; i < ef->nreltab; i++) {
1311 rel = ef->reltab[i].rel;
1312 if (rel == NULL)
1313 panic("lost a reltab!");
1314 rellim = rel + ef->reltab[i].nrel;
1315 base = findbase(ef, ef->reltab[i].sec);
1316 if (base == 0)
1317 panic("lost base for reltab");
1318 for ( ; rel < rellim; rel++) {
1319 symidx = ELF_R_SYM(rel->r_info);
1320 if (symidx >= ef->ddbsymcnt)
1321 continue;
1322 sym = ef->ddbsymtab + symidx;
1323 /* Only do local relocs */
1324 if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
1325 continue;
1326 elf_reloc_local(lf, base, rel, ELF_RELOC_REL,
1327 elf_obj_lookup);
1328 }
1329 }
1330
1331 /* Perform relocations with addend if there are any: */
1332 for (i = 0; i < ef->nrelatab; i++) {
1333 rela = ef->relatab[i].rela;
1334 if (rela == NULL)
1335 panic("lost a relatab!");
1336 relalim = rela + ef->relatab[i].nrela;
1337 base = findbase(ef, ef->relatab[i].sec);
1338 if (base == 0)
1339 panic("lost base for relatab");
1340 for ( ; rela < relalim; rela++) {
1341 symidx = ELF_R_SYM(rela->r_info);
1342 if (symidx >= ef->ddbsymcnt)
1343 continue;
1344 sym = ef->ddbsymtab + symidx;
1345 /* Only do local relocs */
1346 if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
1347 continue;
1348 elf_reloc_local(lf, base, rela, ELF_RELOC_RELA,
1349 elf_obj_lookup);
1350 }
1351 }
1352}
1353
1354static long
1355link_elf_symtab_get(linker_file_t lf, const Elf_Sym **symtab)
1356{
1357 elf_file_t ef = (elf_file_t)lf;
1358
1359 *symtab = ef->ddbsymtab;
1360
1361 if (*symtab == NULL)
1362 return (0);
1363
1364 return (ef->ddbsymcnt);
1365}
1366
1367static long
1368link_elf_strtab_get(linker_file_t lf, caddr_t *strtab)
1369{
1370 elf_file_t ef = (elf_file_t)lf;
1371
1372 *strtab = ef->ddbstrtab;
1373
1374 if (*strtab == NULL)
1375 return (0);
1376
1377 return (ef->ddbstrcnt);
1378}
867 if (error && lf)
868 linker_file_unload(lf, LINKER_UNLOAD_FORCE);
869 if (hdr)
870 free(hdr, M_LINKER);
871
872 return error;
873}
874
875static void
876link_elf_unload_file(linker_file_t file)
877{
878 elf_file_t ef = (elf_file_t) file;
879 int i;
880
881 /* Notify MD code that a module is being unloaded. */
882 elf_cpu_unload_file(file);
883
884 if (ef->progtab) {
885 for (i = 0; i < ef->nprogtab; i++) {
886 if (ef->progtab[i].size == 0)
887 continue;
888 if (ef->progtab[i].name == NULL)
889 continue;
890 if (!strcmp(ef->progtab[i].name, DPCPU_SETNAME))
891 dpcpu_free(ef->progtab[i].addr,
892 ef->progtab[i].size);
893#ifdef VIMAGE
894 else if (!strcmp(ef->progtab[i].name, VNET_SETNAME))
895 vnet_data_free(ef->progtab[i].addr,
896 ef->progtab[i].size);
897#endif
898 }
899 }
900 if (ef->preloaded) {
901 if (ef->reltab)
902 free(ef->reltab, M_LINKER);
903 if (ef->relatab)
904 free(ef->relatab, M_LINKER);
905 if (ef->progtab)
906 free(ef->progtab, M_LINKER);
907 if (ef->ctftab)
908 free(ef->ctftab, M_LINKER);
909 if (ef->ctfoff)
910 free(ef->ctfoff, M_LINKER);
911 if (ef->typoff)
912 free(ef->typoff, M_LINKER);
913 if (file->filename != NULL)
914 preload_delete_name(file->filename);
915 /* XXX reclaim module memory? */
916 return;
917 }
918
919 for (i = 0; i < ef->nreltab; i++)
920 if (ef->reltab[i].rel)
921 free(ef->reltab[i].rel, M_LINKER);
922 for (i = 0; i < ef->nrelatab; i++)
923 if (ef->relatab[i].rela)
924 free(ef->relatab[i].rela, M_LINKER);
925 if (ef->reltab)
926 free(ef->reltab, M_LINKER);
927 if (ef->relatab)
928 free(ef->relatab, M_LINKER);
929 if (ef->progtab)
930 free(ef->progtab, M_LINKER);
931
932 if (ef->object) {
933 vm_map_remove(kernel_map, (vm_offset_t) ef->address,
934 (vm_offset_t) ef->address +
935 (ef->object->size << PAGE_SHIFT));
936 }
937 if (ef->e_shdr)
938 free(ef->e_shdr, M_LINKER);
939 if (ef->ddbsymtab)
940 free(ef->ddbsymtab, M_LINKER);
941 if (ef->ddbstrtab)
942 free(ef->ddbstrtab, M_LINKER);
943 if (ef->shstrtab)
944 free(ef->shstrtab, M_LINKER);
945 if (ef->ctftab)
946 free(ef->ctftab, M_LINKER);
947 if (ef->ctfoff)
948 free(ef->ctfoff, M_LINKER);
949 if (ef->typoff)
950 free(ef->typoff, M_LINKER);
951}
952
953static const char *
954symbol_name(elf_file_t ef, Elf_Size r_info)
955{
956 const Elf_Sym *ref;
957
958 if (ELF_R_SYM(r_info)) {
959 ref = ef->ddbsymtab + ELF_R_SYM(r_info);
960 return ef->ddbstrtab + ref->st_name;
961 } else
962 return NULL;
963}
964
965static Elf_Addr
966findbase(elf_file_t ef, int sec)
967{
968 int i;
969 Elf_Addr base = 0;
970
971 for (i = 0; i < ef->nprogtab; i++) {
972 if (sec == ef->progtab[i].sec) {
973 base = (Elf_Addr)ef->progtab[i].addr;
974 break;
975 }
976 }
977 return base;
978}
979
980static int
981relocate_file(elf_file_t ef)
982{
983 const Elf_Rel *rellim;
984 const Elf_Rel *rel;
985 const Elf_Rela *relalim;
986 const Elf_Rela *rela;
987 const char *symname;
988 const Elf_Sym *sym;
989 int i;
990 Elf_Size symidx;
991 Elf_Addr base;
992
993
994 /* Perform relocations without addend if there are any: */
995 for (i = 0; i < ef->nreltab; i++) {
996 rel = ef->reltab[i].rel;
997 if (rel == NULL)
998 panic("lost a reltab!");
999 rellim = rel + ef->reltab[i].nrel;
1000 base = findbase(ef, ef->reltab[i].sec);
1001 if (base == 0)
1002 panic("lost base for reltab");
1003 for ( ; rel < rellim; rel++) {
1004 symidx = ELF_R_SYM(rel->r_info);
1005 if (symidx >= ef->ddbsymcnt)
1006 continue;
1007 sym = ef->ddbsymtab + symidx;
1008 /* Local relocs are already done */
1009 if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
1010 continue;
1011 if (elf_reloc(&ef->lf, base, rel, ELF_RELOC_REL,
1012 elf_obj_lookup)) {
1013 symname = symbol_name(ef, rel->r_info);
1014 printf("link_elf_obj: symbol %s undefined\n",
1015 symname);
1016 return ENOENT;
1017 }
1018 }
1019 }
1020
1021 /* Perform relocations with addend if there are any: */
1022 for (i = 0; i < ef->nrelatab; i++) {
1023 rela = ef->relatab[i].rela;
1024 if (rela == NULL)
1025 panic("lost a relatab!");
1026 relalim = rela + ef->relatab[i].nrela;
1027 base = findbase(ef, ef->relatab[i].sec);
1028 if (base == 0)
1029 panic("lost base for relatab");
1030 for ( ; rela < relalim; rela++) {
1031 symidx = ELF_R_SYM(rela->r_info);
1032 if (symidx >= ef->ddbsymcnt)
1033 continue;
1034 sym = ef->ddbsymtab + symidx;
1035 /* Local relocs are already done */
1036 if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
1037 continue;
1038 if (elf_reloc(&ef->lf, base, rela, ELF_RELOC_RELA,
1039 elf_obj_lookup)) {
1040 symname = symbol_name(ef, rela->r_info);
1041 printf("link_elf_obj: symbol %s undefined\n",
1042 symname);
1043 return ENOENT;
1044 }
1045 }
1046 }
1047
1048 return 0;
1049}
1050
1051static int
1052link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t *sym)
1053{
1054 elf_file_t ef = (elf_file_t) lf;
1055 const Elf_Sym *symp;
1056 const char *strp;
1057 int i;
1058
1059 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
1060 strp = ef->ddbstrtab + symp->st_name;
1061 if (symp->st_shndx != SHN_UNDEF && strcmp(name, strp) == 0) {
1062 *sym = (c_linker_sym_t) symp;
1063 return 0;
1064 }
1065 }
1066 return ENOENT;
1067}
1068
1069static int
1070link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
1071 linker_symval_t *symval)
1072{
1073 elf_file_t ef = (elf_file_t) lf;
1074 const Elf_Sym *es = (const Elf_Sym*) sym;
1075
1076 if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) {
1077 symval->name = ef->ddbstrtab + es->st_name;
1078 symval->value = (caddr_t)es->st_value;
1079 symval->size = es->st_size;
1080 return 0;
1081 }
1082 return ENOENT;
1083}
1084
1085static int
1086link_elf_search_symbol(linker_file_t lf, caddr_t value,
1087 c_linker_sym_t *sym, long *diffp)
1088{
1089 elf_file_t ef = (elf_file_t) lf;
1090 u_long off = (uintptr_t) (void *) value;
1091 u_long diff = off;
1092 u_long st_value;
1093 const Elf_Sym *es;
1094 const Elf_Sym *best = 0;
1095 int i;
1096
1097 for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) {
1098 if (es->st_name == 0)
1099 continue;
1100 st_value = es->st_value;
1101 if (off >= st_value) {
1102 if (off - st_value < diff) {
1103 diff = off - st_value;
1104 best = es;
1105 if (diff == 0)
1106 break;
1107 } else if (off - st_value == diff) {
1108 best = es;
1109 }
1110 }
1111 }
1112 if (best == 0)
1113 *diffp = off;
1114 else
1115 *diffp = diff;
1116 *sym = (c_linker_sym_t) best;
1117
1118 return 0;
1119}
1120
1121/*
1122 * Look up a linker set on an ELF system.
1123 */
1124static int
1125link_elf_lookup_set(linker_file_t lf, const char *name,
1126 void ***startp, void ***stopp, int *countp)
1127{
1128 elf_file_t ef = (elf_file_t)lf;
1129 void **start, **stop;
1130 int i, count;
1131
1132 /* Relative to section number */
1133 for (i = 0; i < ef->nprogtab; i++) {
1134 if ((strncmp(ef->progtab[i].name, "set_", 4) == 0) &&
1135 strcmp(ef->progtab[i].name + 4, name) == 0) {
1136 start = (void **)ef->progtab[i].addr;
1137 stop = (void **)((char *)ef->progtab[i].addr +
1138 ef->progtab[i].size);
1139 count = stop - start;
1140 if (startp)
1141 *startp = start;
1142 if (stopp)
1143 *stopp = stop;
1144 if (countp)
1145 *countp = count;
1146 return (0);
1147 }
1148 }
1149 return (ESRCH);
1150}
1151
1152static int
1153link_elf_each_function_name(linker_file_t file,
1154 int (*callback)(const char *, void *), void *opaque)
1155{
1156 elf_file_t ef = (elf_file_t)file;
1157 const Elf_Sym *symp;
1158 int i, error;
1159
1160 /* Exhaustive search */
1161 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
1162 if (symp->st_value != 0 &&
1163 ELF_ST_TYPE(symp->st_info) == STT_FUNC) {
1164 error = callback(ef->ddbstrtab + symp->st_name, opaque);
1165 if (error)
1166 return (error);
1167 }
1168 }
1169 return (0);
1170}
1171
1172static int
1173link_elf_each_function_nameval(linker_file_t file,
1174 linker_function_nameval_callback_t callback, void *opaque)
1175{
1176 linker_symval_t symval;
1177 elf_file_t ef = (elf_file_t)file;
1178 const Elf_Sym* symp;
1179 int i, error;
1180
1181 /* Exhaustive search */
1182 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
1183 if (symp->st_value != 0 &&
1184 ELF_ST_TYPE(symp->st_info) == STT_FUNC) {
1185 error = link_elf_symbol_values(file, (c_linker_sym_t) symp, &symval);
1186 if (error)
1187 return (error);
1188 error = callback(file, i, &symval, opaque);
1189 if (error)
1190 return (error);
1191 }
1192 }
1193 return (0);
1194}
1195
1196/*
1197 * Symbol lookup function that can be used when the symbol index is known (ie
1198 * in relocations). It uses the symbol index instead of doing a fully fledged
1199 * hash table based lookup when such is valid. For example for local symbols.
1200 * This is not only more efficient, it's also more correct. It's not always
1201 * the case that the symbol can be found through the hash table.
1202 */
1203static Elf_Addr
1204elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps)
1205{
1206 elf_file_t ef = (elf_file_t)lf;
1207 const Elf_Sym *sym;
1208 const char *symbol;
1209 Elf_Addr ret;
1210
1211 /* Don't even try to lookup the symbol if the index is bogus. */
1212 if (symidx >= ef->ddbsymcnt)
1213 return (0);
1214
1215 sym = ef->ddbsymtab + symidx;
1216
1217 /* Quick answer if there is a definition included. */
1218 if (sym->st_shndx != SHN_UNDEF)
1219 return (sym->st_value);
1220
1221 /* If we get here, then it is undefined and needs a lookup. */
1222 switch (ELF_ST_BIND(sym->st_info)) {
1223 case STB_LOCAL:
1224 /* Local, but undefined? huh? */
1225 return (0);
1226
1227 case STB_GLOBAL:
1228 /* Relative to Data or Function name */
1229 symbol = ef->ddbstrtab + sym->st_name;
1230
1231 /* Force a lookup failure if the symbol name is bogus. */
1232 if (*symbol == 0)
1233 return (0);
1234 ret = ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps));
1235 return ret;
1236
1237 case STB_WEAK:
1238 printf("link_elf_obj: Weak symbols not supported\n");
1239 return (0);
1240
1241 default:
1242 return (0);
1243 }
1244}
1245
1246static void
1247link_elf_fix_link_set(elf_file_t ef)
1248{
1249 static const char startn[] = "__start_";
1250 static const char stopn[] = "__stop_";
1251 Elf_Sym *sym;
1252 const char *sym_name, *linkset_name;
1253 Elf_Addr startp, stopp;
1254 Elf_Size symidx;
1255 int start, i;
1256
1257 startp = stopp = 0;
1258 for (symidx = 1 /* zero entry is special */;
1259 symidx < ef->ddbsymcnt; symidx++) {
1260 sym = ef->ddbsymtab + symidx;
1261 if (sym->st_shndx != SHN_UNDEF)
1262 continue;
1263
1264 sym_name = ef->ddbstrtab + sym->st_name;
1265 if (strncmp(sym_name, startn, sizeof(startn) - 1) == 0) {
1266 start = 1;
1267 linkset_name = sym_name + sizeof(startn) - 1;
1268 }
1269 else if (strncmp(sym_name, stopn, sizeof(stopn) - 1) == 0) {
1270 start = 0;
1271 linkset_name = sym_name + sizeof(stopn) - 1;
1272 }
1273 else
1274 continue;
1275
1276 for (i = 0; i < ef->nprogtab; i++) {
1277 if (strcmp(ef->progtab[i].name, linkset_name) == 0) {
1278 startp = (Elf_Addr)ef->progtab[i].addr;
1279 stopp = (Elf_Addr)(startp + ef->progtab[i].size);
1280 break;
1281 }
1282 }
1283 if (i == ef->nprogtab)
1284 continue;
1285
1286 sym->st_value = start ? startp : stopp;
1287 sym->st_shndx = i;
1288 }
1289}
1290
1291static void
1292link_elf_reloc_local(linker_file_t lf)
1293{
1294 elf_file_t ef = (elf_file_t)lf;
1295 const Elf_Rel *rellim;
1296 const Elf_Rel *rel;
1297 const Elf_Rela *relalim;
1298 const Elf_Rela *rela;
1299 const Elf_Sym *sym;
1300 Elf_Addr base;
1301 int i;
1302 Elf_Size symidx;
1303
1304 link_elf_fix_link_set(ef);
1305
1306 /* Perform relocations without addend if there are any: */
1307 for (i = 0; i < ef->nreltab; i++) {
1308 rel = ef->reltab[i].rel;
1309 if (rel == NULL)
1310 panic("lost a reltab!");
1311 rellim = rel + ef->reltab[i].nrel;
1312 base = findbase(ef, ef->reltab[i].sec);
1313 if (base == 0)
1314 panic("lost base for reltab");
1315 for ( ; rel < rellim; rel++) {
1316 symidx = ELF_R_SYM(rel->r_info);
1317 if (symidx >= ef->ddbsymcnt)
1318 continue;
1319 sym = ef->ddbsymtab + symidx;
1320 /* Only do local relocs */
1321 if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
1322 continue;
1323 elf_reloc_local(lf, base, rel, ELF_RELOC_REL,
1324 elf_obj_lookup);
1325 }
1326 }
1327
1328 /* Perform relocations with addend if there are any: */
1329 for (i = 0; i < ef->nrelatab; i++) {
1330 rela = ef->relatab[i].rela;
1331 if (rela == NULL)
1332 panic("lost a relatab!");
1333 relalim = rela + ef->relatab[i].nrela;
1334 base = findbase(ef, ef->relatab[i].sec);
1335 if (base == 0)
1336 panic("lost base for relatab");
1337 for ( ; rela < relalim; rela++) {
1338 symidx = ELF_R_SYM(rela->r_info);
1339 if (symidx >= ef->ddbsymcnt)
1340 continue;
1341 sym = ef->ddbsymtab + symidx;
1342 /* Only do local relocs */
1343 if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
1344 continue;
1345 elf_reloc_local(lf, base, rela, ELF_RELOC_RELA,
1346 elf_obj_lookup);
1347 }
1348 }
1349}
1350
1351static long
1352link_elf_symtab_get(linker_file_t lf, const Elf_Sym **symtab)
1353{
1354 elf_file_t ef = (elf_file_t)lf;
1355
1356 *symtab = ef->ddbsymtab;
1357
1358 if (*symtab == NULL)
1359 return (0);
1360
1361 return (ef->ddbsymcnt);
1362}
1363
1364static long
1365link_elf_strtab_get(linker_file_t lf, caddr_t *strtab)
1366{
1367 elf_file_t ef = (elf_file_t)lf;
1368
1369 *strtab = ef->ddbstrtab;
1370
1371 if (*strtab == NULL)
1372 return (0);
1373
1374 return (ef->ddbstrcnt);
1375}