35#include <sys/malloc.h> 36#include <sys/mutex.h> 37#include <sys/proc.h> 38#include <sys/namei.h> 39#include <sys/fcntl.h> 40#include <sys/vnode.h> 41#include <sys/linker.h> 42 43#include <machine/elf.h> 44#ifdef GPROF 45#include <machine/profile.h> 46#endif 47 48#include <vm/vm.h> 49#include <vm/vm_param.h> 50#ifdef SPARSE_MAPPING 51#include <vm/vm_object.h> 52#include <vm/vm_kern.h> 53#include <vm/vm_extern.h> 54#endif 55#include <vm/pmap.h> 56#include <vm/vm_map.h> 57 58#include <sys/link_elf.h> 59 60#include "linker_if.h" 61 62typedef struct elf_file { 63 struct linker_file lf; /* Common fields */ 64 int preloaded; /* Was file pre-loaded */ 65 caddr_t address; /* Relocation address */ 66#ifdef SPARSE_MAPPING 67 vm_object_t object; /* VM object to hold file pages */ 68#endif 69 Elf_Dyn* dynamic; /* Symbol table etc. */ 70 Elf_Hashelt nbuckets; /* DT_HASH info */ 71 Elf_Hashelt nchains; 72 const Elf_Hashelt* buckets; 73 const Elf_Hashelt* chains; 74 caddr_t hash; 75 caddr_t strtab; /* DT_STRTAB */ 76 int strsz; /* DT_STRSZ */ 77 const Elf_Sym* symtab; /* DT_SYMTAB */ 78 Elf_Addr* got; /* DT_PLTGOT */ 79 const Elf_Rel* pltrel; /* DT_JMPREL */ 80 int pltrelsize; /* DT_PLTRELSZ */ 81 const Elf_Rela* pltrela; /* DT_JMPREL */ 82 int pltrelasize; /* DT_PLTRELSZ */ 83 const Elf_Rel* rel; /* DT_REL */ 84 int relsize; /* DT_RELSZ */ 85 const Elf_Rela* rela; /* DT_RELA */ 86 int relasize; /* DT_RELASZ */ 87 caddr_t modptr; 88 const Elf_Sym* ddbsymtab; /* The symbol table we are using */ 89 long ddbsymcnt; /* Number of symbols */ 90 caddr_t ddbstrtab; /* String table */ 91 long ddbstrcnt; /* number of bytes in string table */ 92 caddr_t symbase; /* malloc'ed symbold base */ 93 caddr_t strbase; /* malloc'ed string base */ 94#ifdef DDB 95 struct link_map gdb; /* hooks for gdb */ 96#endif 97} *elf_file_t; 98 99static int link_elf_link_common_finish(linker_file_t); 100static int link_elf_link_preload(linker_class_t cls, 101 const char*, linker_file_t*); 102static int link_elf_link_preload_finish(linker_file_t); 103static int link_elf_load_file(linker_class_t, const char*, linker_file_t*); 104static int link_elf_lookup_symbol(linker_file_t, const char*, 105 c_linker_sym_t*); 106static int link_elf_symbol_values(linker_file_t, c_linker_sym_t, linker_symval_t*); 107static int link_elf_search_symbol(linker_file_t, caddr_t value, 108 c_linker_sym_t* sym, long* diffp); 109 110static void link_elf_unload_file(linker_file_t); 111static void link_elf_unload_preload(linker_file_t); 112static int link_elf_lookup_set(linker_file_t, const char *, 113 void ***, void ***, int *); 114static int link_elf_each_function_name(linker_file_t, 115 int (*)(const char *, void *), 116 void *); 117 118static kobj_method_t link_elf_methods[] = { 119 KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol), 120 KOBJMETHOD(linker_symbol_values, link_elf_symbol_values), 121 KOBJMETHOD(linker_search_symbol, link_elf_search_symbol), 122 KOBJMETHOD(linker_unload, link_elf_unload_file), 123 KOBJMETHOD(linker_load_file, link_elf_load_file), 124 KOBJMETHOD(linker_link_preload, link_elf_link_preload), 125 KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish), 126 KOBJMETHOD(linker_lookup_set, link_elf_lookup_set), 127 KOBJMETHOD(linker_each_function_name, link_elf_each_function_name), 128 { 0, 0 } 129}; 130 131static struct linker_class link_elf_class = { 132#if ELF_TARG_CLASS == ELFCLASS32 133 "elf32", 134#else 135 "elf64", 136#endif 137 link_elf_methods, sizeof(struct elf_file) 138}; 139 140static int parse_dynamic(elf_file_t ef); 141static int relocate_file(elf_file_t ef); 142static int link_elf_preload_parse_symbols(elf_file_t ef); 143 144#ifdef DDB 145static void r_debug_state(struct r_debug *dummy_one, 146 struct link_map *dummy_two); 147 148/* 149 * A list of loaded modules for GDB to use for loading symbols. 150 */ 151struct r_debug r_debug; 152 153#define GDB_STATE(s) r_debug.r_state = s; r_debug_state(NULL, NULL); 154 155/* 156 * Function for the debugger to set a breakpoint on to gain control. 157 */ 158static void 159r_debug_state(struct r_debug *dummy_one __unused, 160 struct link_map *dummy_two __unused) 161{ 162} 163 164static void 165link_elf_add_gdb(struct link_map *l) 166{ 167 struct link_map *prev; 168 169 l->l_next = NULL; 170 171 if (r_debug.r_map == NULL) { 172 /* Add first. */ 173 l->l_prev = NULL; 174 r_debug.r_map = l; 175 } else { 176 /* Append to list. */ 177 for (prev = r_debug.r_map; prev->l_next != NULL; prev = prev->l_next) 178 ; 179 l->l_prev = prev; 180 prev->l_next = l; 181 } 182} 183 184static void 185link_elf_delete_gdb(struct link_map *l) 186{ 187 if (l->l_prev == NULL) { 188 /* Remove first. */ 189 if ((r_debug.r_map = l->l_next) != NULL) 190 l->l_next->l_prev = NULL; 191 } else { 192 /* Remove any but first. */ 193 if ((l->l_prev->l_next = l->l_next) != NULL) 194 l->l_next->l_prev = l->l_prev; 195 } 196} 197#endif /* DDB */ 198 199#ifdef __ia64__ 200Elf_Addr link_elf_get_gp(linker_file_t); 201#endif 202 203/* 204 * The kernel symbol table starts here. 205 */ 206extern struct _dynamic _DYNAMIC; 207 208static void 209link_elf_error(const char *s) 210{ 211 printf("kldload: %s\n", s); 212} 213 214/* 215 * Actions performed after linking/loading both the preloaded kernel and any 216 * modules; whether preloaded or dynamicly loaded. 217 */ 218static int 219link_elf_link_common_finish(linker_file_t lf) 220{ 221#ifdef DDB 222 elf_file_t ef = (elf_file_t)lf; 223 char *newfilename; 224#endif 225 int error; 226 227 /* Notify MD code that a module is being loaded. */ 228 error = elf_cpu_load_file(lf); 229 if (error) 230 return (error); 231 232#ifdef DDB 233 GDB_STATE(RT_ADD); 234 ef->gdb.l_addr = lf->address; 235 newfilename = malloc(strlen(lf->filename) + 1, M_LINKER, M_WAITOK); 236 strcpy(newfilename, lf->filename); 237 ef->gdb.l_name = newfilename; 238 ef->gdb.l_ld = ef->dynamic; 239 link_elf_add_gdb(&ef->gdb); 240 GDB_STATE(RT_CONSISTENT); 241#endif 242 243 return (0); 244} 245 246static void 247link_elf_init(void* arg) 248{ 249 Elf_Dyn *dp; 250 caddr_t modptr, baseptr, sizeptr; 251 elf_file_t ef; 252 char *modname; 253 254 linker_add_class(&link_elf_class); 255 256 dp = (Elf_Dyn*) &_DYNAMIC; 257 modname = NULL; 258 modptr = preload_search_by_type("elf kernel"); 259 if (modptr) 260 modname = (char *)preload_search_info(modptr, MODINFO_NAME); 261 if (modname == NULL) 262 modname = "kernel"; 263 linker_kernel_file = linker_make_file(modname, &link_elf_class); 264 if (linker_kernel_file == NULL) 265 panic("link_elf_init: Can't create linker structures for kernel"); 266 267 ef = (elf_file_t) linker_kernel_file; 268 ef->preloaded = 1; 269 ef->address = 0; 270#ifdef SPARSE_MAPPING 271 ef->object = 0; 272#endif 273 ef->dynamic = dp; 274 275 if (dp) 276 parse_dynamic(ef); 277 linker_kernel_file->address = (caddr_t) KERNBASE; 278 linker_kernel_file->size = -(intptr_t)linker_kernel_file->address; 279 280 if (modptr) { 281 ef->modptr = modptr; 282 baseptr = preload_search_info(modptr, MODINFO_ADDR); 283 if (baseptr) 284 linker_kernel_file->address = *(caddr_t *)baseptr; 285 sizeptr = preload_search_info(modptr, MODINFO_SIZE); 286 if (sizeptr) 287 linker_kernel_file->size = *(size_t *)sizeptr; 288 } 289 (void)link_elf_preload_parse_symbols(ef); 290 291#ifdef DDB 292 r_debug.r_map = NULL; 293 r_debug.r_brk = r_debug_state; 294 r_debug.r_state = RT_CONSISTENT; 295#endif 296 297 (void)link_elf_link_common_finish(linker_kernel_file); 298} 299 300SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0); 301 302static int 303link_elf_preload_parse_symbols(elf_file_t ef) 304{ 305 caddr_t pointer; 306 caddr_t ssym, esym, base; 307 caddr_t strtab; 308 int strcnt; 309 Elf_Sym* symtab; 310 int symcnt; 311 312 if (ef->modptr == NULL) 313 return 0; 314 pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_SSYM); 315 if (pointer == NULL) 316 return 0; 317 ssym = *(caddr_t *)pointer; 318 pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_ESYM); 319 if (pointer == NULL) 320 return 0; 321 esym = *(caddr_t *)pointer; 322 323 base = ssym; 324 325 symcnt = *(long *)base; 326 base += sizeof(long); 327 symtab = (Elf_Sym *)base; 328 base += roundup(symcnt, sizeof(long)); 329 330 if (base > esym || base < ssym) { 331 printf("Symbols are corrupt!\n"); 332 return EINVAL; 333 } 334 335 strcnt = *(long *)base; 336 base += sizeof(long); 337 strtab = base; 338 base += roundup(strcnt, sizeof(long)); 339 340 if (base > esym || base < ssym) { 341 printf("Symbols are corrupt!\n"); 342 return EINVAL; 343 } 344 345 ef->ddbsymtab = symtab; 346 ef->ddbsymcnt = symcnt / sizeof(Elf_Sym); 347 ef->ddbstrtab = strtab; 348 ef->ddbstrcnt = strcnt; 349 350 return 0; 351} 352 353static int 354parse_dynamic(elf_file_t ef) 355{ 356 Elf_Dyn *dp; 357 int plttype = DT_REL; 358 359 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) { 360 switch (dp->d_tag) { 361 case DT_HASH: 362 { 363 /* From src/libexec/rtld-elf/rtld.c */ 364 const Elf_Hashelt *hashtab = (const Elf_Hashelt *) 365 (ef->address + dp->d_un.d_ptr); 366 ef->nbuckets = hashtab[0]; 367 ef->nchains = hashtab[1]; 368 ef->buckets = hashtab + 2; 369 ef->chains = ef->buckets + ef->nbuckets; 370 break; 371 } 372 case DT_STRTAB: 373 ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr); 374 break; 375 case DT_STRSZ: 376 ef->strsz = dp->d_un.d_val; 377 break; 378 case DT_SYMTAB: 379 ef->symtab = (Elf_Sym*) (ef->address + dp->d_un.d_ptr); 380 break; 381 case DT_SYMENT: 382 if (dp->d_un.d_val != sizeof(Elf_Sym)) 383 return ENOEXEC; 384 break; 385 case DT_PLTGOT: 386 ef->got = (Elf_Addr *) (ef->address + dp->d_un.d_ptr); 387 break; 388 case DT_REL: 389 ef->rel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr); 390 break; 391 case DT_RELSZ: 392 ef->relsize = dp->d_un.d_val; 393 break; 394 case DT_RELENT: 395 if (dp->d_un.d_val != sizeof(Elf_Rel)) 396 return ENOEXEC; 397 break; 398 case DT_JMPREL: 399 ef->pltrel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr); 400 break; 401 case DT_PLTRELSZ: 402 ef->pltrelsize = dp->d_un.d_val; 403 break; 404 case DT_RELA: 405 ef->rela = (const Elf_Rela *) (ef->address + dp->d_un.d_ptr); 406 break; 407 case DT_RELASZ: 408 ef->relasize = dp->d_un.d_val; 409 break; 410 case DT_RELAENT: 411 if (dp->d_un.d_val != sizeof(Elf_Rela)) 412 return ENOEXEC; 413 break; 414 case DT_PLTREL: 415 plttype = dp->d_un.d_val; 416 if (plttype != DT_REL && plttype != DT_RELA) 417 return ENOEXEC; 418 break; 419#ifdef DDB 420 case DT_DEBUG: 421 dp->d_un.d_ptr = (Elf_Addr) &r_debug; 422 break; 423#endif 424 } 425 } 426 427 if (plttype == DT_RELA) { 428 ef->pltrela = (const Elf_Rela *) ef->pltrel; 429 ef->pltrel = NULL; 430 ef->pltrelasize = ef->pltrelsize; 431 ef->pltrelsize = 0; 432 } 433 434 ef->ddbsymtab = ef->symtab; 435 ef->ddbsymcnt = ef->nchains; 436 ef->ddbstrtab = ef->strtab; 437 ef->ddbstrcnt = ef->strsz; 438 439 return 0; 440} 441 442static int 443link_elf_link_preload(linker_class_t cls, 444 const char* filename, linker_file_t *result) 445{ 446 caddr_t modptr, baseptr, sizeptr, dynptr; 447 char *type; 448 elf_file_t ef; 449 linker_file_t lf; 450 int error; 451 vm_offset_t dp; 452 453 /* Look to see if we have the file preloaded */ 454 modptr = preload_search_by_name(filename); 455 if (modptr == NULL) 456 return ENOENT; 457 458 type = (char *)preload_search_info(modptr, MODINFO_TYPE); 459 baseptr = preload_search_info(modptr, MODINFO_ADDR); 460 sizeptr = preload_search_info(modptr, MODINFO_SIZE); 461 dynptr = preload_search_info(modptr, MODINFO_METADATA|MODINFOMD_DYNAMIC); 462 if (type == NULL || strcmp(type, "elf module") != 0) 463 return (EFTYPE); 464 if (baseptr == NULL || sizeptr == NULL || dynptr == NULL) 465 return (EINVAL); 466 467 lf = linker_make_file(filename, &link_elf_class); 468 if (lf == NULL) { 469 return ENOMEM; 470 } 471 472 ef = (elf_file_t) lf; 473 ef->preloaded = 1; 474 ef->modptr = modptr; 475 ef->address = *(caddr_t *)baseptr; 476#ifdef SPARSE_MAPPING 477 ef->object = 0; 478#endif 479 dp = (vm_offset_t)ef->address + *(vm_offset_t *)dynptr; 480 ef->dynamic = (Elf_Dyn *)dp; 481 lf->address = ef->address; 482 lf->size = *(size_t *)sizeptr; 483 484 error = parse_dynamic(ef); 485 if (error) { 486 linker_file_unload(lf); 487 return error; 488 } 489 *result = lf; 490 return (0); 491} 492 493static int 494link_elf_link_preload_finish(linker_file_t lf) 495{ 496 elf_file_t ef; 497 int error; 498 499 ef = (elf_file_t) lf; 500#if 0 /* this will be more trouble than it's worth for now */ 501 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) { 502 if (dp->d_tag != DT_NEEDED) 503 continue; 504 modname = ef->strtab + dp->d_un.d_val; 505 error = linker_load_module(modname, lf); 506 if (error) 507 goto out; 508 } 509#endif 510 error = relocate_file(ef); 511 if (error) 512 return error; 513 (void)link_elf_preload_parse_symbols(ef); 514 515 return (link_elf_link_common_finish(lf)); 516} 517 518static int 519link_elf_load_file(linker_class_t cls, const char* filename, 520 linker_file_t* result) 521{ 522 struct nameidata nd; 523 struct thread* td = curthread; /* XXX */ 524 Elf_Ehdr *hdr; 525 caddr_t firstpage; 526 int nbytes, i; 527 Elf_Phdr *phdr; 528 Elf_Phdr *phlimit; 529 Elf_Phdr *segs[2]; 530 int nsegs; 531 Elf_Phdr *phdyn; 532 Elf_Phdr *phphdr; 533 caddr_t mapbase; 534 size_t mapsize; 535 Elf_Off base_offset; 536 Elf_Addr base_vaddr; 537 Elf_Addr base_vlimit; 538 int error = 0; 539 int resid, flags; 540 elf_file_t ef; 541 linker_file_t lf; 542 Elf_Shdr *shdr; 543 int symtabindex; 544 int symstrindex; 545 int symcnt; 546 int strcnt; 547 548 GIANT_REQUIRED; 549 550 shdr = NULL; 551 lf = NULL; 552 553 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td); 554 flags = FREAD; 555 error = vn_open(&nd, &flags, 0); 556 if (error) 557 return error; 558 NDFREE(&nd, NDF_ONLY_PNBUF);
| 37#include <sys/malloc.h> 38#include <sys/mutex.h> 39#include <sys/proc.h> 40#include <sys/namei.h> 41#include <sys/fcntl.h> 42#include <sys/vnode.h> 43#include <sys/linker.h> 44 45#include <machine/elf.h> 46#ifdef GPROF 47#include <machine/profile.h> 48#endif 49 50#include <vm/vm.h> 51#include <vm/vm_param.h> 52#ifdef SPARSE_MAPPING 53#include <vm/vm_object.h> 54#include <vm/vm_kern.h> 55#include <vm/vm_extern.h> 56#endif 57#include <vm/pmap.h> 58#include <vm/vm_map.h> 59 60#include <sys/link_elf.h> 61 62#include "linker_if.h" 63 64typedef struct elf_file { 65 struct linker_file lf; /* Common fields */ 66 int preloaded; /* Was file pre-loaded */ 67 caddr_t address; /* Relocation address */ 68#ifdef SPARSE_MAPPING 69 vm_object_t object; /* VM object to hold file pages */ 70#endif 71 Elf_Dyn* dynamic; /* Symbol table etc. */ 72 Elf_Hashelt nbuckets; /* DT_HASH info */ 73 Elf_Hashelt nchains; 74 const Elf_Hashelt* buckets; 75 const Elf_Hashelt* chains; 76 caddr_t hash; 77 caddr_t strtab; /* DT_STRTAB */ 78 int strsz; /* DT_STRSZ */ 79 const Elf_Sym* symtab; /* DT_SYMTAB */ 80 Elf_Addr* got; /* DT_PLTGOT */ 81 const Elf_Rel* pltrel; /* DT_JMPREL */ 82 int pltrelsize; /* DT_PLTRELSZ */ 83 const Elf_Rela* pltrela; /* DT_JMPREL */ 84 int pltrelasize; /* DT_PLTRELSZ */ 85 const Elf_Rel* rel; /* DT_REL */ 86 int relsize; /* DT_RELSZ */ 87 const Elf_Rela* rela; /* DT_RELA */ 88 int relasize; /* DT_RELASZ */ 89 caddr_t modptr; 90 const Elf_Sym* ddbsymtab; /* The symbol table we are using */ 91 long ddbsymcnt; /* Number of symbols */ 92 caddr_t ddbstrtab; /* String table */ 93 long ddbstrcnt; /* number of bytes in string table */ 94 caddr_t symbase; /* malloc'ed symbold base */ 95 caddr_t strbase; /* malloc'ed string base */ 96#ifdef DDB 97 struct link_map gdb; /* hooks for gdb */ 98#endif 99} *elf_file_t; 100 101static int link_elf_link_common_finish(linker_file_t); 102static int link_elf_link_preload(linker_class_t cls, 103 const char*, linker_file_t*); 104static int link_elf_link_preload_finish(linker_file_t); 105static int link_elf_load_file(linker_class_t, const char*, linker_file_t*); 106static int link_elf_lookup_symbol(linker_file_t, const char*, 107 c_linker_sym_t*); 108static int link_elf_symbol_values(linker_file_t, c_linker_sym_t, linker_symval_t*); 109static int link_elf_search_symbol(linker_file_t, caddr_t value, 110 c_linker_sym_t* sym, long* diffp); 111 112static void link_elf_unload_file(linker_file_t); 113static void link_elf_unload_preload(linker_file_t); 114static int link_elf_lookup_set(linker_file_t, const char *, 115 void ***, void ***, int *); 116static int link_elf_each_function_name(linker_file_t, 117 int (*)(const char *, void *), 118 void *); 119 120static kobj_method_t link_elf_methods[] = { 121 KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol), 122 KOBJMETHOD(linker_symbol_values, link_elf_symbol_values), 123 KOBJMETHOD(linker_search_symbol, link_elf_search_symbol), 124 KOBJMETHOD(linker_unload, link_elf_unload_file), 125 KOBJMETHOD(linker_load_file, link_elf_load_file), 126 KOBJMETHOD(linker_link_preload, link_elf_link_preload), 127 KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish), 128 KOBJMETHOD(linker_lookup_set, link_elf_lookup_set), 129 KOBJMETHOD(linker_each_function_name, link_elf_each_function_name), 130 { 0, 0 } 131}; 132 133static struct linker_class link_elf_class = { 134#if ELF_TARG_CLASS == ELFCLASS32 135 "elf32", 136#else 137 "elf64", 138#endif 139 link_elf_methods, sizeof(struct elf_file) 140}; 141 142static int parse_dynamic(elf_file_t ef); 143static int relocate_file(elf_file_t ef); 144static int link_elf_preload_parse_symbols(elf_file_t ef); 145 146#ifdef DDB 147static void r_debug_state(struct r_debug *dummy_one, 148 struct link_map *dummy_two); 149 150/* 151 * A list of loaded modules for GDB to use for loading symbols. 152 */ 153struct r_debug r_debug; 154 155#define GDB_STATE(s) r_debug.r_state = s; r_debug_state(NULL, NULL); 156 157/* 158 * Function for the debugger to set a breakpoint on to gain control. 159 */ 160static void 161r_debug_state(struct r_debug *dummy_one __unused, 162 struct link_map *dummy_two __unused) 163{ 164} 165 166static void 167link_elf_add_gdb(struct link_map *l) 168{ 169 struct link_map *prev; 170 171 l->l_next = NULL; 172 173 if (r_debug.r_map == NULL) { 174 /* Add first. */ 175 l->l_prev = NULL; 176 r_debug.r_map = l; 177 } else { 178 /* Append to list. */ 179 for (prev = r_debug.r_map; prev->l_next != NULL; prev = prev->l_next) 180 ; 181 l->l_prev = prev; 182 prev->l_next = l; 183 } 184} 185 186static void 187link_elf_delete_gdb(struct link_map *l) 188{ 189 if (l->l_prev == NULL) { 190 /* Remove first. */ 191 if ((r_debug.r_map = l->l_next) != NULL) 192 l->l_next->l_prev = NULL; 193 } else { 194 /* Remove any but first. */ 195 if ((l->l_prev->l_next = l->l_next) != NULL) 196 l->l_next->l_prev = l->l_prev; 197 } 198} 199#endif /* DDB */ 200 201#ifdef __ia64__ 202Elf_Addr link_elf_get_gp(linker_file_t); 203#endif 204 205/* 206 * The kernel symbol table starts here. 207 */ 208extern struct _dynamic _DYNAMIC; 209 210static void 211link_elf_error(const char *s) 212{ 213 printf("kldload: %s\n", s); 214} 215 216/* 217 * Actions performed after linking/loading both the preloaded kernel and any 218 * modules; whether preloaded or dynamicly loaded. 219 */ 220static int 221link_elf_link_common_finish(linker_file_t lf) 222{ 223#ifdef DDB 224 elf_file_t ef = (elf_file_t)lf; 225 char *newfilename; 226#endif 227 int error; 228 229 /* Notify MD code that a module is being loaded. */ 230 error = elf_cpu_load_file(lf); 231 if (error) 232 return (error); 233 234#ifdef DDB 235 GDB_STATE(RT_ADD); 236 ef->gdb.l_addr = lf->address; 237 newfilename = malloc(strlen(lf->filename) + 1, M_LINKER, M_WAITOK); 238 strcpy(newfilename, lf->filename); 239 ef->gdb.l_name = newfilename; 240 ef->gdb.l_ld = ef->dynamic; 241 link_elf_add_gdb(&ef->gdb); 242 GDB_STATE(RT_CONSISTENT); 243#endif 244 245 return (0); 246} 247 248static void 249link_elf_init(void* arg) 250{ 251 Elf_Dyn *dp; 252 caddr_t modptr, baseptr, sizeptr; 253 elf_file_t ef; 254 char *modname; 255 256 linker_add_class(&link_elf_class); 257 258 dp = (Elf_Dyn*) &_DYNAMIC; 259 modname = NULL; 260 modptr = preload_search_by_type("elf kernel"); 261 if (modptr) 262 modname = (char *)preload_search_info(modptr, MODINFO_NAME); 263 if (modname == NULL) 264 modname = "kernel"; 265 linker_kernel_file = linker_make_file(modname, &link_elf_class); 266 if (linker_kernel_file == NULL) 267 panic("link_elf_init: Can't create linker structures for kernel"); 268 269 ef = (elf_file_t) linker_kernel_file; 270 ef->preloaded = 1; 271 ef->address = 0; 272#ifdef SPARSE_MAPPING 273 ef->object = 0; 274#endif 275 ef->dynamic = dp; 276 277 if (dp) 278 parse_dynamic(ef); 279 linker_kernel_file->address = (caddr_t) KERNBASE; 280 linker_kernel_file->size = -(intptr_t)linker_kernel_file->address; 281 282 if (modptr) { 283 ef->modptr = modptr; 284 baseptr = preload_search_info(modptr, MODINFO_ADDR); 285 if (baseptr) 286 linker_kernel_file->address = *(caddr_t *)baseptr; 287 sizeptr = preload_search_info(modptr, MODINFO_SIZE); 288 if (sizeptr) 289 linker_kernel_file->size = *(size_t *)sizeptr; 290 } 291 (void)link_elf_preload_parse_symbols(ef); 292 293#ifdef DDB 294 r_debug.r_map = NULL; 295 r_debug.r_brk = r_debug_state; 296 r_debug.r_state = RT_CONSISTENT; 297#endif 298 299 (void)link_elf_link_common_finish(linker_kernel_file); 300} 301 302SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0); 303 304static int 305link_elf_preload_parse_symbols(elf_file_t ef) 306{ 307 caddr_t pointer; 308 caddr_t ssym, esym, base; 309 caddr_t strtab; 310 int strcnt; 311 Elf_Sym* symtab; 312 int symcnt; 313 314 if (ef->modptr == NULL) 315 return 0; 316 pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_SSYM); 317 if (pointer == NULL) 318 return 0; 319 ssym = *(caddr_t *)pointer; 320 pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_ESYM); 321 if (pointer == NULL) 322 return 0; 323 esym = *(caddr_t *)pointer; 324 325 base = ssym; 326 327 symcnt = *(long *)base; 328 base += sizeof(long); 329 symtab = (Elf_Sym *)base; 330 base += roundup(symcnt, sizeof(long)); 331 332 if (base > esym || base < ssym) { 333 printf("Symbols are corrupt!\n"); 334 return EINVAL; 335 } 336 337 strcnt = *(long *)base; 338 base += sizeof(long); 339 strtab = base; 340 base += roundup(strcnt, sizeof(long)); 341 342 if (base > esym || base < ssym) { 343 printf("Symbols are corrupt!\n"); 344 return EINVAL; 345 } 346 347 ef->ddbsymtab = symtab; 348 ef->ddbsymcnt = symcnt / sizeof(Elf_Sym); 349 ef->ddbstrtab = strtab; 350 ef->ddbstrcnt = strcnt; 351 352 return 0; 353} 354 355static int 356parse_dynamic(elf_file_t ef) 357{ 358 Elf_Dyn *dp; 359 int plttype = DT_REL; 360 361 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) { 362 switch (dp->d_tag) { 363 case DT_HASH: 364 { 365 /* From src/libexec/rtld-elf/rtld.c */ 366 const Elf_Hashelt *hashtab = (const Elf_Hashelt *) 367 (ef->address + dp->d_un.d_ptr); 368 ef->nbuckets = hashtab[0]; 369 ef->nchains = hashtab[1]; 370 ef->buckets = hashtab + 2; 371 ef->chains = ef->buckets + ef->nbuckets; 372 break; 373 } 374 case DT_STRTAB: 375 ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr); 376 break; 377 case DT_STRSZ: 378 ef->strsz = dp->d_un.d_val; 379 break; 380 case DT_SYMTAB: 381 ef->symtab = (Elf_Sym*) (ef->address + dp->d_un.d_ptr); 382 break; 383 case DT_SYMENT: 384 if (dp->d_un.d_val != sizeof(Elf_Sym)) 385 return ENOEXEC; 386 break; 387 case DT_PLTGOT: 388 ef->got = (Elf_Addr *) (ef->address + dp->d_un.d_ptr); 389 break; 390 case DT_REL: 391 ef->rel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr); 392 break; 393 case DT_RELSZ: 394 ef->relsize = dp->d_un.d_val; 395 break; 396 case DT_RELENT: 397 if (dp->d_un.d_val != sizeof(Elf_Rel)) 398 return ENOEXEC; 399 break; 400 case DT_JMPREL: 401 ef->pltrel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr); 402 break; 403 case DT_PLTRELSZ: 404 ef->pltrelsize = dp->d_un.d_val; 405 break; 406 case DT_RELA: 407 ef->rela = (const Elf_Rela *) (ef->address + dp->d_un.d_ptr); 408 break; 409 case DT_RELASZ: 410 ef->relasize = dp->d_un.d_val; 411 break; 412 case DT_RELAENT: 413 if (dp->d_un.d_val != sizeof(Elf_Rela)) 414 return ENOEXEC; 415 break; 416 case DT_PLTREL: 417 plttype = dp->d_un.d_val; 418 if (plttype != DT_REL && plttype != DT_RELA) 419 return ENOEXEC; 420 break; 421#ifdef DDB 422 case DT_DEBUG: 423 dp->d_un.d_ptr = (Elf_Addr) &r_debug; 424 break; 425#endif 426 } 427 } 428 429 if (plttype == DT_RELA) { 430 ef->pltrela = (const Elf_Rela *) ef->pltrel; 431 ef->pltrel = NULL; 432 ef->pltrelasize = ef->pltrelsize; 433 ef->pltrelsize = 0; 434 } 435 436 ef->ddbsymtab = ef->symtab; 437 ef->ddbsymcnt = ef->nchains; 438 ef->ddbstrtab = ef->strtab; 439 ef->ddbstrcnt = ef->strsz; 440 441 return 0; 442} 443 444static int 445link_elf_link_preload(linker_class_t cls, 446 const char* filename, linker_file_t *result) 447{ 448 caddr_t modptr, baseptr, sizeptr, dynptr; 449 char *type; 450 elf_file_t ef; 451 linker_file_t lf; 452 int error; 453 vm_offset_t dp; 454 455 /* Look to see if we have the file preloaded */ 456 modptr = preload_search_by_name(filename); 457 if (modptr == NULL) 458 return ENOENT; 459 460 type = (char *)preload_search_info(modptr, MODINFO_TYPE); 461 baseptr = preload_search_info(modptr, MODINFO_ADDR); 462 sizeptr = preload_search_info(modptr, MODINFO_SIZE); 463 dynptr = preload_search_info(modptr, MODINFO_METADATA|MODINFOMD_DYNAMIC); 464 if (type == NULL || strcmp(type, "elf module") != 0) 465 return (EFTYPE); 466 if (baseptr == NULL || sizeptr == NULL || dynptr == NULL) 467 return (EINVAL); 468 469 lf = linker_make_file(filename, &link_elf_class); 470 if (lf == NULL) { 471 return ENOMEM; 472 } 473 474 ef = (elf_file_t) lf; 475 ef->preloaded = 1; 476 ef->modptr = modptr; 477 ef->address = *(caddr_t *)baseptr; 478#ifdef SPARSE_MAPPING 479 ef->object = 0; 480#endif 481 dp = (vm_offset_t)ef->address + *(vm_offset_t *)dynptr; 482 ef->dynamic = (Elf_Dyn *)dp; 483 lf->address = ef->address; 484 lf->size = *(size_t *)sizeptr; 485 486 error = parse_dynamic(ef); 487 if (error) { 488 linker_file_unload(lf); 489 return error; 490 } 491 *result = lf; 492 return (0); 493} 494 495static int 496link_elf_link_preload_finish(linker_file_t lf) 497{ 498 elf_file_t ef; 499 int error; 500 501 ef = (elf_file_t) lf; 502#if 0 /* this will be more trouble than it's worth for now */ 503 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) { 504 if (dp->d_tag != DT_NEEDED) 505 continue; 506 modname = ef->strtab + dp->d_un.d_val; 507 error = linker_load_module(modname, lf); 508 if (error) 509 goto out; 510 } 511#endif 512 error = relocate_file(ef); 513 if (error) 514 return error; 515 (void)link_elf_preload_parse_symbols(ef); 516 517 return (link_elf_link_common_finish(lf)); 518} 519 520static int 521link_elf_load_file(linker_class_t cls, const char* filename, 522 linker_file_t* result) 523{ 524 struct nameidata nd; 525 struct thread* td = curthread; /* XXX */ 526 Elf_Ehdr *hdr; 527 caddr_t firstpage; 528 int nbytes, i; 529 Elf_Phdr *phdr; 530 Elf_Phdr *phlimit; 531 Elf_Phdr *segs[2]; 532 int nsegs; 533 Elf_Phdr *phdyn; 534 Elf_Phdr *phphdr; 535 caddr_t mapbase; 536 size_t mapsize; 537 Elf_Off base_offset; 538 Elf_Addr base_vaddr; 539 Elf_Addr base_vlimit; 540 int error = 0; 541 int resid, flags; 542 elf_file_t ef; 543 linker_file_t lf; 544 Elf_Shdr *shdr; 545 int symtabindex; 546 int symstrindex; 547 int symcnt; 548 int strcnt; 549 550 GIANT_REQUIRED; 551 552 shdr = NULL; 553 lf = NULL; 554 555 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td); 556 flags = FREAD; 557 error = vn_open(&nd, &flags, 0); 558 if (error) 559 return error; 560 NDFREE(&nd, NDF_ONLY_PNBUF);
|
559 560 /* 561 * Read the elf header from the file. 562 */ 563 firstpage = malloc(PAGE_SIZE, M_LINKER, M_WAITOK); 564 if (firstpage == NULL) { 565 error = ENOMEM; 566 goto out; 567 } 568 hdr = (Elf_Ehdr *)firstpage; 569 error = vn_rdwr(UIO_READ, nd.ni_vp, firstpage, PAGE_SIZE, 0, 570 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 571 &resid, td); 572 nbytes = PAGE_SIZE - resid; 573 if (error) 574 goto out; 575 576 if (!IS_ELF(*hdr)) { 577 error = ENOEXEC; 578 goto out; 579 } 580 581 if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS 582 || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) { 583 link_elf_error("Unsupported file layout"); 584 error = ENOEXEC; 585 goto out; 586 } 587 if (hdr->e_ident[EI_VERSION] != EV_CURRENT 588 || hdr->e_version != EV_CURRENT) { 589 link_elf_error("Unsupported file version"); 590 error = ENOEXEC; 591 goto out; 592 } 593 if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) { 594 link_elf_error("Unsupported file type"); 595 error = ENOEXEC; 596 goto out; 597 } 598 if (hdr->e_machine != ELF_TARG_MACH) { 599 link_elf_error("Unsupported machine"); 600 error = ENOEXEC; 601 goto out; 602 } 603 604 /* 605 * We rely on the program header being in the first page. This is 606 * not strictly required by the ABI specification, but it seems to 607 * always true in practice. And, it simplifies things considerably. 608 */ 609 if (!((hdr->e_phentsize == sizeof(Elf_Phdr)) && 610 (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE) && 611 (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= nbytes))) 612 link_elf_error("Unreadable program headers"); 613 614 /* 615 * Scan the program header entries, and save key information. 616 * 617 * We rely on there being exactly two load segments, text and data, 618 * in that order. 619 */ 620 phdr = (Elf_Phdr *) (firstpage + hdr->e_phoff); 621 phlimit = phdr + hdr->e_phnum; 622 nsegs = 0; 623 phdyn = NULL; 624 phphdr = NULL; 625 while (phdr < phlimit) { 626 switch (phdr->p_type) { 627 628 case PT_LOAD: 629 if (nsegs == 2) { 630 link_elf_error("Too many sections"); 631 error = ENOEXEC; 632 goto out; 633 } 634 segs[nsegs] = phdr; 635 ++nsegs; 636 break; 637 638 case PT_PHDR: 639 phphdr = phdr; 640 break; 641 642 case PT_DYNAMIC: 643 phdyn = phdr; 644 break; 645 646 case PT_INTERP: 647 link_elf_error("Unsupported file type"); 648 error = ENOEXEC; 649 goto out; 650 } 651 652 ++phdr; 653 } 654 if (phdyn == NULL) { 655 link_elf_error("Object is not dynamically-linked"); 656 error = ENOEXEC; 657 goto out; 658 } 659 660 /* 661 * Allocate the entire address space of the object, to stake out our 662 * contiguous region, and to establish the base address for relocation. 663 */ 664 base_offset = trunc_page(segs[0]->p_offset); 665 base_vaddr = trunc_page(segs[0]->p_vaddr); 666 base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz); 667 mapsize = base_vlimit - base_vaddr; 668 669 lf = linker_make_file(filename, &link_elf_class); 670 if (!lf) { 671 error = ENOMEM; 672 goto out; 673 } 674 675 ef = (elf_file_t) lf; 676#ifdef SPARSE_MAPPING 677 ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT); 678 if (ef->object == NULL) { 679 error = ENOMEM; 680 goto out; 681 } 682 vm_object_reference(ef->object); 683 ef->address = (caddr_t) vm_map_min(kernel_map); 684 error = vm_map_find(kernel_map, ef->object, 0, 685 (vm_offset_t *) &ef->address, 686 mapsize, 1, 687 VM_PROT_ALL, VM_PROT_ALL, 0); 688 if (error) { 689 vm_object_deallocate(ef->object); 690 ef->object = 0; 691 goto out; 692 } 693#else 694 ef->address = malloc(mapsize, M_LINKER, M_WAITOK); 695 if (!ef->address) { 696 error = ENOMEM; 697 goto out; 698 } 699#endif 700 mapbase = ef->address; 701 702 /* 703 * Read the text and data sections and zero the bss. 704 */ 705 for (i = 0; i < 2; i++) { 706 caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr; 707 error = vn_rdwr(UIO_READ, nd.ni_vp, 708 segbase, segs[i]->p_filesz, segs[i]->p_offset, 709 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 710 &resid, td); 711 if (error) { 712 goto out; 713 } 714 bzero(segbase + segs[i]->p_filesz, 715 segs[i]->p_memsz - segs[i]->p_filesz); 716 717#ifdef SPARSE_MAPPING 718 /* 719 * Wire down the pages 720 */ 721 vm_map_wire(kernel_map, 722 (vm_offset_t) segbase, 723 (vm_offset_t) segbase + segs[i]->p_memsz, 724 FALSE); 725#endif 726 } 727 728#ifdef GPROF 729 /* Update profiling information with the new text segment. */ 730 kmupetext((uintfptr_t)(mapbase + segs[0]->p_vaddr - base_vaddr + 731 segs[0]->p_memsz)); 732#endif 733 734 ef->dynamic = (Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr); 735 736 lf->address = ef->address; 737 lf->size = mapsize; 738 739 error = parse_dynamic(ef); 740 if (error) 741 goto out; 742 error = linker_load_dependencies(lf); 743 if (error) 744 goto out; 745#if 0 /* this will be more trouble than it's worth for now */ 746 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) { 747 if (dp->d_tag != DT_NEEDED) 748 continue; 749 modname = ef->strtab + dp->d_un.d_val; 750 error = linker_load_module(modname, lf); 751 if (error) 752 goto out; 753 } 754#endif 755 error = relocate_file(ef); 756 if (error) 757 goto out; 758 759 /* Try and load the symbol table if it's present. (you can strip it!) */ 760 nbytes = hdr->e_shnum * hdr->e_shentsize; 761 if (nbytes == 0 || hdr->e_shoff == 0) 762 goto nosyms; 763 shdr = malloc(nbytes, M_LINKER, M_WAITOK | M_ZERO); 764 if (shdr == NULL) { 765 error = ENOMEM; 766 goto out; 767 } 768 error = vn_rdwr(UIO_READ, nd.ni_vp, 769 (caddr_t)shdr, nbytes, hdr->e_shoff, 770 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 771 &resid, td); 772 if (error) 773 goto out; 774 symtabindex = -1; 775 symstrindex = -1; 776 for (i = 0; i < hdr->e_shnum; i++) { 777 if (shdr[i].sh_type == SHT_SYMTAB) { 778 symtabindex = i; 779 symstrindex = shdr[i].sh_link; 780 } 781 } 782 if (symtabindex < 0 || symstrindex < 0) 783 goto nosyms; 784 785 symcnt = shdr[symtabindex].sh_size; 786 ef->symbase = malloc(symcnt, M_LINKER, M_WAITOK); 787 strcnt = shdr[symstrindex].sh_size; 788 ef->strbase = malloc(strcnt, M_LINKER, M_WAITOK); 789 790 if (ef->symbase == NULL || ef->strbase == NULL) { 791 error = ENOMEM; 792 goto out; 793 } 794 error = vn_rdwr(UIO_READ, nd.ni_vp, 795 ef->symbase, symcnt, shdr[symtabindex].sh_offset, 796 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 797 &resid, td); 798 if (error) 799 goto out; 800 error = vn_rdwr(UIO_READ, nd.ni_vp, 801 ef->strbase, strcnt, shdr[symstrindex].sh_offset, 802 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 803 &resid, td); 804 if (error) 805 goto out; 806 807 ef->ddbsymcnt = symcnt / sizeof(Elf_Sym); 808 ef->ddbsymtab = (const Elf_Sym *)ef->symbase; 809 ef->ddbstrcnt = strcnt; 810 ef->ddbstrtab = ef->strbase; 811 812 error = link_elf_link_common_finish(lf); 813 if (error) 814 goto out; 815 816nosyms: 817 818 *result = lf; 819 820out: 821 if (error && lf) 822 linker_file_unload(lf); 823 if (shdr) 824 free(shdr, M_LINKER); 825 if (firstpage) 826 free(firstpage, M_LINKER); 827 VOP_UNLOCK(nd.ni_vp, 0, td); 828 vn_close(nd.ni_vp, FREAD, td->td_ucred, td); 829 830 return error; 831} 832 833static void 834link_elf_unload_file(linker_file_t file) 835{ 836 elf_file_t ef = (elf_file_t) file; 837 838#ifdef DDB 839 if (ef->gdb.l_ld) { 840 GDB_STATE(RT_DELETE); 841 free((void *)(uintptr_t)ef->gdb.l_name, M_LINKER); 842 link_elf_delete_gdb(&ef->gdb); 843 GDB_STATE(RT_CONSISTENT); 844 } 845#endif 846 847 /* Notify MD code that a module is being unloaded. */ 848 elf_cpu_unload_file(file); 849 850 if (ef->preloaded) { 851 link_elf_unload_preload(file); 852 return; 853 } 854 855#ifdef SPARSE_MAPPING 856 if (ef->object) { 857 vm_map_remove(kernel_map, (vm_offset_t) ef->address, 858 (vm_offset_t) ef->address 859 + (ef->object->size << PAGE_SHIFT)); 860 vm_object_deallocate(ef->object); 861 } 862#else 863 if (ef->address) 864 free(ef->address, M_LINKER); 865#endif 866 if (ef->symbase) 867 free(ef->symbase, M_LINKER); 868 if (ef->strbase) 869 free(ef->strbase, M_LINKER); 870} 871 872static void 873link_elf_unload_preload(linker_file_t file) 874{ 875 if (file->filename) 876 preload_delete_name(file->filename); 877} 878 879static const char * 880symbol_name(elf_file_t ef, Elf_Word r_info) 881{ 882 const Elf_Sym *ref; 883 884 if (ELF_R_SYM(r_info)) { 885 ref = ef->symtab + ELF_R_SYM(r_info); 886 return ef->strtab + ref->st_name; 887 } else 888 return NULL; 889} 890 891static int 892relocate_file(elf_file_t ef) 893{ 894 const Elf_Rel *rellim; 895 const Elf_Rel *rel; 896 const Elf_Rela *relalim; 897 const Elf_Rela *rela; 898 const char *symname; 899 900 /* Perform relocations without addend if there are any: */ 901 rel = ef->rel; 902 if (rel) { 903 rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize); 904 while (rel < rellim) { 905 if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) { 906 symname = symbol_name(ef, rel->r_info); 907 printf("link_elf: symbol %s undefined\n", symname); 908 return ENOENT; 909 } 910 rel++; 911 } 912 } 913 914 /* Perform relocations with addend if there are any: */ 915 rela = ef->rela; 916 if (rela) { 917 relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize); 918 while (rela < relalim) { 919 if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) { 920 symname = symbol_name(ef, rela->r_info); 921 printf("link_elf: symbol %s undefined\n", symname); 922 return ENOENT; 923 } 924 rela++; 925 } 926 } 927 928 /* Perform PLT relocations without addend if there are any: */ 929 rel = ef->pltrel; 930 if (rel) { 931 rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize); 932 while (rel < rellim) { 933 if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) { 934 symname = symbol_name(ef, rel->r_info); 935 printf("link_elf: symbol %s undefined\n", symname); 936 return ENOENT; 937 } 938 rel++; 939 } 940 } 941 942 /* Perform relocations with addend if there are any: */ 943 rela = ef->pltrela; 944 if (rela) { 945 relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize); 946 while (rela < relalim) { 947 if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) { 948 symname = symbol_name(ef, rela->r_info); 949 printf("link_elf: symbol %s undefined\n", symname); 950 return ENOENT; 951 } 952 rela++; 953 } 954 } 955 956 return 0; 957} 958 959/* 960 * Hash function for symbol table lookup. Don't even think about changing 961 * this. It is specified by the System V ABI. 962 */ 963static unsigned long 964elf_hash(const char *name) 965{ 966 const unsigned char *p = (const unsigned char *) name; 967 unsigned long h = 0; 968 unsigned long g; 969 970 while (*p != '\0') { 971 h = (h << 4) + *p++; 972 if ((g = h & 0xf0000000) != 0) 973 h ^= g >> 24; 974 h &= ~g; 975 } 976 return h; 977} 978 979static int 980link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t* sym) 981{ 982 elf_file_t ef = (elf_file_t) lf; 983 unsigned long symnum; 984 const Elf_Sym* symp; 985 const char *strp; 986 unsigned long hash; 987 int i; 988 989 /* First, search hashed global symbols */ 990 hash = elf_hash(name); 991 symnum = ef->buckets[hash % ef->nbuckets]; 992 993 while (symnum != STN_UNDEF) { 994 if (symnum >= ef->nchains) { 995 printf("link_elf_lookup_symbol: corrupt symbol table\n"); 996 return ENOENT; 997 } 998 999 symp = ef->symtab + symnum; 1000 if (symp->st_name == 0) { 1001 printf("link_elf_lookup_symbol: corrupt symbol table\n"); 1002 return ENOENT; 1003 } 1004 1005 strp = ef->strtab + symp->st_name; 1006 1007 if (strcmp(name, strp) == 0) { 1008 if (symp->st_shndx != SHN_UNDEF || 1009 (symp->st_value != 0 && 1010 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) { 1011 *sym = (c_linker_sym_t) symp; 1012 return 0; 1013 } else 1014 return ENOENT; 1015 } 1016 1017 symnum = ef->chains[symnum]; 1018 } 1019 1020 /* If we have not found it, look at the full table (if loaded) */ 1021 if (ef->symtab == ef->ddbsymtab) 1022 return ENOENT; 1023 1024 /* Exhaustive search */ 1025 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 1026 strp = ef->ddbstrtab + symp->st_name; 1027 if (strcmp(name, strp) == 0) { 1028 if (symp->st_shndx != SHN_UNDEF || 1029 (symp->st_value != 0 && 1030 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) { 1031 *sym = (c_linker_sym_t) symp; 1032 return 0; 1033 } else 1034 return ENOENT; 1035 } 1036 } 1037 1038 return ENOENT; 1039} 1040 1041static int 1042link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, linker_symval_t* symval) 1043{ 1044 elf_file_t ef = (elf_file_t) lf; 1045 const Elf_Sym* es = (const Elf_Sym*) sym; 1046 1047 if (es >= ef->symtab && es < (ef->symtab + ef->nchains)) { 1048 symval->name = ef->strtab + es->st_name; 1049 symval->value = (caddr_t) ef->address + es->st_value; 1050 symval->size = es->st_size; 1051 return 0; 1052 } 1053 if (ef->symtab == ef->ddbsymtab) 1054 return ENOENT; 1055 if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) { 1056 symval->name = ef->ddbstrtab + es->st_name; 1057 symval->value = (caddr_t) ef->address + es->st_value; 1058 symval->size = es->st_size; 1059 return 0; 1060 } 1061 return ENOENT; 1062} 1063 1064static int 1065link_elf_search_symbol(linker_file_t lf, caddr_t value, 1066 c_linker_sym_t* sym, long* diffp) 1067{ 1068 elf_file_t ef = (elf_file_t) lf; 1069 u_long off = (uintptr_t) (void *) value; 1070 u_long diff = off; 1071 u_long st_value; 1072 const Elf_Sym* es; 1073 const Elf_Sym* best = 0; 1074 int i; 1075 1076 for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) { 1077 if (es->st_name == 0) 1078 continue; 1079 st_value = es->st_value + (uintptr_t) (void *) ef->address; 1080 if (off >= st_value) { 1081 if (off - st_value < diff) { 1082 diff = off - st_value; 1083 best = es; 1084 if (diff == 0) 1085 break; 1086 } else if (off - st_value == diff) { 1087 best = es; 1088 } 1089 } 1090 } 1091 if (best == 0) 1092 *diffp = off; 1093 else 1094 *diffp = diff; 1095 *sym = (c_linker_sym_t) best; 1096 1097 return 0; 1098} 1099 1100/* 1101 * Look up a linker set on an ELF system. 1102 */ 1103static int 1104link_elf_lookup_set(linker_file_t lf, const char *name, 1105 void ***startp, void ***stopp, int *countp) 1106{ 1107 c_linker_sym_t sym; 1108 linker_symval_t symval; 1109 char *setsym; 1110 void **start, **stop; 1111 int len, error = 0, count; 1112 1113 len = strlen(name) + sizeof("__start_set_"); /* sizeof includes \0 */ 1114 setsym = malloc(len, M_LINKER, M_WAITOK); 1115 if (setsym == NULL) 1116 return ENOMEM; 1117 1118 /* get address of first entry */ 1119 snprintf(setsym, len, "%s%s", "__start_set_", name); 1120 error = link_elf_lookup_symbol(lf, setsym, &sym); 1121 if (error) 1122 goto out; 1123 link_elf_symbol_values(lf, sym, &symval); 1124 if (symval.value == 0) { 1125 error = ESRCH; 1126 goto out; 1127 } 1128 start = (void **)symval.value; 1129 1130 /* get address of last entry */ 1131 snprintf(setsym, len, "%s%s", "__stop_set_", name); 1132 error = link_elf_lookup_symbol(lf, setsym, &sym); 1133 if (error) 1134 goto out; 1135 link_elf_symbol_values(lf, sym, &symval); 1136 if (symval.value == 0) { 1137 error = ESRCH; 1138 goto out; 1139 } 1140 stop = (void **)symval.value; 1141 1142 /* and the number of entries */ 1143 count = stop - start; 1144 1145 /* and copy out */ 1146 if (startp) 1147 *startp = start; 1148 if (stopp) 1149 *stopp = stop; 1150 if (countp) 1151 *countp = count; 1152 1153out: 1154 free(setsym, M_LINKER); 1155 return error; 1156} 1157 1158static int 1159link_elf_each_function_name(linker_file_t file, 1160 int (*callback)(const char *, void *), void *opaque) { 1161 elf_file_t ef = (elf_file_t)file; 1162 const Elf_Sym* symp; 1163 int i, error; 1164 1165 /* Exhaustive search */ 1166 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 1167 if (symp->st_value != 0 && 1168 ELF_ST_TYPE(symp->st_info) == STT_FUNC) { 1169 error = callback(ef->ddbstrtab + symp->st_name, opaque); 1170 if (error) 1171 return (error); 1172 } 1173 } 1174 return (0); 1175} 1176 1177#ifdef __ia64__ 1178/* 1179 * Each KLD has its own GP. The GP value for each load module is given by 1180 * DT_PLTGOT on ia64. We need GP to construct function descriptors, but 1181 * don't have direct access to the ELF file structure. The link_elf_get_gp() 1182 * function returns the GP given a pointer to a generic linker file struct. 1183 */ 1184Elf_Addr 1185link_elf_get_gp(linker_file_t lf) 1186{ 1187 elf_file_t ef = (elf_file_t)lf; 1188 return (Elf_Addr)ef->got; 1189} 1190#endif 1191 1192const Elf_Sym * 1193elf_get_sym(linker_file_t lf, Elf_Word symidx) 1194{ 1195 elf_file_t ef = (elf_file_t)lf; 1196 1197 if (symidx >= ef->nchains) 1198 return (NULL); 1199 return (ef->symtab + symidx); 1200} 1201 1202const char * 1203elf_get_symname(linker_file_t lf, Elf_Word symidx) 1204{ 1205 elf_file_t ef = (elf_file_t)lf; 1206 const Elf_Sym *sym; 1207 1208 if (symidx >= ef->nchains) 1209 return (NULL); 1210 sym = ef->symtab + symidx; 1211 return (ef->strtab + sym->st_name); 1212} 1213 1214/* 1215 * Symbol lookup function that can be used when the symbol index is known (ie 1216 * in relocations). It uses the symbol index instead of doing a fully fledged 1217 * hash table based lookup when such is valid. For example for local symbols. 1218 * This is not only more efficient, it's also more correct. It's not always 1219 * the case that the symbol can be found through the hash table. 1220 */ 1221Elf_Addr 1222elf_lookup(linker_file_t lf, Elf_Word symidx, int deps) 1223{ 1224 elf_file_t ef = (elf_file_t)lf; 1225 const Elf_Sym *sym; 1226 const char *symbol; 1227 1228 /* Don't even try to lookup the symbol if the index is bogus. */ 1229 if (symidx >= ef->nchains) 1230 return (0); 1231 1232 sym = ef->symtab + symidx; 1233 1234 /* 1235 * Don't do a full lookup when the symbol is local. It may even 1236 * fail because it may not be found through the hash table. 1237 */ 1238 if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) { 1239 /* Force lookup failure when we have an insanity. */ 1240 if (sym->st_shndx == SHN_UNDEF || sym->st_value == 0) 1241 return (0); 1242 return ((Elf_Addr)ef->address + sym->st_value); 1243 } 1244 1245 /* 1246 * XXX we can avoid doing a hash table based lookup for global 1247 * symbols as well. This however is not always valid, so we'll 1248 * just do it the hard way for now. Performance tweaks can 1249 * always be added. 1250 */ 1251 1252 symbol = ef->strtab + sym->st_name; 1253 1254 /* Force a lookup failure if the symbol name is bogus. */ 1255 if (*symbol == 0) 1256 return (0); 1257 1258 return ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps)); 1259}
| 568 569 /* 570 * Read the elf header from the file. 571 */ 572 firstpage = malloc(PAGE_SIZE, M_LINKER, M_WAITOK); 573 if (firstpage == NULL) { 574 error = ENOMEM; 575 goto out; 576 } 577 hdr = (Elf_Ehdr *)firstpage; 578 error = vn_rdwr(UIO_READ, nd.ni_vp, firstpage, PAGE_SIZE, 0, 579 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 580 &resid, td); 581 nbytes = PAGE_SIZE - resid; 582 if (error) 583 goto out; 584 585 if (!IS_ELF(*hdr)) { 586 error = ENOEXEC; 587 goto out; 588 } 589 590 if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS 591 || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) { 592 link_elf_error("Unsupported file layout"); 593 error = ENOEXEC; 594 goto out; 595 } 596 if (hdr->e_ident[EI_VERSION] != EV_CURRENT 597 || hdr->e_version != EV_CURRENT) { 598 link_elf_error("Unsupported file version"); 599 error = ENOEXEC; 600 goto out; 601 } 602 if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) { 603 link_elf_error("Unsupported file type"); 604 error = ENOEXEC; 605 goto out; 606 } 607 if (hdr->e_machine != ELF_TARG_MACH) { 608 link_elf_error("Unsupported machine"); 609 error = ENOEXEC; 610 goto out; 611 } 612 613 /* 614 * We rely on the program header being in the first page. This is 615 * not strictly required by the ABI specification, but it seems to 616 * always true in practice. And, it simplifies things considerably. 617 */ 618 if (!((hdr->e_phentsize == sizeof(Elf_Phdr)) && 619 (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE) && 620 (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= nbytes))) 621 link_elf_error("Unreadable program headers"); 622 623 /* 624 * Scan the program header entries, and save key information. 625 * 626 * We rely on there being exactly two load segments, text and data, 627 * in that order. 628 */ 629 phdr = (Elf_Phdr *) (firstpage + hdr->e_phoff); 630 phlimit = phdr + hdr->e_phnum; 631 nsegs = 0; 632 phdyn = NULL; 633 phphdr = NULL; 634 while (phdr < phlimit) { 635 switch (phdr->p_type) { 636 637 case PT_LOAD: 638 if (nsegs == 2) { 639 link_elf_error("Too many sections"); 640 error = ENOEXEC; 641 goto out; 642 } 643 segs[nsegs] = phdr; 644 ++nsegs; 645 break; 646 647 case PT_PHDR: 648 phphdr = phdr; 649 break; 650 651 case PT_DYNAMIC: 652 phdyn = phdr; 653 break; 654 655 case PT_INTERP: 656 link_elf_error("Unsupported file type"); 657 error = ENOEXEC; 658 goto out; 659 } 660 661 ++phdr; 662 } 663 if (phdyn == NULL) { 664 link_elf_error("Object is not dynamically-linked"); 665 error = ENOEXEC; 666 goto out; 667 } 668 669 /* 670 * Allocate the entire address space of the object, to stake out our 671 * contiguous region, and to establish the base address for relocation. 672 */ 673 base_offset = trunc_page(segs[0]->p_offset); 674 base_vaddr = trunc_page(segs[0]->p_vaddr); 675 base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz); 676 mapsize = base_vlimit - base_vaddr; 677 678 lf = linker_make_file(filename, &link_elf_class); 679 if (!lf) { 680 error = ENOMEM; 681 goto out; 682 } 683 684 ef = (elf_file_t) lf; 685#ifdef SPARSE_MAPPING 686 ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT); 687 if (ef->object == NULL) { 688 error = ENOMEM; 689 goto out; 690 } 691 vm_object_reference(ef->object); 692 ef->address = (caddr_t) vm_map_min(kernel_map); 693 error = vm_map_find(kernel_map, ef->object, 0, 694 (vm_offset_t *) &ef->address, 695 mapsize, 1, 696 VM_PROT_ALL, VM_PROT_ALL, 0); 697 if (error) { 698 vm_object_deallocate(ef->object); 699 ef->object = 0; 700 goto out; 701 } 702#else 703 ef->address = malloc(mapsize, M_LINKER, M_WAITOK); 704 if (!ef->address) { 705 error = ENOMEM; 706 goto out; 707 } 708#endif 709 mapbase = ef->address; 710 711 /* 712 * Read the text and data sections and zero the bss. 713 */ 714 for (i = 0; i < 2; i++) { 715 caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr; 716 error = vn_rdwr(UIO_READ, nd.ni_vp, 717 segbase, segs[i]->p_filesz, segs[i]->p_offset, 718 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 719 &resid, td); 720 if (error) { 721 goto out; 722 } 723 bzero(segbase + segs[i]->p_filesz, 724 segs[i]->p_memsz - segs[i]->p_filesz); 725 726#ifdef SPARSE_MAPPING 727 /* 728 * Wire down the pages 729 */ 730 vm_map_wire(kernel_map, 731 (vm_offset_t) segbase, 732 (vm_offset_t) segbase + segs[i]->p_memsz, 733 FALSE); 734#endif 735 } 736 737#ifdef GPROF 738 /* Update profiling information with the new text segment. */ 739 kmupetext((uintfptr_t)(mapbase + segs[0]->p_vaddr - base_vaddr + 740 segs[0]->p_memsz)); 741#endif 742 743 ef->dynamic = (Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr); 744 745 lf->address = ef->address; 746 lf->size = mapsize; 747 748 error = parse_dynamic(ef); 749 if (error) 750 goto out; 751 error = linker_load_dependencies(lf); 752 if (error) 753 goto out; 754#if 0 /* this will be more trouble than it's worth for now */ 755 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) { 756 if (dp->d_tag != DT_NEEDED) 757 continue; 758 modname = ef->strtab + dp->d_un.d_val; 759 error = linker_load_module(modname, lf); 760 if (error) 761 goto out; 762 } 763#endif 764 error = relocate_file(ef); 765 if (error) 766 goto out; 767 768 /* Try and load the symbol table if it's present. (you can strip it!) */ 769 nbytes = hdr->e_shnum * hdr->e_shentsize; 770 if (nbytes == 0 || hdr->e_shoff == 0) 771 goto nosyms; 772 shdr = malloc(nbytes, M_LINKER, M_WAITOK | M_ZERO); 773 if (shdr == NULL) { 774 error = ENOMEM; 775 goto out; 776 } 777 error = vn_rdwr(UIO_READ, nd.ni_vp, 778 (caddr_t)shdr, nbytes, hdr->e_shoff, 779 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 780 &resid, td); 781 if (error) 782 goto out; 783 symtabindex = -1; 784 symstrindex = -1; 785 for (i = 0; i < hdr->e_shnum; i++) { 786 if (shdr[i].sh_type == SHT_SYMTAB) { 787 symtabindex = i; 788 symstrindex = shdr[i].sh_link; 789 } 790 } 791 if (symtabindex < 0 || symstrindex < 0) 792 goto nosyms; 793 794 symcnt = shdr[symtabindex].sh_size; 795 ef->symbase = malloc(symcnt, M_LINKER, M_WAITOK); 796 strcnt = shdr[symstrindex].sh_size; 797 ef->strbase = malloc(strcnt, M_LINKER, M_WAITOK); 798 799 if (ef->symbase == NULL || ef->strbase == NULL) { 800 error = ENOMEM; 801 goto out; 802 } 803 error = vn_rdwr(UIO_READ, nd.ni_vp, 804 ef->symbase, symcnt, shdr[symtabindex].sh_offset, 805 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 806 &resid, td); 807 if (error) 808 goto out; 809 error = vn_rdwr(UIO_READ, nd.ni_vp, 810 ef->strbase, strcnt, shdr[symstrindex].sh_offset, 811 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 812 &resid, td); 813 if (error) 814 goto out; 815 816 ef->ddbsymcnt = symcnt / sizeof(Elf_Sym); 817 ef->ddbsymtab = (const Elf_Sym *)ef->symbase; 818 ef->ddbstrcnt = strcnt; 819 ef->ddbstrtab = ef->strbase; 820 821 error = link_elf_link_common_finish(lf); 822 if (error) 823 goto out; 824 825nosyms: 826 827 *result = lf; 828 829out: 830 if (error && lf) 831 linker_file_unload(lf); 832 if (shdr) 833 free(shdr, M_LINKER); 834 if (firstpage) 835 free(firstpage, M_LINKER); 836 VOP_UNLOCK(nd.ni_vp, 0, td); 837 vn_close(nd.ni_vp, FREAD, td->td_ucred, td); 838 839 return error; 840} 841 842static void 843link_elf_unload_file(linker_file_t file) 844{ 845 elf_file_t ef = (elf_file_t) file; 846 847#ifdef DDB 848 if (ef->gdb.l_ld) { 849 GDB_STATE(RT_DELETE); 850 free((void *)(uintptr_t)ef->gdb.l_name, M_LINKER); 851 link_elf_delete_gdb(&ef->gdb); 852 GDB_STATE(RT_CONSISTENT); 853 } 854#endif 855 856 /* Notify MD code that a module is being unloaded. */ 857 elf_cpu_unload_file(file); 858 859 if (ef->preloaded) { 860 link_elf_unload_preload(file); 861 return; 862 } 863 864#ifdef SPARSE_MAPPING 865 if (ef->object) { 866 vm_map_remove(kernel_map, (vm_offset_t) ef->address, 867 (vm_offset_t) ef->address 868 + (ef->object->size << PAGE_SHIFT)); 869 vm_object_deallocate(ef->object); 870 } 871#else 872 if (ef->address) 873 free(ef->address, M_LINKER); 874#endif 875 if (ef->symbase) 876 free(ef->symbase, M_LINKER); 877 if (ef->strbase) 878 free(ef->strbase, M_LINKER); 879} 880 881static void 882link_elf_unload_preload(linker_file_t file) 883{ 884 if (file->filename) 885 preload_delete_name(file->filename); 886} 887 888static const char * 889symbol_name(elf_file_t ef, Elf_Word r_info) 890{ 891 const Elf_Sym *ref; 892 893 if (ELF_R_SYM(r_info)) { 894 ref = ef->symtab + ELF_R_SYM(r_info); 895 return ef->strtab + ref->st_name; 896 } else 897 return NULL; 898} 899 900static int 901relocate_file(elf_file_t ef) 902{ 903 const Elf_Rel *rellim; 904 const Elf_Rel *rel; 905 const Elf_Rela *relalim; 906 const Elf_Rela *rela; 907 const char *symname; 908 909 /* Perform relocations without addend if there are any: */ 910 rel = ef->rel; 911 if (rel) { 912 rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize); 913 while (rel < rellim) { 914 if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) { 915 symname = symbol_name(ef, rel->r_info); 916 printf("link_elf: symbol %s undefined\n", symname); 917 return ENOENT; 918 } 919 rel++; 920 } 921 } 922 923 /* Perform relocations with addend if there are any: */ 924 rela = ef->rela; 925 if (rela) { 926 relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize); 927 while (rela < relalim) { 928 if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) { 929 symname = symbol_name(ef, rela->r_info); 930 printf("link_elf: symbol %s undefined\n", symname); 931 return ENOENT; 932 } 933 rela++; 934 } 935 } 936 937 /* Perform PLT relocations without addend if there are any: */ 938 rel = ef->pltrel; 939 if (rel) { 940 rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize); 941 while (rel < rellim) { 942 if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) { 943 symname = symbol_name(ef, rel->r_info); 944 printf("link_elf: symbol %s undefined\n", symname); 945 return ENOENT; 946 } 947 rel++; 948 } 949 } 950 951 /* Perform relocations with addend if there are any: */ 952 rela = ef->pltrela; 953 if (rela) { 954 relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize); 955 while (rela < relalim) { 956 if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) { 957 symname = symbol_name(ef, rela->r_info); 958 printf("link_elf: symbol %s undefined\n", symname); 959 return ENOENT; 960 } 961 rela++; 962 } 963 } 964 965 return 0; 966} 967 968/* 969 * Hash function for symbol table lookup. Don't even think about changing 970 * this. It is specified by the System V ABI. 971 */ 972static unsigned long 973elf_hash(const char *name) 974{ 975 const unsigned char *p = (const unsigned char *) name; 976 unsigned long h = 0; 977 unsigned long g; 978 979 while (*p != '\0') { 980 h = (h << 4) + *p++; 981 if ((g = h & 0xf0000000) != 0) 982 h ^= g >> 24; 983 h &= ~g; 984 } 985 return h; 986} 987 988static int 989link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t* sym) 990{ 991 elf_file_t ef = (elf_file_t) lf; 992 unsigned long symnum; 993 const Elf_Sym* symp; 994 const char *strp; 995 unsigned long hash; 996 int i; 997 998 /* First, search hashed global symbols */ 999 hash = elf_hash(name); 1000 symnum = ef->buckets[hash % ef->nbuckets]; 1001 1002 while (symnum != STN_UNDEF) { 1003 if (symnum >= ef->nchains) { 1004 printf("link_elf_lookup_symbol: corrupt symbol table\n"); 1005 return ENOENT; 1006 } 1007 1008 symp = ef->symtab + symnum; 1009 if (symp->st_name == 0) { 1010 printf("link_elf_lookup_symbol: corrupt symbol table\n"); 1011 return ENOENT; 1012 } 1013 1014 strp = ef->strtab + symp->st_name; 1015 1016 if (strcmp(name, strp) == 0) { 1017 if (symp->st_shndx != SHN_UNDEF || 1018 (symp->st_value != 0 && 1019 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) { 1020 *sym = (c_linker_sym_t) symp; 1021 return 0; 1022 } else 1023 return ENOENT; 1024 } 1025 1026 symnum = ef->chains[symnum]; 1027 } 1028 1029 /* If we have not found it, look at the full table (if loaded) */ 1030 if (ef->symtab == ef->ddbsymtab) 1031 return ENOENT; 1032 1033 /* Exhaustive search */ 1034 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 1035 strp = ef->ddbstrtab + symp->st_name; 1036 if (strcmp(name, strp) == 0) { 1037 if (symp->st_shndx != SHN_UNDEF || 1038 (symp->st_value != 0 && 1039 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) { 1040 *sym = (c_linker_sym_t) symp; 1041 return 0; 1042 } else 1043 return ENOENT; 1044 } 1045 } 1046 1047 return ENOENT; 1048} 1049 1050static int 1051link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, linker_symval_t* symval) 1052{ 1053 elf_file_t ef = (elf_file_t) lf; 1054 const Elf_Sym* es = (const Elf_Sym*) sym; 1055 1056 if (es >= ef->symtab && es < (ef->symtab + ef->nchains)) { 1057 symval->name = ef->strtab + es->st_name; 1058 symval->value = (caddr_t) ef->address + es->st_value; 1059 symval->size = es->st_size; 1060 return 0; 1061 } 1062 if (ef->symtab == ef->ddbsymtab) 1063 return ENOENT; 1064 if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) { 1065 symval->name = ef->ddbstrtab + es->st_name; 1066 symval->value = (caddr_t) ef->address + es->st_value; 1067 symval->size = es->st_size; 1068 return 0; 1069 } 1070 return ENOENT; 1071} 1072 1073static int 1074link_elf_search_symbol(linker_file_t lf, caddr_t value, 1075 c_linker_sym_t* sym, long* diffp) 1076{ 1077 elf_file_t ef = (elf_file_t) lf; 1078 u_long off = (uintptr_t) (void *) value; 1079 u_long diff = off; 1080 u_long st_value; 1081 const Elf_Sym* es; 1082 const Elf_Sym* best = 0; 1083 int i; 1084 1085 for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) { 1086 if (es->st_name == 0) 1087 continue; 1088 st_value = es->st_value + (uintptr_t) (void *) ef->address; 1089 if (off >= st_value) { 1090 if (off - st_value < diff) { 1091 diff = off - st_value; 1092 best = es; 1093 if (diff == 0) 1094 break; 1095 } else if (off - st_value == diff) { 1096 best = es; 1097 } 1098 } 1099 } 1100 if (best == 0) 1101 *diffp = off; 1102 else 1103 *diffp = diff; 1104 *sym = (c_linker_sym_t) best; 1105 1106 return 0; 1107} 1108 1109/* 1110 * Look up a linker set on an ELF system. 1111 */ 1112static int 1113link_elf_lookup_set(linker_file_t lf, const char *name, 1114 void ***startp, void ***stopp, int *countp) 1115{ 1116 c_linker_sym_t sym; 1117 linker_symval_t symval; 1118 char *setsym; 1119 void **start, **stop; 1120 int len, error = 0, count; 1121 1122 len = strlen(name) + sizeof("__start_set_"); /* sizeof includes \0 */ 1123 setsym = malloc(len, M_LINKER, M_WAITOK); 1124 if (setsym == NULL) 1125 return ENOMEM; 1126 1127 /* get address of first entry */ 1128 snprintf(setsym, len, "%s%s", "__start_set_", name); 1129 error = link_elf_lookup_symbol(lf, setsym, &sym); 1130 if (error) 1131 goto out; 1132 link_elf_symbol_values(lf, sym, &symval); 1133 if (symval.value == 0) { 1134 error = ESRCH; 1135 goto out; 1136 } 1137 start = (void **)symval.value; 1138 1139 /* get address of last entry */ 1140 snprintf(setsym, len, "%s%s", "__stop_set_", name); 1141 error = link_elf_lookup_symbol(lf, setsym, &sym); 1142 if (error) 1143 goto out; 1144 link_elf_symbol_values(lf, sym, &symval); 1145 if (symval.value == 0) { 1146 error = ESRCH; 1147 goto out; 1148 } 1149 stop = (void **)symval.value; 1150 1151 /* and the number of entries */ 1152 count = stop - start; 1153 1154 /* and copy out */ 1155 if (startp) 1156 *startp = start; 1157 if (stopp) 1158 *stopp = stop; 1159 if (countp) 1160 *countp = count; 1161 1162out: 1163 free(setsym, M_LINKER); 1164 return error; 1165} 1166 1167static int 1168link_elf_each_function_name(linker_file_t file, 1169 int (*callback)(const char *, void *), void *opaque) { 1170 elf_file_t ef = (elf_file_t)file; 1171 const Elf_Sym* symp; 1172 int i, error; 1173 1174 /* Exhaustive search */ 1175 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 1176 if (symp->st_value != 0 && 1177 ELF_ST_TYPE(symp->st_info) == STT_FUNC) { 1178 error = callback(ef->ddbstrtab + symp->st_name, opaque); 1179 if (error) 1180 return (error); 1181 } 1182 } 1183 return (0); 1184} 1185 1186#ifdef __ia64__ 1187/* 1188 * Each KLD has its own GP. The GP value for each load module is given by 1189 * DT_PLTGOT on ia64. We need GP to construct function descriptors, but 1190 * don't have direct access to the ELF file structure. The link_elf_get_gp() 1191 * function returns the GP given a pointer to a generic linker file struct. 1192 */ 1193Elf_Addr 1194link_elf_get_gp(linker_file_t lf) 1195{ 1196 elf_file_t ef = (elf_file_t)lf; 1197 return (Elf_Addr)ef->got; 1198} 1199#endif 1200 1201const Elf_Sym * 1202elf_get_sym(linker_file_t lf, Elf_Word symidx) 1203{ 1204 elf_file_t ef = (elf_file_t)lf; 1205 1206 if (symidx >= ef->nchains) 1207 return (NULL); 1208 return (ef->symtab + symidx); 1209} 1210 1211const char * 1212elf_get_symname(linker_file_t lf, Elf_Word symidx) 1213{ 1214 elf_file_t ef = (elf_file_t)lf; 1215 const Elf_Sym *sym; 1216 1217 if (symidx >= ef->nchains) 1218 return (NULL); 1219 sym = ef->symtab + symidx; 1220 return (ef->strtab + sym->st_name); 1221} 1222 1223/* 1224 * Symbol lookup function that can be used when the symbol index is known (ie 1225 * in relocations). It uses the symbol index instead of doing a fully fledged 1226 * hash table based lookup when such is valid. For example for local symbols. 1227 * This is not only more efficient, it's also more correct. It's not always 1228 * the case that the symbol can be found through the hash table. 1229 */ 1230Elf_Addr 1231elf_lookup(linker_file_t lf, Elf_Word symidx, int deps) 1232{ 1233 elf_file_t ef = (elf_file_t)lf; 1234 const Elf_Sym *sym; 1235 const char *symbol; 1236 1237 /* Don't even try to lookup the symbol if the index is bogus. */ 1238 if (symidx >= ef->nchains) 1239 return (0); 1240 1241 sym = ef->symtab + symidx; 1242 1243 /* 1244 * Don't do a full lookup when the symbol is local. It may even 1245 * fail because it may not be found through the hash table. 1246 */ 1247 if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) { 1248 /* Force lookup failure when we have an insanity. */ 1249 if (sym->st_shndx == SHN_UNDEF || sym->st_value == 0) 1250 return (0); 1251 return ((Elf_Addr)ef->address + sym->st_value); 1252 } 1253 1254 /* 1255 * XXX we can avoid doing a hash table based lookup for global 1256 * symbols as well. This however is not always valid, so we'll 1257 * just do it the hard way for now. Performance tweaks can 1258 * always be added. 1259 */ 1260 1261 symbol = ef->strtab + sym->st_name; 1262 1263 /* Force a lookup failure if the symbol name is bogus. */ 1264 if (*symbol == 0) 1265 return (0); 1266 1267 return ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps)); 1268}
|