Deleted Added
full compact
link_elf_obj.c (55090) link_elf_obj.c (59603)
1/*-
1/*-
2 * Copyright (c) 1998 Doug Rabson
2 * Copyright (c) 1998-2000 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 7 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 7 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/kern/link_elf_obj.c 55090 1999-12-24 15:33:36Z bde $
26 * $FreeBSD: head/sys/kern/link_elf_obj.c 59603 2000-04-24 17:08:04Z dfr $
27 */
28
27 */
28
29#include "opt_ddb.h"
30
29#include <sys/param.h>
30#include <sys/kernel.h>
31#include <sys/systm.h>
32#include <sys/malloc.h>
33#include <sys/proc.h>
34#include <sys/namei.h>
35#include <sys/fcntl.h>
36#include <sys/vnode.h>

--- 6 unchanged lines hidden (view full) ---

43#include <sys/lock.h>
44#ifdef SPARSE_MAPPING
45#include <vm/vm_object.h>
46#include <vm/vm_kern.h>
47#include <vm/vm_extern.h>
48#endif
49#include <vm/pmap.h>
50#include <vm/vm_map.h>
31#include <sys/param.h>
32#include <sys/kernel.h>
33#include <sys/systm.h>
34#include <sys/malloc.h>
35#include <sys/proc.h>
36#include <sys/namei.h>
37#include <sys/fcntl.h>
38#include <sys/vnode.h>

--- 6 unchanged lines hidden (view full) ---

45#include <sys/lock.h>
46#ifdef SPARSE_MAPPING
47#include <vm/vm_object.h>
48#include <vm/vm_kern.h>
49#include <vm/vm_extern.h>
50#endif
51#include <vm/pmap.h>
52#include <vm/vm_map.h>
53#include <link.h>
51
54
52static int link_elf_load_module(const char*, linker_file_t*);
53static int link_elf_load_file(const char*, linker_file_t*);
54static int link_elf_lookup_symbol(linker_file_t, const char*,
55 c_linker_sym_t*);
56static int link_elf_symbol_values(linker_file_t, c_linker_sym_t, linker_symval_t*);
57static int link_elf_search_symbol(linker_file_t, caddr_t value,
58 c_linker_sym_t* sym, long* diffp);
55#include "linker_if.h"
59
56
60static void link_elf_unload_file(linker_file_t);
61static void link_elf_unload_module(linker_file_t);
62
63static struct linker_class_ops link_elf_class_ops = {
64 link_elf_load_module,
65};
66
67static struct linker_file_ops link_elf_file_ops = {
68 link_elf_lookup_symbol,
69 link_elf_symbol_values,
70 link_elf_search_symbol,
71 link_elf_unload_file,
72};
73
74static struct linker_file_ops link_elf_module_ops = {
75 link_elf_lookup_symbol,
76 link_elf_symbol_values,
77 link_elf_search_symbol,
78 link_elf_unload_module,
79};
80typedef struct elf_file {
57typedef struct elf_file {
58 struct linker_file lf; /* Common fields */
59 int preloaded; /* Was file pre-loaded */
81 caddr_t address; /* Relocation address */
82#ifdef SPARSE_MAPPING
83 vm_object_t object; /* VM object to hold file pages */
84#endif
60 caddr_t address; /* Relocation address */
61#ifdef SPARSE_MAPPING
62 vm_object_t object; /* VM object to hold file pages */
63#endif
85 const Elf_Dyn* dynamic; /* Symbol table etc. */
64 Elf_Dyn* dynamic; /* Symbol table etc. */
86 Elf_Off nbuckets; /* DT_HASH info */
87 Elf_Off nchains;
88 const Elf_Off* buckets;
89 const Elf_Off* chains;
90 caddr_t hash;
91 caddr_t strtab; /* DT_STRTAB */
92 int strsz; /* DT_STRSZ */
93 const Elf_Sym* symtab; /* DT_SYMTAB */

--- 8 unchanged lines hidden (view full) ---

102 int relasize; /* DT_RELASZ */
103 caddr_t modptr;
104 const Elf_Sym* ddbsymtab; /* The symbol table we are using */
105 long ddbsymcnt; /* Number of symbols */
106 caddr_t ddbstrtab; /* String table */
107 long ddbstrcnt; /* number of bytes in string table */
108 caddr_t symbase; /* malloc'ed symbold base */
109 caddr_t strbase; /* malloc'ed string base */
65 Elf_Off nbuckets; /* DT_HASH info */
66 Elf_Off nchains;
67 const Elf_Off* buckets;
68 const Elf_Off* chains;
69 caddr_t hash;
70 caddr_t strtab; /* DT_STRTAB */
71 int strsz; /* DT_STRSZ */
72 const Elf_Sym* symtab; /* DT_SYMTAB */

--- 8 unchanged lines hidden (view full) ---

81 int relasize; /* DT_RELASZ */
82 caddr_t modptr;
83 const Elf_Sym* ddbsymtab; /* The symbol table we are using */
84 long ddbsymcnt; /* Number of symbols */
85 caddr_t ddbstrtab; /* String table */
86 long ddbstrcnt; /* number of bytes in string table */
87 caddr_t symbase; /* malloc'ed symbold base */
88 caddr_t strbase; /* malloc'ed string base */
89#ifdef DDB
90 struct link_map gdb; /* hooks for gdb */
91#endif
110} *elf_file_t;
111
92} *elf_file_t;
93
112static int parse_dynamic(linker_file_t lf);
113static int load_dependancies(linker_file_t lf);
114static int relocate_file(linker_file_t lf);
115static int parse_module_symbols(linker_file_t lf);
94static int link_elf_load_module(linker_class_t cls,
95 const char*, linker_file_t*);
96static int link_elf_load_file(const char*, linker_file_t*);
97static int link_elf_lookup_symbol(linker_file_t, const char*,
98 c_linker_sym_t*);
99static int link_elf_symbol_values(linker_file_t, c_linker_sym_t, linker_symval_t*);
100static int link_elf_search_symbol(linker_file_t, caddr_t value,
101 c_linker_sym_t* sym, long* diffp);
116
102
103static void link_elf_unload_file(linker_file_t);
104static void link_elf_unload_module(linker_file_t);
105
106static kobj_method_t link_elf_methods[] = {
107 KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol),
108 KOBJMETHOD(linker_symbol_values, link_elf_symbol_values),
109 KOBJMETHOD(linker_search_symbol, link_elf_search_symbol),
110 KOBJMETHOD(linker_unload, link_elf_unload_file),
111 KOBJMETHOD(linker_load_file, link_elf_load_module),
112 { 0, 0 }
113};
114
115static struct linker_class link_elf_class = {
116#if ELF_TARG_CLASS == ELFCLASS32
117 "elf32",
118#else
119 "elf64",
120#endif
121 link_elf_methods, sizeof(struct elf_file)
122};
123
124static int parse_dynamic(elf_file_t ef);
125static int load_dependancies(elf_file_t ef);
126static int relocate_file(elf_file_t ef);
127static int parse_module_symbols(elf_file_t ef);
128
129#ifdef DDB
130
117/*
131/*
132 * A list of loaded modules for GDB to use for loading symbols.
133 */
134struct r_debug r_debug;
135
136#define GDB_STATE(s) r_debug.r_state = s; r_debug_state();
137
138/*
139 * Function for the debugger to set a breakpoint on to gain control.
140 */
141void
142r_debug_state(void)
143{
144}
145
146#endif
147
148/*
118 * The kernel symbol table starts here.
119 */
120extern struct _dynamic _DYNAMIC;
121
122static void
123link_elf_init(void* arg)
124{
125#ifdef __ELF__
126 Elf_Dyn *dp;
127 caddr_t modptr, baseptr, sizeptr;
128 elf_file_t ef;
129 char *modname;
130#endif
131
149 * The kernel symbol table starts here.
150 */
151extern struct _dynamic _DYNAMIC;
152
153static void
154link_elf_init(void* arg)
155{
156#ifdef __ELF__
157 Elf_Dyn *dp;
158 caddr_t modptr, baseptr, sizeptr;
159 elf_file_t ef;
160 char *modname;
161#endif
162
132#if ELF_TARG_CLASS == ELFCLASS32
133 linker_add_class("elf32", NULL, &link_elf_class_ops);
134#else
135 linker_add_class("elf64", NULL, &link_elf_class_ops);
136#endif
163 linker_add_class(&link_elf_class);
137
138#ifdef __ELF__
139 dp = (Elf_Dyn*) &_DYNAMIC;
140 if (dp) {
164
165#ifdef __ELF__
166 dp = (Elf_Dyn*) &_DYNAMIC;
167 if (dp) {
141 ef = malloc(sizeof(struct elf_file), M_LINKER, M_NOWAIT);
142 if (ef == NULL)
143 panic("link_elf_init: Can't create linker structures for kernel");
144 bzero(ef, sizeof(*ef));
145
146 ef->address = 0;
147#ifdef SPARSE_MAPPING
148 ef->object = 0;
149#endif
150 ef->dynamic = dp;
151 modname = NULL;
152 modptr = preload_search_by_type("elf kernel");
153 if (modptr)
154 modname = (char *)preload_search_info(modptr, MODINFO_NAME);
155 if (modname == NULL)
156 modname = "kernel";
168 modname = NULL;
169 modptr = preload_search_by_type("elf kernel");
170 if (modptr)
171 modname = (char *)preload_search_info(modptr, MODINFO_NAME);
172 if (modname == NULL)
173 modname = "kernel";
157 linker_kernel_file = linker_make_file(modname, ef, &link_elf_file_ops);
174 linker_kernel_file = linker_make_file(modname, &link_elf_class);
158 if (linker_kernel_file == NULL)
159 panic("link_elf_init: Can't create linker structures for kernel");
175 if (linker_kernel_file == NULL)
176 panic("link_elf_init: Can't create linker structures for kernel");
160 parse_dynamic(linker_kernel_file);
177
178 ef = (elf_file_t) linker_kernel_file;
179 ef->address = 0;
180#ifdef SPARSE_MAPPING
181 ef->object = 0;
182#endif
183 ef->dynamic = dp;
184
185 parse_dynamic(ef);
161 linker_kernel_file->address = (caddr_t) KERNBASE;
162 linker_kernel_file->size = -(intptr_t)linker_kernel_file->address;
163
164 if (modptr) {
165 ef->modptr = modptr;
166 baseptr = preload_search_info(modptr, MODINFO_ADDR);
167 if (baseptr)
168 linker_kernel_file->address = *(caddr_t *)baseptr;
169 sizeptr = preload_search_info(modptr, MODINFO_SIZE);
170 if (sizeptr)
171 linker_kernel_file->size = *(size_t *)sizeptr;
172 }
186 linker_kernel_file->address = (caddr_t) KERNBASE;
187 linker_kernel_file->size = -(intptr_t)linker_kernel_file->address;
188
189 if (modptr) {
190 ef->modptr = modptr;
191 baseptr = preload_search_info(modptr, MODINFO_ADDR);
192 if (baseptr)
193 linker_kernel_file->address = *(caddr_t *)baseptr;
194 sizeptr = preload_search_info(modptr, MODINFO_SIZE);
195 if (sizeptr)
196 linker_kernel_file->size = *(size_t *)sizeptr;
197 }
173 (void)parse_module_symbols(linker_kernel_file);
198 (void)parse_module_symbols(ef);
174 linker_current_file = linker_kernel_file;
175 linker_kernel_file->flags |= LINKER_FILE_LINKED;
199 linker_current_file = linker_kernel_file;
200 linker_kernel_file->flags |= LINKER_FILE_LINKED;
201
202#ifdef DDB
203 ef->gdb.l_addr = linker_kernel_file->address;
204 ef->gdb.l_name = modname;
205 ef->gdb.l_ld = dp;
206 ef->gdb.l_prev = 0;
207 ef->gdb.l_next = 0;
208
209 r_debug.r_map = &ef->gdb;
210 r_debug.r_brk = r_debug_state;
211 r_debug.r_state = RT_CONSISTENT;
212
213 r_debug_state(); /* say hello to gdb! */
214#endif
215
176 }
177#endif
178}
179
180SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0);
181
182static int
216 }
217#endif
218}
219
220SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0);
221
222static int
183parse_module_symbols(linker_file_t lf)
223parse_module_symbols(elf_file_t ef)
184{
224{
185 elf_file_t ef = lf->priv;
186 caddr_t pointer;
187 caddr_t ssym, esym, base;
188 caddr_t strtab;
189 int strcnt;
190 Elf_Sym* symtab;
191 int symcnt;
192
193 if (ef->modptr == NULL)

--- 33 unchanged lines hidden (view full) ---

227 ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
228 ef->ddbstrtab = strtab;
229 ef->ddbstrcnt = strcnt;
230
231 return 0;
232}
233
234static int
225 caddr_t pointer;
226 caddr_t ssym, esym, base;
227 caddr_t strtab;
228 int strcnt;
229 Elf_Sym* symtab;
230 int symcnt;
231
232 if (ef->modptr == NULL)

--- 33 unchanged lines hidden (view full) ---

266 ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
267 ef->ddbstrtab = strtab;
268 ef->ddbstrcnt = strcnt;
269
270 return 0;
271}
272
273static int
235parse_dynamic(linker_file_t lf)
274parse_dynamic(elf_file_t ef)
236{
275{
237 elf_file_t ef = lf->priv;
238 const Elf_Dyn *dp;
276 Elf_Dyn *dp;
239 int plttype = DT_REL;
240
241 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
242 switch (dp->d_tag) {
243 case DT_HASH:
244 {
245 /* From src/libexec/rtld-elf/rtld.c */
246 const Elf_Off *hashtab = (const Elf_Off *)

--- 46 unchanged lines hidden (view full) ---

293 if (dp->d_un.d_val != sizeof(Elf_Rela))
294 return ENOEXEC;
295 break;
296 case DT_PLTREL:
297 plttype = dp->d_un.d_val;
298 if (plttype != DT_REL && plttype != DT_RELA)
299 return ENOEXEC;
300 break;
277 int plttype = DT_REL;
278
279 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
280 switch (dp->d_tag) {
281 case DT_HASH:
282 {
283 /* From src/libexec/rtld-elf/rtld.c */
284 const Elf_Off *hashtab = (const Elf_Off *)

--- 46 unchanged lines hidden (view full) ---

331 if (dp->d_un.d_val != sizeof(Elf_Rela))
332 return ENOEXEC;
333 break;
334 case DT_PLTREL:
335 plttype = dp->d_un.d_val;
336 if (plttype != DT_REL && plttype != DT_RELA)
337 return ENOEXEC;
338 break;
339#ifdef DDB
340 case DT_DEBUG:
341 dp->d_un.d_ptr = (Elf_Addr) &r_debug;
342 break;
343#endif
301 }
302 }
303
304 if (plttype == DT_RELA) {
305 ef->pltrela = (const Elf_Rela *) ef->pltrel;
306 ef->pltrel = NULL;
307 ef->pltrelasize = ef->pltrelsize;
308 ef->pltrelsize = 0;

--- 8 unchanged lines hidden (view full) ---

317}
318
319static void
320link_elf_error(const char *s)
321{
322 printf("kldload: %s\n", s);
323}
324
344 }
345 }
346
347 if (plttype == DT_RELA) {
348 ef->pltrela = (const Elf_Rela *) ef->pltrel;
349 ef->pltrel = NULL;
350 ef->pltrelasize = ef->pltrelsize;
351 ef->pltrelsize = 0;

--- 8 unchanged lines hidden (view full) ---

360}
361
362static void
363link_elf_error(const char *s)
364{
365 printf("kldload: %s\n", s);
366}
367
368#ifdef DDB
369
370static void
371link_elf_add_gdb(struct link_map *l)
372{
373 struct link_map *prev;
374
375 /*
376 * Scan to the end of the list.
377 */
378 for (prev = r_debug.r_map; prev->l_next != NULL; prev = prev->l_next)
379 ;
380
381 /* Link in the new entry. */
382 l->l_prev = prev;
383 l->l_next = prev->l_next;
384 prev->l_next = l;
385}
386
387static void
388link_elf_delete_gdb(struct link_map *l)
389{
390 if (l->l_prev == NULL) {
391 if ((r_debug.r_map = l->l_next) != NULL)
392 l->l_next->l_prev = NULL;
393 return;
394 }
395
396 if ((l->l_prev->l_next = l->l_next) != NULL)
397 l->l_next->l_prev = l->l_prev;
398}
399
400#endif /* DDB */
401
325static int
402static int
326link_elf_load_module(const char *filename, linker_file_t *result)
403link_elf_load_module(linker_class_t cls,
404 const char *filename, linker_file_t *result)
327{
328 caddr_t modptr, baseptr, sizeptr, dynptr;
329 char *type;
330 elf_file_t ef;
331 linker_file_t lf;
332 int error;
333 vm_offset_t dp;
334

--- 7 unchanged lines hidden (view full) ---

342 baseptr = preload_search_info(modptr, MODINFO_ADDR);
343 sizeptr = preload_search_info(modptr, MODINFO_SIZE);
344 dynptr = preload_search_info(modptr, MODINFO_METADATA|MODINFOMD_DYNAMIC);
345 if (type == NULL || strcmp(type, "elf module") != 0)
346 return (EFTYPE);
347 if (baseptr == NULL || sizeptr == NULL || dynptr == NULL)
348 return (EINVAL);
349
405{
406 caddr_t modptr, baseptr, sizeptr, dynptr;
407 char *type;
408 elf_file_t ef;
409 linker_file_t lf;
410 int error;
411 vm_offset_t dp;
412

--- 7 unchanged lines hidden (view full) ---

420 baseptr = preload_search_info(modptr, MODINFO_ADDR);
421 sizeptr = preload_search_info(modptr, MODINFO_SIZE);
422 dynptr = preload_search_info(modptr, MODINFO_METADATA|MODINFOMD_DYNAMIC);
423 if (type == NULL || strcmp(type, "elf module") != 0)
424 return (EFTYPE);
425 if (baseptr == NULL || sizeptr == NULL || dynptr == NULL)
426 return (EINVAL);
427
350 ef = malloc(sizeof(struct elf_file), M_LINKER, M_WAITOK);
351 if (ef == NULL)
352 return (ENOMEM);
353 bzero(ef, sizeof(*ef));
428 lf = linker_make_file(filename, &link_elf_class);
429 if (lf == NULL) {
430 return ENOMEM;
431 }
432
433 ef = (elf_file_t) lf;
434 ef->preloaded = 1;
354 ef->modptr = modptr;
355 ef->address = *(caddr_t *)baseptr;
356#ifdef SPARSE_MAPPING
357 ef->object = 0;
358#endif
359 dp = (vm_offset_t)ef->address + *(vm_offset_t *)dynptr;
360 ef->dynamic = (Elf_Dyn *)dp;
435 ef->modptr = modptr;
436 ef->address = *(caddr_t *)baseptr;
437#ifdef SPARSE_MAPPING
438 ef->object = 0;
439#endif
440 dp = (vm_offset_t)ef->address + *(vm_offset_t *)dynptr;
441 ef->dynamic = (Elf_Dyn *)dp;
361 lf = linker_make_file(filename, ef, &link_elf_module_ops);
362 if (lf == NULL) {
363 free(ef, M_LINKER);
364 return ENOMEM;
365 }
442
366 lf->address = ef->address;
367 lf->size = *(size_t *)sizeptr;
368
443 lf->address = ef->address;
444 lf->size = *(size_t *)sizeptr;
445
369 error = parse_dynamic(lf);
446 error = parse_dynamic(ef);
370 if (error) {
371 linker_file_unload(lf);
372 return error;
373 }
447 if (error) {
448 linker_file_unload(lf);
449 return error;
450 }
374 error = load_dependancies(lf);
451 error = load_dependancies(ef);
375 if (error) {
376 linker_file_unload(lf);
377 return error;
378 }
452 if (error) {
453 linker_file_unload(lf);
454 return error;
455 }
379 error = relocate_file(lf);
456 error = relocate_file(ef);
380 if (error) {
381 linker_file_unload(lf);
382 return error;
383 }
457 if (error) {
458 linker_file_unload(lf);
459 return error;
460 }
384 (void)parse_module_symbols(lf);
461 (void)parse_module_symbols(ef);
385 lf->flags |= LINKER_FILE_LINKED;
462 lf->flags |= LINKER_FILE_LINKED;
463
464#ifdef DDB
465 GDB_STATE(RT_ADD);
466 ef->gdb.l_addr = lf->address;
467 ef->gdb.l_name = filename;
468 ef->gdb.l_ld = ef->dynamic;
469 link_elf_add_gdb(&ef->gdb);
470 GDB_STATE(RT_CONSISTENT);
471#endif
472
386 *result = lf;
387 return (0);
388}
389
390static int
391link_elf_load_file(const char* filename, linker_file_t* result)
392{
393 struct nameidata nd;

--- 135 unchanged lines hidden (view full) ---

529 * Allocate the entire address space of the object, to stake out our
530 * contiguous region, and to establish the base address for relocation.
531 */
532 base_offset = trunc_page(segs[0]->p_offset);
533 base_vaddr = trunc_page(segs[0]->p_vaddr);
534 base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz);
535 mapsize = base_vlimit - base_vaddr;
536
473 *result = lf;
474 return (0);
475}
476
477static int
478link_elf_load_file(const char* filename, linker_file_t* result)
479{
480 struct nameidata nd;

--- 135 unchanged lines hidden (view full) ---

616 * Allocate the entire address space of the object, to stake out our
617 * contiguous region, and to establish the base address for relocation.
618 */
619 base_offset = trunc_page(segs[0]->p_offset);
620 base_vaddr = trunc_page(segs[0]->p_vaddr);
621 base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz);
622 mapsize = base_vlimit - base_vaddr;
623
537 ef = malloc(sizeof(struct elf_file), M_LINKER, M_WAITOK);
538 bzero(ef, sizeof(*ef));
624 lf = linker_make_file(filename, &link_elf_class);
625 if (!lf) {
626 error = ENOMEM;
627 goto out;
628 }
629
630 ef = (elf_file_t) lf;
539#ifdef SPARSE_MAPPING
540 ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT);
541 if (ef->object == NULL) {
542 free(ef, M_LINKER);
543 error = ENOMEM;
544 goto out;
545 }
546 vm_object_reference(ef->object);
547 ef->address = (caddr_t) vm_map_min(kernel_map);
548 error = vm_map_find(kernel_map, ef->object, 0,
549 (vm_offset_t *) &ef->address,
550 mapsize, 1,
551 VM_PROT_ALL, VM_PROT_ALL, 0);
552 if (error) {
553 vm_object_deallocate(ef->object);
631#ifdef SPARSE_MAPPING
632 ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT);
633 if (ef->object == NULL) {
634 free(ef, M_LINKER);
635 error = ENOMEM;
636 goto out;
637 }
638 vm_object_reference(ef->object);
639 ef->address = (caddr_t) vm_map_min(kernel_map);
640 error = vm_map_find(kernel_map, ef->object, 0,
641 (vm_offset_t *) &ef->address,
642 mapsize, 1,
643 VM_PROT_ALL, VM_PROT_ALL, 0);
644 if (error) {
645 vm_object_deallocate(ef->object);
554 free(ef, M_LINKER);
646 ef->object = 0;
555 goto out;
556 }
557#else
558 ef->address = malloc(mapsize, M_LINKER, M_WAITOK);
647 goto out;
648 }
649#else
650 ef->address = malloc(mapsize, M_LINKER, M_WAITOK);
651 if (!ef->address) {
652 error = ENOMEM;
653 goto out;
654 }
559#endif
560 mapbase = ef->address;
561
562 /*
563 * Read the text and data sections and zero the bss.
564 */
565 for (i = 0; i < 2; i++) {
566 caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr;
567 error = vn_rdwr(UIO_READ, nd.ni_vp,
568 segbase, segs[i]->p_filesz, segs[i]->p_offset,
569 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
570 if (error) {
655#endif
656 mapbase = ef->address;
657
658 /*
659 * Read the text and data sections and zero the bss.
660 */
661 for (i = 0; i < 2; i++) {
662 caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr;
663 error = vn_rdwr(UIO_READ, nd.ni_vp,
664 segbase, segs[i]->p_filesz, segs[i]->p_offset,
665 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
666 if (error) {
571#ifdef SPARSE_MAPPING
572 vm_map_remove(kernel_map, (vm_offset_t) ef->address,
573 (vm_offset_t) ef->address
574 + (ef->object->size << PAGE_SHIFT));
575 vm_object_deallocate(ef->object);
576#else
577 free(ef->address, M_LINKER);
578#endif
579 free(ef, M_LINKER);
580 goto out;
581 }
582 bzero(segbase + segs[i]->p_filesz,
583 segs[i]->p_memsz - segs[i]->p_filesz);
584
585#ifdef SPARSE_MAPPING
586 /*
587 * Wire down the pages
588 */
589 vm_map_pageable(kernel_map,
590 (vm_offset_t) segbase,
591 (vm_offset_t) segbase + segs[i]->p_memsz,
592 FALSE);
593#endif
594 }
595
667 goto out;
668 }
669 bzero(segbase + segs[i]->p_filesz,
670 segs[i]->p_memsz - segs[i]->p_filesz);
671
672#ifdef SPARSE_MAPPING
673 /*
674 * Wire down the pages
675 */
676 vm_map_pageable(kernel_map,
677 (vm_offset_t) segbase,
678 (vm_offset_t) segbase + segs[i]->p_memsz,
679 FALSE);
680#endif
681 }
682
596 ef->dynamic = (const Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr);
683 ef->dynamic = (Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr);
597
684
598 lf = linker_make_file(filename, ef, &link_elf_file_ops);
599 if (lf == NULL) {
600#ifdef SPARSE_MAPPING
601 vm_map_remove(kernel_map, (vm_offset_t) ef->address,
602 (vm_offset_t) ef->address
603 + (ef->object->size << PAGE_SHIFT));
604 vm_object_deallocate(ef->object);
605#else
606 free(ef->address, M_LINKER);
607#endif
608 free(ef, M_LINKER);
609 error = ENOMEM;
610 goto out;
611 }
612 lf->address = ef->address;
613 lf->size = mapsize;
614
685 lf->address = ef->address;
686 lf->size = mapsize;
687
615 error = parse_dynamic(lf);
688 error = parse_dynamic(ef);
616 if (error)
617 goto out;
689 if (error)
690 goto out;
618 error = load_dependancies(lf);
691 error = load_dependancies(ef);
619 if (error)
620 goto out;
692 if (error)
693 goto out;
621 error = relocate_file(lf);
694 error = relocate_file(ef);
622 if (error)
623 goto out;
624
625 /* Try and load the symbol table if it's present. (you can strip it!) */
626 nbytes = hdr->e_shnum * hdr->e_shentsize;
627 if (nbytes == 0 || hdr->e_shoff == 0)
628 goto nosyms;
629 shdr = malloc(nbytes, M_LINKER, M_WAITOK);

--- 40 unchanged lines hidden (view full) ---

670
671 ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
672 ef->ddbsymtab = (const Elf_Sym *)ef->symbase;
673 ef->ddbstrcnt = strcnt;
674 ef->ddbstrtab = ef->strbase;
675
676 lf->flags |= LINKER_FILE_LINKED;
677
695 if (error)
696 goto out;
697
698 /* Try and load the symbol table if it's present. (you can strip it!) */
699 nbytes = hdr->e_shnum * hdr->e_shentsize;
700 if (nbytes == 0 || hdr->e_shoff == 0)
701 goto nosyms;
702 shdr = malloc(nbytes, M_LINKER, M_WAITOK);

--- 40 unchanged lines hidden (view full) ---

743
744 ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
745 ef->ddbsymtab = (const Elf_Sym *)ef->symbase;
746 ef->ddbstrcnt = strcnt;
747 ef->ddbstrtab = ef->strbase;
748
749 lf->flags |= LINKER_FILE_LINKED;
750
751#ifdef DDB
752 GDB_STATE(RT_ADD);
753 ef->gdb.l_addr = lf->address;
754 ef->gdb.l_name = linker_search_path(filename);
755 ef->gdb.l_ld = ef->dynamic;
756 link_elf_add_gdb(&ef->gdb);
757 GDB_STATE(RT_CONSISTENT);
758#endif
759
678nosyms:
679
680 *result = lf;
681
682out:
683 if (error && lf)
684 linker_file_unload(lf);
685 if (shdr)

--- 4 unchanged lines hidden (view full) ---

690 vn_close(nd.ni_vp, FREAD, p->p_ucred, p);
691
692 return error;
693}
694
695static void
696link_elf_unload_file(linker_file_t file)
697{
760nosyms:
761
762 *result = lf;
763
764out:
765 if (error && lf)
766 linker_file_unload(lf);
767 if (shdr)

--- 4 unchanged lines hidden (view full) ---

772 vn_close(nd.ni_vp, FREAD, p->p_ucred, p);
773
774 return error;
775}
776
777static void
778link_elf_unload_file(linker_file_t file)
779{
698 elf_file_t ef = file->priv;
780 elf_file_t ef = (elf_file_t) file;
699
781
700 if (ef) {
782#ifdef DDB
783 if (ef->gdb.l_ld) {
784 GDB_STATE(RT_DELETE);
785 link_elf_delete_gdb(&ef->gdb);
786 GDB_STATE(RT_CONSISTENT);
787 /* The strange cast is to quieten a 'discarding const' warning. */
788 free((caddr_t) (uintptr_t) ef->gdb.l_name, M_LINKER);
789 }
790#endif
791
792 if (ef->preloaded) {
793 link_elf_unload_module(file);
794 return;
795 }
701#ifdef SPARSE_MAPPING
796#ifdef SPARSE_MAPPING
702 if (ef->object) {
703 vm_map_remove(kernel_map, (vm_offset_t) ef->address,
704 (vm_offset_t) ef->address
705 + (ef->object->size << PAGE_SHIFT));
706 vm_object_deallocate(ef->object);
707 }
797 if (ef->object) {
798 vm_map_remove(kernel_map, (vm_offset_t) ef->address,
799 (vm_offset_t) ef->address
800 + (ef->object->size << PAGE_SHIFT));
801 vm_object_deallocate(ef->object);
802 }
708#else
803#else
709 if (ef->address)
710 free(ef->address, M_LINKER);
804 if (ef->address)
805 free(ef->address, M_LINKER);
711#endif
806#endif
712 if (ef->symbase)
713 free(ef->symbase, M_LINKER);
714 if (ef->strbase)
715 free(ef->strbase, M_LINKER);
716 free(ef, M_LINKER);
717 }
807 if (ef->symbase)
808 free(ef->symbase, M_LINKER);
809 if (ef->strbase)
810 free(ef->strbase, M_LINKER);
718}
719
720static void
721link_elf_unload_module(linker_file_t file)
722{
811}
812
813static void
814link_elf_unload_module(linker_file_t file)
815{
723 elf_file_t ef = file->priv;
724
725 if (ef)
726 free(ef, M_LINKER);
727 if (file->filename)
728 preload_delete_name(file->filename);
729}
730
731static int
816 if (file->filename)
817 preload_delete_name(file->filename);
818}
819
820static int
732load_dependancies(linker_file_t lf)
821load_dependancies(elf_file_t ef)
733{
822{
734 elf_file_t ef = lf->priv;
735 linker_file_t lfdep;
736 char* name;
737 const Elf_Dyn *dp;
738 int error = 0;
739
740 /*
741 * All files are dependant on /kernel.
742 */
743 if (linker_kernel_file) {
744 linker_kernel_file->refs++;
823 linker_file_t lfdep;
824 char* name;
825 const Elf_Dyn *dp;
826 int error = 0;
827
828 /*
829 * All files are dependant on /kernel.
830 */
831 if (linker_kernel_file) {
832 linker_kernel_file->refs++;
745 linker_file_add_dependancy(lf, linker_kernel_file);
833 linker_file_add_dependancy(&ef->lf, linker_kernel_file);
746 }
747
748 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
749 if (dp->d_tag == DT_NEEDED) {
750 name = ef->strtab + dp->d_un.d_val;
751
752 error = linker_load_file(name, &lfdep);
753 if (error)
754 goto out;
834 }
835
836 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
837 if (dp->d_tag == DT_NEEDED) {
838 name = ef->strtab + dp->d_un.d_val;
839
840 error = linker_load_file(name, &lfdep);
841 if (error)
842 goto out;
755 error = linker_file_add_dependancy(lf, lfdep);
843 error = linker_file_add_dependancy(&ef->lf, lfdep);
756 if (error)
757 goto out;
758 }
759 }
760
761out:
762 return error;
763}

--- 6 unchanged lines hidden (view full) ---

770 if (ELF_R_SYM(r_info)) {
771 ref = ef->symtab + ELF_R_SYM(r_info);
772 return ef->strtab + ref->st_name;
773 } else
774 return NULL;
775}
776
777static int
844 if (error)
845 goto out;
846 }
847 }
848
849out:
850 return error;
851}

--- 6 unchanged lines hidden (view full) ---

858 if (ELF_R_SYM(r_info)) {
859 ref = ef->symtab + ELF_R_SYM(r_info);
860 return ef->strtab + ref->st_name;
861 } else
862 return NULL;
863}
864
865static int
778relocate_file(linker_file_t lf)
866relocate_file(elf_file_t ef)
779{
867{
780 elf_file_t ef = lf->priv;
781 const Elf_Rel *rellim;
782 const Elf_Rel *rel;
783 const Elf_Rela *relalim;
784 const Elf_Rela *rela;
785 const char *symname;
786
787 /* Perform relocations without addend if there are any: */
788 rel = ef->rel;
789 if (rel) {
790 rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize);
791 while (rel < rellim) {
792 symname = symbol_name(ef, rel->r_info);
868 const Elf_Rel *rellim;
869 const Elf_Rel *rel;
870 const Elf_Rela *relalim;
871 const Elf_Rela *rela;
872 const char *symname;
873
874 /* Perform relocations without addend if there are any: */
875 rel = ef->rel;
876 if (rel) {
877 rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize);
878 while (rel < rellim) {
879 symname = symbol_name(ef, rel->r_info);
793 if (elf_reloc(lf, rel, ELF_RELOC_REL, symname)) {
794 printf("link_elf: symbol %s undefined\n", symname);
880 if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL, symname)) {
881 uprintf("link_elf: symbol %s undefined\n", symname);
795 return ENOENT;
796 }
797 rel++;
798 }
799 }
800
801 /* Perform relocations with addend if there are any: */
802 rela = ef->rela;
803 if (rela) {
804 relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize);
805 while (rela < relalim) {
806 symname = symbol_name(ef, rela->r_info);
882 return ENOENT;
883 }
884 rel++;
885 }
886 }
887
888 /* Perform relocations with addend if there are any: */
889 rela = ef->rela;
890 if (rela) {
891 relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize);
892 while (rela < relalim) {
893 symname = symbol_name(ef, rela->r_info);
807 if (elf_reloc(lf, rela, ELF_RELOC_RELA, symname)) {
808 printf("link_elf: symbol %s undefined\n", symname);
894 if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA, symname)) {
895 uprintf("link_elf: symbol %s undefined\n", symname);
809 return ENOENT;
810 }
811 rela++;
812 }
813 }
814
815 /* Perform PLT relocations without addend if there are any: */
816 rel = ef->pltrel;
817 if (rel) {
818 rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize);
819 while (rel < rellim) {
820 symname = symbol_name(ef, rel->r_info);
896 return ENOENT;
897 }
898 rela++;
899 }
900 }
901
902 /* Perform PLT relocations without addend if there are any: */
903 rel = ef->pltrel;
904 if (rel) {
905 rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize);
906 while (rel < rellim) {
907 symname = symbol_name(ef, rel->r_info);
821 if (elf_reloc(lf, rel, ELF_RELOC_REL, symname)) {
822 printf("link_elf: symbol %s undefined\n", symname);
908 if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL, symname)) {
909 uprintf("link_elf: symbol %s undefined\n", symname);
823 return ENOENT;
824 }
825 rel++;
826 }
827 }
828
829 /* Perform relocations with addend if there are any: */
830 rela = ef->pltrela;
831 if (rela) {
832 relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize);
833 while (rela < relalim) {
834 symname = symbol_name(ef, rela->r_info);
910 return ENOENT;
911 }
912 rel++;
913 }
914 }
915
916 /* Perform relocations with addend if there are any: */
917 rela = ef->pltrela;
918 if (rela) {
919 relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize);
920 while (rela < relalim) {
921 symname = symbol_name(ef, rela->r_info);
835 if (elf_reloc(lf, rela, ELF_RELOC_RELA, symname)) {
836 printf("link_elf: symbol %s undefined\n", symname);
922 if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA, symname)) {
923 uprintf("link_elf: symbol %s undefined\n", symname);
837 return ENOENT;
838 }
839 rela++;
840 }
841 }
842
843 return 0;
844}

--- 16 unchanged lines hidden (view full) ---

861 h &= ~g;
862 }
863 return h;
864}
865
866int
867link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t* sym)
868{
924 return ENOENT;
925 }
926 rela++;
927 }
928 }
929
930 return 0;
931}

--- 16 unchanged lines hidden (view full) ---

948 h &= ~g;
949 }
950 return h;
951}
952
953int
954link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t* sym)
955{
869 elf_file_t ef = lf->priv;
956 elf_file_t ef = (elf_file_t) lf;
870 unsigned long symnum;
871 const Elf_Sym* symp;
872 const char *strp;
873 unsigned long hash;
874 int i;
875
876 /* First, search hashed global symbols */
877 hash = elf_hash(name);

--- 45 unchanged lines hidden (view full) ---

923 }
924
925 return ENOENT;
926}
927
928static int
929link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, linker_symval_t* symval)
930{
957 unsigned long symnum;
958 const Elf_Sym* symp;
959 const char *strp;
960 unsigned long hash;
961 int i;
962
963 /* First, search hashed global symbols */
964 hash = elf_hash(name);

--- 45 unchanged lines hidden (view full) ---

1010 }
1011
1012 return ENOENT;
1013}
1014
1015static int
1016link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, linker_symval_t* symval)
1017{
931 elf_file_t ef = lf->priv;
1018 elf_file_t ef = (elf_file_t) lf;
932 const Elf_Sym* es = (const Elf_Sym*) sym;
933
934 if (es >= ef->symtab && ((es - ef->symtab) < ef->nchains)) {
935 symval->name = ef->strtab + es->st_name;
936 symval->value = (caddr_t) ef->address + es->st_value;
937 symval->size = es->st_size;
938 return 0;
939 }

--- 7 unchanged lines hidden (view full) ---

947 }
948 return ENOENT;
949}
950
951static int
952link_elf_search_symbol(linker_file_t lf, caddr_t value,
953 c_linker_sym_t* sym, long* diffp)
954{
1019 const Elf_Sym* es = (const Elf_Sym*) sym;
1020
1021 if (es >= ef->symtab && ((es - ef->symtab) < ef->nchains)) {
1022 symval->name = ef->strtab + es->st_name;
1023 symval->value = (caddr_t) ef->address + es->st_value;
1024 symval->size = es->st_size;
1025 return 0;
1026 }

--- 7 unchanged lines hidden (view full) ---

1034 }
1035 return ENOENT;
1036}
1037
1038static int
1039link_elf_search_symbol(linker_file_t lf, caddr_t value,
1040 c_linker_sym_t* sym, long* diffp)
1041{
955 elf_file_t ef = lf->priv;
1042 elf_file_t ef = (elf_file_t) lf;
956 u_long off = (uintptr_t) (void *) value;
957 u_long diff = off;
958 u_long st_value;
959 const Elf_Sym* es;
960 const Elf_Sym* best = 0;
961 int i;
962
963 for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) {

--- 22 unchanged lines hidden ---
1043 u_long off = (uintptr_t) (void *) value;
1044 u_long diff = off;
1045 u_long st_value;
1046 const Elf_Sym* es;
1047 const Elf_Sym* best = 0;
1048 int i;
1049
1050 for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) {

--- 22 unchanged lines hidden ---