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 --- |