1 /*- 2 * Copyright (c) 1998-2000 Doug Rabson 3 * Copyright (c) 2004 Peter Wemm 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include "opt_ddb.h" 32 #include "opt_mac.h" 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/lock.h> 38 #include <sys/mac.h> 39 #include <sys/malloc.h> 40 #include <sys/mutex.h> 41 #include <sys/proc.h> 42 #include <sys/namei.h> 43 #include <sys/fcntl.h> 44 #include <sys/vnode.h> 45 #include <sys/linker.h> 46 47 #include <machine/elf.h> 48 49 #include <vm/vm.h> 50 #include <vm/vm_param.h> 51 #include <vm/vm_object.h> 52 #include <vm/vm_kern.h> 53 #include <vm/vm_extern.h> 54 #include <vm/pmap.h> 55 #include <vm/vm_map.h> 56 57 #include <sys/link_elf.h> 58 59 #include "linker_if.h" 60 61 typedef struct { 62 void *addr; 63 Elf_Off size; 64 int flags; 65 int sec; /* Original section */ 66 char *name; 67 } Elf_progent; 68 69 typedef struct { 70 Elf_Rel *rel; 71 int nrel; 72 int sec; 73 } Elf_relent; 74 75 typedef struct { 76 Elf_Rela *rela; 77 int nrela; 78 int sec; 79 } Elf_relaent; 80 81 82 typedef struct elf_file { 83 struct linker_file lf; /* Common fields */ 84 85 caddr_t address; /* Relocation address */ 86 vm_object_t object; /* VM object to hold file pages */ 87 Elf_Shdr *e_shdr; 88 89 Elf_progent *progtab; 90 int nprogtab; 91 92 Elf_relaent *relatab; 93 int nrela; 94 95 Elf_relent *reltab; 96 int nrel; 97 98 Elf_Sym *ddbsymtab; /* The symbol table we are using */ 99 long ddbsymcnt; /* Number of symbols */ 100 caddr_t ddbstrtab; /* String table */ 101 long ddbstrcnt; /* number of bytes in string table */ 102 103 caddr_t shstrtab; /* Section name string table */ 104 long shstrcnt; /* number of bytes in string table */ 105 106 } *elf_file_t; 107 108 static int link_elf_link_preload(linker_class_t cls, 109 const char *, linker_file_t *); 110 static int link_elf_link_preload_finish(linker_file_t); 111 static int link_elf_load_file(linker_class_t, const char *, linker_file_t *); 112 static int link_elf_lookup_symbol(linker_file_t, const char *, 113 c_linker_sym_t *); 114 static int link_elf_symbol_values(linker_file_t, c_linker_sym_t, 115 linker_symval_t *); 116 static int link_elf_search_symbol(linker_file_t, caddr_t value, 117 c_linker_sym_t *sym, long *diffp); 118 119 static void link_elf_unload_file(linker_file_t); 120 static int link_elf_lookup_set(linker_file_t, const char *, 121 void ***, void ***, int *); 122 static int link_elf_each_function_name(linker_file_t, 123 int (*)(const char *, void *), void *); 124 static void link_elf_reloc_local(linker_file_t); 125 126 static Elf_Addr elf_obj_lookup(linker_file_t lf, Elf_Word symidx, int deps); 127 128 static kobj_method_t link_elf_methods[] = { 129 KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol), 130 KOBJMETHOD(linker_symbol_values, link_elf_symbol_values), 131 KOBJMETHOD(linker_search_symbol, link_elf_search_symbol), 132 KOBJMETHOD(linker_unload, link_elf_unload_file), 133 KOBJMETHOD(linker_load_file, link_elf_load_file), 134 KOBJMETHOD(linker_link_preload, link_elf_link_preload), 135 KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish), 136 KOBJMETHOD(linker_lookup_set, link_elf_lookup_set), 137 KOBJMETHOD(linker_each_function_name, link_elf_each_function_name), 138 { 0, 0 } 139 }; 140 141 static struct linker_class link_elf_class = { 142 #if ELF_TARG_CLASS == ELFCLASS32 143 "elf32_obj", 144 #else 145 "elf64_obj", 146 #endif 147 link_elf_methods, sizeof(struct elf_file) 148 }; 149 150 static int relocate_file(elf_file_t ef); 151 152 static void 153 link_elf_error(const char *s) 154 { 155 printf("kldload: %s\n", s); 156 } 157 158 static void 159 link_elf_init(void *arg) 160 { 161 162 linker_add_class(&link_elf_class); 163 } 164 165 SYSINIT(link_elf_obj, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0); 166 167 static int 168 link_elf_link_preload(linker_class_t cls, const char *filename, 169 linker_file_t *result) 170 { 171 /* preload not done this way */ 172 return (EFTYPE); 173 } 174 175 static int 176 link_elf_link_preload_finish(linker_file_t lf) 177 { 178 /* preload not done this way */ 179 return (EFTYPE); 180 } 181 182 static int 183 link_elf_load_file(linker_class_t cls, const char *filename, 184 linker_file_t *result) 185 { 186 struct nameidata nd; 187 struct thread *td = curthread; /* XXX */ 188 Elf_Ehdr *hdr; 189 Elf_Shdr *shdr; 190 Elf_Sym *es; 191 int nbytes, i, j; 192 vm_offset_t mapbase; 193 size_t mapsize; 194 int error = 0; 195 int resid, flags; 196 elf_file_t ef; 197 linker_file_t lf; 198 int symtabindex; 199 int symstrindex; 200 int shstrindex; 201 int nsym; 202 int pb, rl, ra; 203 int alignmask; 204 205 GIANT_REQUIRED; 206 207 shdr = NULL; 208 lf = NULL; 209 mapsize = 0; 210 hdr = NULL; 211 212 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td); 213 flags = FREAD; 214 error = vn_open(&nd, &flags, 0, -1); 215 if (error) 216 return error; 217 NDFREE(&nd, NDF_ONLY_PNBUF); 218 #ifdef MAC 219 error = mac_check_kld_load(td->td_ucred, nd.ni_vp); 220 if (error) { 221 goto out; 222 } 223 #endif 224 225 /* Read the elf header from the file. */ 226 hdr = malloc(sizeof(*hdr), M_LINKER, M_WAITOK); 227 if (hdr == NULL) { 228 error = ENOMEM; 229 goto out; 230 } 231 error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)hdr, sizeof(*hdr), 0, 232 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 233 &resid, td); 234 if (error) 235 goto out; 236 if (resid != 0){ 237 error = ENOEXEC; 238 goto out; 239 } 240 241 if (!IS_ELF(*hdr)) { 242 error = ENOEXEC; 243 goto out; 244 } 245 246 if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS 247 || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) { 248 link_elf_error("Unsupported file layout"); 249 error = ENOEXEC; 250 goto out; 251 } 252 if (hdr->e_ident[EI_VERSION] != EV_CURRENT 253 || hdr->e_version != EV_CURRENT) { 254 link_elf_error("Unsupported file version"); 255 error = ENOEXEC; 256 goto out; 257 } 258 if (hdr->e_type != ET_REL) { 259 link_elf_error("Unsupported file type"); 260 error = ENOEXEC; 261 goto out; 262 } 263 if (hdr->e_machine != ELF_TARG_MACH) { 264 link_elf_error("Unsupported machine"); 265 error = ENOEXEC; 266 goto out; 267 } 268 269 lf = linker_make_file(filename, &link_elf_class); 270 if (!lf) { 271 error = ENOMEM; 272 goto out; 273 } 274 ef = (elf_file_t) lf; 275 ef->nprogtab = 0; 276 ef->e_shdr = 0; 277 ef->nrel = 0; 278 ef->nrela = 0; 279 280 /* Allocate and read in the section header */ 281 nbytes = hdr->e_shnum * hdr->e_shentsize; 282 if (nbytes == 0 || hdr->e_shoff == 0 || 283 hdr->e_shentsize != sizeof(Elf_Shdr)) { 284 error = ENOEXEC; 285 goto out; 286 } 287 shdr = malloc(nbytes, M_LINKER, M_WAITOK); 288 if (shdr == NULL) { 289 error = ENOMEM; 290 goto out; 291 } 292 ef->e_shdr = shdr; 293 error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)shdr, nbytes, hdr->e_shoff, 294 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td); 295 if (error) 296 goto out; 297 if (resid) { 298 error = ENOEXEC; 299 goto out; 300 } 301 302 /* Scan the section header for information and table sizing. */ 303 nsym = 0; 304 symtabindex = -1; 305 symstrindex = -1; 306 for (i = 0; i < hdr->e_shnum; i++) { 307 switch (shdr[i].sh_type) { 308 case SHT_PROGBITS: 309 case SHT_NOBITS: 310 ef->nprogtab++; 311 break; 312 case SHT_SYMTAB: 313 nsym++; 314 symtabindex = i; 315 symstrindex = shdr[i].sh_link; 316 break; 317 case SHT_REL: 318 ef->nrel++; 319 break; 320 case SHT_RELA: 321 ef->nrela++; 322 break; 323 case SHT_STRTAB: 324 break; 325 } 326 } 327 if (ef->nprogtab == 0) { 328 link_elf_error("file has no contents"); 329 error = ENOEXEC; 330 goto out; 331 } 332 if (nsym != 1) { 333 /* Only allow one symbol table for now */ 334 link_elf_error("file has no valid symbol table"); 335 error = ENOEXEC; 336 goto out; 337 } 338 if (symstrindex < 0 || symstrindex > hdr->e_shnum || 339 shdr[symstrindex].sh_type != SHT_STRTAB) { 340 link_elf_error("file has invalid symbol strings"); 341 error = ENOEXEC; 342 goto out; 343 } 344 345 /* Allocate space for tracking the load chunks */ 346 if (ef->nprogtab != 0) 347 ef->progtab = malloc(ef->nprogtab * sizeof(*ef->progtab), 348 M_LINKER, M_WAITOK | M_ZERO); 349 if (ef->nrel != 0) 350 ef->reltab = malloc(ef->nrel * sizeof(*ef->reltab), M_LINKER, 351 M_WAITOK | M_ZERO); 352 if (ef->nrela != 0) 353 ef->relatab = malloc(ef->nrela * sizeof(*ef->relatab), M_LINKER, 354 M_WAITOK | M_ZERO); 355 if ((ef->nprogtab != 0 && ef->progtab == NULL) || 356 (ef->nrel != 0 && ef->reltab == NULL) || 357 (ef->nrela != 0 && ef->relatab == NULL)) { 358 error = ENOMEM; 359 goto out; 360 } 361 362 if (symtabindex == -1) 363 panic("lost symbol table index"); 364 /* Allocate space for and load the symbol table */ 365 ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym); 366 ef->ddbsymtab = malloc(shdr[symtabindex].sh_size, M_LINKER, M_WAITOK); 367 if (ef->ddbsymtab == NULL) { 368 error = ENOMEM; 369 goto out; 370 } 371 error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)ef->ddbsymtab, 372 shdr[symtabindex].sh_size, shdr[symtabindex].sh_offset, 373 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 374 &resid, td); 375 if (error) 376 goto out; 377 if (resid != 0){ 378 error = EINVAL; 379 goto out; 380 } 381 382 if (symstrindex == -1) 383 panic("lost symbol string index"); 384 /* Allocate space for and load the symbol strings */ 385 ef->ddbstrcnt = shdr[symstrindex].sh_size; 386 ef->ddbstrtab = malloc(shdr[symstrindex].sh_size, M_LINKER, M_WAITOK); 387 if (ef->ddbstrtab == NULL) { 388 error = ENOMEM; 389 goto out; 390 } 391 error = vn_rdwr(UIO_READ, nd.ni_vp, ef->ddbstrtab, 392 shdr[symstrindex].sh_size, shdr[symstrindex].sh_offset, 393 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 394 &resid, td); 395 if (error) 396 goto out; 397 if (resid != 0){ 398 error = EINVAL; 399 goto out; 400 } 401 402 /* Do we have a string table for the section names? */ 403 shstrindex = -1; 404 if (hdr->e_shstrndx != 0 && 405 shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) { 406 shstrindex = hdr->e_shstrndx; 407 ef->shstrcnt = shdr[shstrindex].sh_size; 408 ef->shstrtab = malloc(shdr[shstrindex].sh_size, M_LINKER, 409 M_WAITOK); 410 if (ef->shstrtab == NULL) { 411 error = ENOMEM; 412 goto out; 413 } 414 error = vn_rdwr(UIO_READ, nd.ni_vp, ef->shstrtab, 415 shdr[shstrindex].sh_size, shdr[shstrindex].sh_offset, 416 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 417 &resid, td); 418 if (error) 419 goto out; 420 if (resid != 0){ 421 error = EINVAL; 422 goto out; 423 } 424 } 425 426 /* Size up code/data(progbits) and bss(nobits). */ 427 alignmask = 0; 428 for (i = 0; i < hdr->e_shnum; i++) { 429 switch (shdr[i].sh_type) { 430 case SHT_PROGBITS: 431 case SHT_NOBITS: 432 alignmask = shdr[i].sh_addralign - 1; 433 mapsize += alignmask; 434 mapsize &= ~alignmask; 435 mapsize += shdr[i].sh_size; 436 break; 437 } 438 } 439 440 /* 441 * We know how much space we need for the text/data/bss/etc. 442 * This stuff needs to be in a single chunk so that profiling etc 443 * can get the bounds and gdb can associate offsets with modules 444 */ 445 ef->object = vm_object_allocate(OBJT_DEFAULT, 446 round_page(mapsize) >> PAGE_SHIFT); 447 if (ef->object == NULL) { 448 error = ENOMEM; 449 goto out; 450 } 451 vm_object_reference(ef->object); 452 ef->address = (caddr_t) vm_map_min(kernel_map); 453 error = vm_map_find(kernel_map, ef->object, 0, &mapbase, 454 round_page(mapsize), TRUE, VM_PROT_ALL, VM_PROT_ALL, FALSE); 455 if (error) { 456 vm_object_deallocate(ef->object); 457 ef->object = 0; 458 goto out; 459 } 460 461 /* Wire the pages */ 462 vm_map_wire(kernel_map, mapbase, 463 mapbase + round_page(mapsize), 464 VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES); 465 466 /* Inform the kld system about the situation */ 467 lf->address = ef->address = (caddr_t)mapbase; 468 lf->size = mapsize; 469 470 /* 471 * Now load code/data(progbits), zero bss(nobits), allocate space for 472 * and load relocs 473 */ 474 pb = 0; 475 rl = 0; 476 ra = 0; 477 alignmask = 0; 478 for (i = 0; i < hdr->e_shnum; i++) { 479 switch (shdr[i].sh_type) { 480 case SHT_PROGBITS: 481 case SHT_NOBITS: 482 alignmask = shdr[i].sh_addralign - 1; 483 mapbase += alignmask; 484 mapbase &= ~alignmask; 485 ef->progtab[pb].addr = (void *)(uintptr_t)mapbase; 486 if (shdr[i].sh_type == SHT_PROGBITS) { 487 ef->progtab[pb].name = "<<PROGBITS>>"; 488 error = vn_rdwr(UIO_READ, nd.ni_vp, 489 ef->progtab[pb].addr, 490 shdr[i].sh_size, shdr[i].sh_offset, 491 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, 492 NOCRED, &resid, td); 493 if (error) 494 goto out; 495 if (resid != 0){ 496 error = EINVAL; 497 goto out; 498 } 499 } else { 500 ef->progtab[pb].name = "<<NOBITS>>"; 501 bzero(ef->progtab[pb].addr, shdr[i].sh_size); 502 } 503 ef->progtab[pb].size = shdr[i].sh_size; 504 ef->progtab[pb].sec = i; 505 if (ef->shstrtab && shdr[i].sh_name != 0) 506 ef->progtab[pb].name = 507 ef->shstrtab + shdr[i].sh_name; 508 509 /* Update all symbol values with the offset. */ 510 for (j = 0; j < ef->ddbsymcnt; j++) { 511 es = &ef->ddbsymtab[j]; 512 if (es->st_shndx != i) 513 continue; 514 es->st_value += (Elf_Addr)ef->progtab[pb].addr; 515 } 516 mapbase += shdr[i].sh_size; 517 pb++; 518 break; 519 case SHT_REL: 520 ef->reltab[rl].rel = malloc(shdr[i].sh_size, M_LINKER, 521 M_WAITOK); 522 ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel); 523 ef->reltab[rl].sec = shdr[i].sh_info; 524 error = vn_rdwr(UIO_READ, nd.ni_vp, 525 (void *)ef->reltab[rl].rel, 526 shdr[i].sh_size, shdr[i].sh_offset, 527 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 528 &resid, td); 529 if (error) 530 goto out; 531 if (resid != 0){ 532 error = EINVAL; 533 goto out; 534 } 535 rl++; 536 break; 537 case SHT_RELA: 538 ef->relatab[ra].rela = malloc(shdr[i].sh_size, M_LINKER, 539 M_WAITOK); 540 ef->relatab[ra].nrela = 541 shdr[i].sh_size / sizeof(Elf_Rela); 542 ef->relatab[ra].sec = shdr[i].sh_info; 543 error = vn_rdwr(UIO_READ, nd.ni_vp, 544 (void *)ef->relatab[ra].rela, 545 shdr[i].sh_size, shdr[i].sh_offset, 546 UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, 547 &resid, td); 548 if (error) 549 goto out; 550 if (resid != 0){ 551 error = EINVAL; 552 goto out; 553 } 554 ra++; 555 break; 556 } 557 } 558 if (pb != ef->nprogtab) 559 panic("lost progbits"); 560 if (rl != ef->nrel) 561 panic("lost rel"); 562 if (ra != ef->nrela) 563 panic("lost rela"); 564 if (mapbase != (vm_offset_t)ef->address + mapsize) 565 panic("mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n", 566 mapbase, ef->address, mapsize, 567 (vm_offset_t)ef->address + mapsize); 568 569 /* Local intra-module relocations */ 570 link_elf_reloc_local(lf); 571 572 /* Pull in dependencies */ 573 error = linker_load_dependencies(lf); 574 if (error) 575 goto out; 576 577 /* External relocations */ 578 error = relocate_file(ef); 579 if (error) 580 goto out; 581 582 /* Notify MD code that a module is being loaded. */ 583 error = elf_cpu_load_file(lf); 584 if (error) 585 goto out; 586 587 *result = lf; 588 589 out: 590 if (error && lf) 591 linker_file_unload(lf, LINKER_UNLOAD_FORCE); 592 if (hdr) 593 free(hdr, M_LINKER); 594 VOP_UNLOCK(nd.ni_vp, 0, td); 595 vn_close(nd.ni_vp, FREAD, td->td_ucred, td); 596 597 return error; 598 } 599 600 static void 601 link_elf_unload_file(linker_file_t file) 602 { 603 elf_file_t ef = (elf_file_t) file; 604 int i; 605 606 /* Notify MD code that a module is being unloaded. */ 607 elf_cpu_unload_file(file); 608 609 for (i = 0; i < ef->nrel; i++) 610 if (ef->reltab[i].rel) 611 free(ef->reltab[i].rel, M_LINKER); 612 for (i = 0; i < ef->nrela; i++) 613 if (ef->relatab[i].rela) 614 free(ef->relatab[i].rela, M_LINKER); 615 if (ef->reltab) 616 free(ef->reltab, M_LINKER); 617 if (ef->relatab) 618 free(ef->relatab, M_LINKER); 619 if (ef->progtab) 620 free(ef->progtab, M_LINKER); 621 622 if (ef->object) { 623 vm_map_remove(kernel_map, (vm_offset_t) ef->address, 624 (vm_offset_t) ef->address + 625 (ef->object->size << PAGE_SHIFT)); 626 vm_object_deallocate(ef->object); 627 } 628 if (ef->e_shdr) 629 free(ef->e_shdr, M_LINKER); 630 if (ef->ddbsymtab) 631 free(ef->ddbsymtab, M_LINKER); 632 if (ef->ddbstrtab) 633 free(ef->ddbstrtab, M_LINKER); 634 if (ef->shstrtab) 635 free(ef->shstrtab, M_LINKER); 636 } 637 638 static const char * 639 symbol_name(elf_file_t ef, Elf_Word r_info) 640 { 641 const Elf_Sym *ref; 642 643 if (ELF_R_SYM(r_info)) { 644 ref = ef->ddbsymtab + ELF_R_SYM(r_info); 645 return ef->ddbstrtab + ref->st_name; 646 } else 647 return NULL; 648 } 649 650 static Elf_Addr 651 findbase(elf_file_t ef, int sec) 652 { 653 int i; 654 Elf_Addr base = 0; 655 656 for (i = 0; i < ef->nprogtab; i++) { 657 if (sec == ef->progtab[i].sec) { 658 base = (Elf_Addr)ef->progtab[i].addr; 659 break; 660 } 661 } 662 return base; 663 } 664 665 static int 666 relocate_file(elf_file_t ef) 667 { 668 const Elf_Rel *rellim; 669 const Elf_Rel *rel; 670 const Elf_Rela *relalim; 671 const Elf_Rela *rela; 672 const char *symname; 673 const Elf_Sym *sym; 674 int i; 675 Elf_Word symidx; 676 Elf_Addr base; 677 678 679 /* Perform relocations without addend if there are any: */ 680 for (i = 0; i < ef->nrel; i++) { 681 rel = ef->reltab[i].rel; 682 if (rel == NULL) 683 panic("lost a reltab!"); 684 rellim = rel + ef->reltab[i].nrel; 685 base = findbase(ef, ef->reltab[i].sec); 686 if (base == 0) 687 panic("lost base for reltab"); 688 for ( ; rel < rellim; rel++) { 689 symidx = ELF_R_SYM(rel->r_info); 690 if (symidx >= ef->ddbsymcnt) 691 continue; 692 sym = ef->ddbsymtab + symidx; 693 /* Local relocs are already done */ 694 if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) 695 continue; 696 if (elf_reloc(&ef->lf, base, rel, ELF_RELOC_REL, 697 elf_obj_lookup)) { 698 symname = symbol_name(ef, rel->r_info); 699 printf("link_elf_obj: symbol %s undefined\n", 700 symname); 701 return ENOENT; 702 } 703 } 704 } 705 706 /* Perform relocations with addend if there are any: */ 707 for (i = 0; i < ef->nrela; i++) { 708 rela = ef->relatab[i].rela; 709 if (rela == NULL) 710 panic("lost a relatab!"); 711 relalim = rela + ef->relatab[i].nrela; 712 base = findbase(ef, ef->relatab[i].sec); 713 if (base == 0) 714 panic("lost base for relatab"); 715 for ( ; rela < relalim; rela++) { 716 symidx = ELF_R_SYM(rela->r_info); 717 if (symidx >= ef->ddbsymcnt) 718 continue; 719 sym = ef->ddbsymtab + symidx; 720 /* Local relocs are already done */ 721 if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) 722 continue; 723 if (elf_reloc(&ef->lf, base, rela, ELF_RELOC_RELA, 724 elf_obj_lookup)) { 725 symname = symbol_name(ef, rela->r_info); 726 printf("link_elf_obj: symbol %s undefined\n", 727 symname); 728 return ENOENT; 729 } 730 } 731 } 732 733 return 0; 734 } 735 736 static int 737 link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t *sym) 738 { 739 elf_file_t ef = (elf_file_t) lf; 740 const Elf_Sym *symp; 741 const char *strp; 742 int i; 743 744 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 745 strp = ef->ddbstrtab + symp->st_name; 746 if (symp->st_shndx != SHN_UNDEF && strcmp(name, strp) == 0) { 747 *sym = (c_linker_sym_t) symp; 748 return 0; 749 } 750 } 751 return ENOENT; 752 } 753 754 static int 755 link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, 756 linker_symval_t *symval) 757 { 758 elf_file_t ef = (elf_file_t) lf; 759 const Elf_Sym *es = (const Elf_Sym*) sym; 760 761 if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) { 762 symval->name = ef->ddbstrtab + es->st_name; 763 symval->value = (caddr_t)es->st_value; 764 symval->size = es->st_size; 765 return 0; 766 } 767 return ENOENT; 768 } 769 770 static int 771 link_elf_search_symbol(linker_file_t lf, caddr_t value, 772 c_linker_sym_t *sym, long *diffp) 773 { 774 elf_file_t ef = (elf_file_t) lf; 775 u_long off = (uintptr_t) (void *) value; 776 u_long diff = off; 777 u_long st_value; 778 const Elf_Sym *es; 779 const Elf_Sym *best = 0; 780 int i; 781 782 for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) { 783 if (es->st_name == 0) 784 continue; 785 st_value = es->st_value; 786 if (off >= st_value) { 787 if (off - st_value < diff) { 788 diff = off - st_value; 789 best = es; 790 if (diff == 0) 791 break; 792 } else if (off - st_value == diff) { 793 best = es; 794 } 795 } 796 } 797 if (best == 0) 798 *diffp = off; 799 else 800 *diffp = diff; 801 *sym = (c_linker_sym_t) best; 802 803 return 0; 804 } 805 806 /* 807 * Look up a linker set on an ELF system. 808 */ 809 static int 810 link_elf_lookup_set(linker_file_t lf, const char *name, 811 void ***startp, void ***stopp, int *countp) 812 { 813 elf_file_t ef = (elf_file_t)lf; 814 void **start, **stop; 815 int i, count; 816 817 /* Relative to section number */ 818 for (i = 0; i < ef->nprogtab; i++) { 819 if ((strncmp(ef->progtab[i].name, "set_", 4) == 0) && 820 strcmp(ef->progtab[i].name + 4, name) == 0) { 821 start = (void **)ef->progtab[i].addr; 822 stop = (void **)((char *)ef->progtab[i].addr + 823 ef->progtab[i].size); 824 count = stop - start; 825 if (startp) 826 *startp = start; 827 if (stopp) 828 *stopp = stop; 829 if (countp) 830 *countp = count; 831 return (0); 832 } 833 } 834 return (ESRCH); 835 } 836 837 static int 838 link_elf_each_function_name(linker_file_t file, 839 int (*callback)(const char *, void *), void *opaque) 840 { 841 elf_file_t ef = (elf_file_t)file; 842 const Elf_Sym *symp; 843 int i, error; 844 845 /* Exhaustive search */ 846 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 847 if (symp->st_value != 0 && 848 ELF_ST_TYPE(symp->st_info) == STT_FUNC) { 849 error = callback(ef->ddbstrtab + symp->st_name, opaque); 850 if (error) 851 return (error); 852 } 853 } 854 return (0); 855 } 856 857 /* 858 * Symbol lookup function that can be used when the symbol index is known (ie 859 * in relocations). It uses the symbol index instead of doing a fully fledged 860 * hash table based lookup when such is valid. For example for local symbols. 861 * This is not only more efficient, it's also more correct. It's not always 862 * the case that the symbol can be found through the hash table. 863 */ 864 static Elf_Addr 865 elf_obj_lookup(linker_file_t lf, Elf_Word symidx, int deps) 866 { 867 elf_file_t ef = (elf_file_t)lf; 868 const Elf_Sym *sym; 869 const char *symbol; 870 Elf_Addr ret; 871 872 /* Don't even try to lookup the symbol if the index is bogus. */ 873 if (symidx >= ef->ddbsymcnt) 874 return (0); 875 876 sym = ef->ddbsymtab + symidx; 877 878 /* Quick answer if there is a definition included. */ 879 if (sym->st_shndx != SHN_UNDEF) 880 return (sym->st_value); 881 882 /* If we get here, then it is undefined and needs a lookup. */ 883 switch (ELF_ST_BIND(sym->st_info)) { 884 case STB_LOCAL: 885 /* Local, but undefined? huh? */ 886 return (0); 887 888 case STB_GLOBAL: 889 /* Relative to Data or Function name */ 890 symbol = ef->ddbstrtab + sym->st_name; 891 892 /* Force a lookup failure if the symbol name is bogus. */ 893 if (*symbol == 0) 894 return (0); 895 ret = ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps)); 896 return ret; 897 898 case STB_WEAK: 899 printf("link_elf_obj: Weak symbols not supported\n"); 900 return (0); 901 902 default: 903 return (0); 904 } 905 } 906 907 static void 908 link_elf_reloc_local(linker_file_t lf) 909 { 910 elf_file_t ef = (elf_file_t)lf; 911 const Elf_Rel *rellim; 912 const Elf_Rel *rel; 913 const Elf_Rela *relalim; 914 const Elf_Rela *rela; 915 const Elf_Sym *sym; 916 Elf_Addr base; 917 int i; 918 Elf_Word symidx; 919 920 /* Perform relocations without addend if there are any: */ 921 for (i = 0; i < ef->nrel; i++) { 922 rel = ef->reltab[i].rel; 923 if (rel == NULL) 924 panic("lost a reltab!"); 925 rellim = rel + ef->reltab[i].nrel; 926 base = findbase(ef, ef->reltab[i].sec); 927 if (base == 0) 928 panic("lost base for reltab"); 929 for ( ; rel < rellim; rel++) { 930 symidx = ELF_R_SYM(rel->r_info); 931 if (symidx >= ef->ddbsymcnt) 932 continue; 933 sym = ef->ddbsymtab + symidx; 934 /* Only do local relocs */ 935 if (ELF_ST_BIND(sym->st_info) != STB_LOCAL) 936 continue; 937 elf_reloc_local(lf, base, rel, ELF_RELOC_REL, 938 elf_obj_lookup); 939 } 940 } 941 942 /* Perform relocations with addend if there are any: */ 943 for (i = 0; i < ef->nrela; i++) { 944 rela = ef->relatab[i].rela; 945 if (rela == NULL) 946 panic("lost a relatab!"); 947 relalim = rela + ef->relatab[i].nrela; 948 base = findbase(ef, ef->relatab[i].sec); 949 if (base == 0) 950 panic("lost base for relatab"); 951 for ( ; rela < relalim; rela++) { 952 symidx = ELF_R_SYM(rela->r_info); 953 if (symidx >= ef->ddbsymcnt) 954 continue; 955 sym = ef->ddbsymtab + symidx; 956 /* Only do local relocs */ 957 if (ELF_ST_BIND(sym->st_info) != STB_LOCAL) 958 continue; 959 elf_reloc_local(lf, base, rela, ELF_RELOC_RELA, 960 elf_obj_lookup); 961 } 962 } 963 } 964