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