1 /*- 2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3 * Copyright (c) 1998 Peter Wemm <peter@freebsd.org> 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 * $FreeBSD: src/sys/boot/common/load_elf.c,v 1.39 2008/10/14 10:11:14 raj Exp $ 28 */ 29 30 #include <sys/param.h> 31 #include <sys/exec.h> 32 #include <sys/linker.h> 33 #include <sys/module.h> 34 #include <sys/stdint.h> 35 #include <string.h> 36 #include <machine/elf.h> 37 #include <stand.h> 38 #define FREEBSD_ELF 39 #include <link.h> 40 41 #include "bootstrap.h" 42 43 #define COPYOUT(s,d,l) archsw.arch_copyout((vm_offset_t)(s), d, l) 44 45 #if defined(__i386__) && __ELF_WORD_SIZE == 64 46 #undef ELF_TARG_CLASS 47 #undef ELF_TARG_MACH 48 #define ELF_TARG_CLASS ELFCLASS64 49 #define ELF_TARG_MACH EM_X86_64 50 #endif 51 52 typedef struct elf_file { 53 Elf_Phdr *ph; 54 Elf_Ehdr *ehdr; 55 Elf_Sym *symtab; 56 Elf_Hashelt *hashtab; 57 Elf_Hashelt nbuckets; 58 Elf_Hashelt nchains; 59 Elf_Hashelt *buckets; 60 Elf_Hashelt *chains; 61 Elf_Rel *rel; 62 size_t relsz; 63 Elf_Rela *rela; 64 size_t relasz; 65 char *strtab; 66 size_t strsz; 67 int fd; 68 caddr_t firstpage; 69 size_t firstlen; 70 int kernel; 71 u_int64_t off; 72 } *elf_file_t; 73 74 static int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef, u_int64_t loadaddr); 75 static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef, const char* name, Elf_Sym* sym); 76 static int __elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, 77 Elf_Addr p, void *val, size_t len); 78 static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef); 79 static symaddr_fn __elfN(symaddr); 80 static char *fake_modname(const char *name); 81 82 const char *__elfN(kerneltype) = "elf kernel"; 83 const char *__elfN(moduletype) = "elf module"; 84 85 u_int64_t __elfN(relocation_offset) = 0; 86 87 /* 88 * Attempt to load the file (file) as an ELF module. It will be stored at 89 * (dest), and a pointer to a module structure describing the loaded object 90 * will be saved in (result). 91 */ 92 int 93 __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result) 94 { 95 struct preloaded_file *fp, *kfp; 96 struct elf_file ef; 97 Elf_Ehdr *ehdr; 98 int err; 99 u_int pad; 100 ssize_t bytes_read; 101 char *fullpath; 102 103 fp = NULL; 104 bzero(&ef, sizeof(struct elf_file)); 105 106 /* 107 * Open the image, read and validate the ELF header 108 */ 109 if (filename == NULL) /* can't handle nameless */ 110 return(EFTYPE); 111 if ((ef.fd = rel_open(filename, &fullpath, O_RDONLY)) == -1) 112 return(errno); 113 ef.firstpage = malloc(PAGE_SIZE); 114 if (ef.firstpage == NULL) { 115 close(ef.fd); 116 free(fullpath); 117 return(ENOMEM); 118 } 119 bytes_read = read(ef.fd, ef.firstpage, PAGE_SIZE); 120 ef.firstlen = (size_t)bytes_read; 121 if (bytes_read < 0 || ef.firstlen <= sizeof(Elf_Ehdr)) { 122 err = EFTYPE; /* could be EIO, but may be small file */ 123 goto oerr; 124 } 125 ehdr = ef.ehdr = (Elf_Ehdr *)ef.firstpage; 126 127 /* Is it ELF? */ 128 if (!IS_ELF(*ehdr)) { 129 err = EFTYPE; 130 goto oerr; 131 } 132 if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */ 133 ehdr->e_ident[EI_DATA] != ELF_TARG_DATA || 134 ehdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */ 135 ehdr->e_version != EV_CURRENT || 136 ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */ 137 err = EFTYPE; 138 goto oerr; 139 } 140 141 142 /* 143 * Check to see what sort of module we are. 144 */ 145 kfp = file_findfile(NULL, NULL); 146 if (ehdr->e_type == ET_DYN) { 147 /* Looks like a kld module */ 148 if (kfp == NULL) { 149 printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module before kernel\n"); 150 err = EPERM; 151 goto oerr; 152 } 153 if (strcmp(__elfN(kerneltype), kfp->f_type)) { 154 printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module with kernel type '%s'\n", kfp->f_type); 155 err = EPERM; 156 goto oerr; 157 } 158 /* Looks OK, got ahead */ 159 ef.kernel = 0; 160 161 /* Page-align the load address */ 162 pad = (u_int)dest & PAGE_MASK; 163 if (pad != 0) { 164 pad = PAGE_SIZE - pad; 165 dest += pad; 166 } 167 } else if (ehdr->e_type == ET_EXEC) { 168 /* Looks like a kernel */ 169 if (kfp != NULL) { 170 printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: kernel already loaded\n"); 171 err = EPERM; 172 goto oerr; 173 } 174 /* 175 * Calculate destination address based on kernel entrypoint 176 */ 177 dest = ehdr->e_entry; 178 if (dest == 0) { 179 printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: not a kernel (maybe static binary?)\n"); 180 err = EPERM; 181 goto oerr; 182 } 183 ef.kernel = 1; 184 185 } else { 186 err = EFTYPE; 187 goto oerr; 188 } 189 190 /* 191 * Ok, we think we should handle this. 192 */ 193 fp = file_alloc(); 194 if (fp == NULL) { 195 printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: cannot allocate module info\n"); 196 err = EPERM; 197 goto out; 198 } 199 200 /* 201 * Set the kernel name and module path correctly for the kernel's 202 * consumption. Always prepend a /boot if we don't have one. 203 */ 204 if (ef.kernel) { 205 char *mptr; 206 char *fpend; 207 char *modlocal; 208 const char *prefix = ""; 209 210 mptr = malloc(256); 211 if (strncmp(fullpath, "/boot/", 6) != 0) 212 prefix = "/boot"; 213 snprintf(mptr, 256, "%s%s", prefix, fullpath); 214 setenv("kernelname", mptr, 1); 215 216 fpend = strrchr(mptr, '/'); 217 *fpend = 0; 218 if (strcmp(mptr, "/boot") == 0) 219 snprintf(mptr, 256, "/boot/modules"); 220 221 /* Append modules.local for kernel if requested */ 222 modlocal = getenv("local_modules"); 223 if (modlocal != NULL && strcmp(modlocal, "YES") == 0) 224 strncat(mptr, ";/boot/modules.local", 255); 225 226 /* this will be moved to "module_path" on boot */ 227 setenv("exported_module_path", mptr, 1); 228 free(mptr); 229 } 230 fp->f_name = strdup(filename); 231 fp->f_type = strdup(ef.kernel ? __elfN(kerneltype) : __elfN(moduletype)); 232 233 #ifdef ELF_VERBOSE 234 if (ef.kernel) 235 printf("%s entry at 0x%jx\n", filename, (uintmax_t)dest); 236 #else 237 printf("%s ", filename); 238 #endif 239 240 fp->f_size = __elfN(loadimage)(fp, &ef, dest); 241 if (fp->f_size == 0 || fp->f_addr == 0) 242 goto ioerr; 243 244 /* save exec header as metadata */ 245 file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*ehdr), ehdr); 246 247 /* Load OK, return module pointer */ 248 *result = (struct preloaded_file *)fp; 249 err = 0; 250 goto out; 251 252 ioerr: 253 err = EIO; 254 oerr: 255 file_discard(fp); 256 out: 257 if (ef.firstpage) 258 free(ef.firstpage); 259 close(ef.fd); 260 if (fullpath) 261 free(fullpath); 262 return(err); 263 } 264 265 /* 266 * With the file (fd) open on the image, and (ehdr) containing 267 * the Elf header, load the image at (off) 268 */ 269 static int 270 __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) 271 { 272 int i; 273 u_int j; 274 Elf_Ehdr *ehdr; 275 Elf_Phdr *phdr, *php; 276 Elf_Shdr *shdr; 277 int ret; 278 vm_offset_t firstaddr; 279 vm_offset_t lastaddr; 280 size_t chunk; 281 ssize_t result; 282 Elf_Addr ssym, esym; 283 Elf_Dyn *dp; 284 Elf_Addr adp; 285 int ndp; 286 int symstrindex; 287 int symtabindex; 288 Elf_Size size; 289 u_int fpcopy; 290 291 dp = NULL; 292 shdr = NULL; 293 ret = 0; 294 firstaddr = lastaddr = 0; 295 ehdr = ef->ehdr; 296 if (ef->kernel) { 297 #if defined(__x86_64__) || defined(__i386__) 298 #if __ELF_WORD_SIZE == 64 299 off = - (off & 0xffffffffff000000ull);/* x86_64 relocates after locore */ 300 #else 301 off = - (off & 0xff000000u); /* i386 relocates after locore */ 302 #endif 303 #else 304 off = 0; /* other archs use direct mapped kernels */ 305 #endif 306 __elfN(relocation_offset) = off; 307 } 308 ef->off = off; 309 310 if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > ef->firstlen) { 311 printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: program header not within first page\n"); 312 goto out; 313 } 314 phdr = (Elf_Phdr *)(ef->firstpage + ehdr->e_phoff); 315 316 for (i = 0; i < ehdr->e_phnum; i++) { 317 /* We want to load PT_LOAD segments only.. */ 318 if (phdr[i].p_type != PT_LOAD) 319 continue; 320 321 #ifdef ELF_VERBOSE 322 printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx", 323 (long)phdr[i].p_filesz, (long)phdr[i].p_offset, 324 (long)(phdr[i].p_vaddr + off), 325 (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1)); 326 #else 327 if ((phdr[i].p_flags & PF_W) == 0) { 328 printf("text=0x%lx ", (long)phdr[i].p_filesz); 329 } else { 330 printf("data=0x%lx", (long)phdr[i].p_filesz); 331 if (phdr[i].p_filesz < phdr[i].p_memsz) 332 printf("+0x%lx", (long)(phdr[i].p_memsz -phdr[i].p_filesz)); 333 printf(" "); 334 } 335 #endif 336 fpcopy = 0; 337 if (ef->firstlen > phdr[i].p_offset) { 338 fpcopy = ef->firstlen - phdr[i].p_offset; 339 archsw.arch_copyin(ef->firstpage + phdr[i].p_offset, 340 phdr[i].p_vaddr + off, fpcopy); 341 } 342 if (phdr[i].p_filesz > fpcopy) { 343 if (kern_pread(ef->fd, phdr[i].p_vaddr + off + fpcopy, 344 phdr[i].p_filesz - fpcopy, phdr[i].p_offset + fpcopy) != 0) { 345 printf("\nelf" __XSTRING(__ELF_WORD_SIZE) 346 "_loadimage: read failed\n"); 347 goto out; 348 } 349 } 350 /* clear space from oversized segments; eg: bss */ 351 if (phdr[i].p_filesz < phdr[i].p_memsz) { 352 #ifdef ELF_VERBOSE 353 printf(" (bss: 0x%lx-0x%lx)", 354 (long)(phdr[i].p_vaddr + off + phdr[i].p_filesz), 355 (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1)); 356 #endif 357 358 kern_bzero(phdr[i].p_vaddr + off + phdr[i].p_filesz, 359 phdr[i].p_memsz - phdr[i].p_filesz); 360 } 361 #ifdef ELF_VERBOSE 362 printf("\n"); 363 #endif 364 365 if (firstaddr == 0 || firstaddr > (phdr[i].p_vaddr + off)) 366 firstaddr = phdr[i].p_vaddr + off; 367 if (lastaddr == 0 || lastaddr < (phdr[i].p_vaddr + off + phdr[i].p_memsz)) 368 lastaddr = phdr[i].p_vaddr + off + phdr[i].p_memsz; 369 } 370 lastaddr = roundup(lastaddr, sizeof(long)); 371 372 /* 373 * Now grab the symbol tables. This isn't easy if we're reading a 374 * .gz file. I think the rule is going to have to be that you must 375 * strip a file to remove symbols before gzipping it so that we do not 376 * try to lseek() on it. 377 */ 378 chunk = ehdr->e_shnum * ehdr->e_shentsize; 379 if (chunk == 0 || ehdr->e_shoff == 0) 380 goto nosyms; 381 shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk); 382 if (shdr == NULL) { 383 printf("\nelf" __XSTRING(__ELF_WORD_SIZE) 384 "_loadimage: failed to read section headers"); 385 goto nosyms; 386 } 387 symtabindex = -1; 388 symstrindex = -1; 389 for (i = 0; i < ehdr->e_shnum; i++) { 390 if (shdr[i].sh_type != SHT_SYMTAB) 391 continue; 392 for (j = 0; j < ehdr->e_phnum; j++) { 393 if (phdr[j].p_type != PT_LOAD) 394 continue; 395 if (shdr[i].sh_offset >= phdr[j].p_offset && 396 (shdr[i].sh_offset + shdr[i].sh_size <= 397 phdr[j].p_offset + phdr[j].p_filesz)) { 398 shdr[i].sh_offset = 0; 399 shdr[i].sh_size = 0; 400 break; 401 } 402 } 403 if (shdr[i].sh_offset == 0 || shdr[i].sh_size == 0) 404 continue; /* alread loaded in a PT_LOAD above */ 405 /* Save it for loading below */ 406 symtabindex = i; 407 symstrindex = shdr[i].sh_link; 408 } 409 if (symtabindex < 0 || symstrindex < 0) 410 goto nosyms; 411 412 /* Ok, committed to a load. */ 413 #ifndef ELF_VERBOSE 414 printf("syms=["); 415 #endif 416 ssym = lastaddr; 417 for (i = symtabindex; i >= 0; i = symstrindex) { 418 #ifdef ELF_VERBOSE 419 char *secname; 420 421 switch(shdr[i].sh_type) { 422 case SHT_SYMTAB: /* Symbol table */ 423 secname = "symtab"; 424 break; 425 case SHT_STRTAB: /* String table */ 426 secname = "strtab"; 427 break; 428 default: 429 secname = "WHOA!!"; 430 break; 431 } 432 #endif 433 434 size = shdr[i].sh_size; 435 archsw.arch_copyin(&size, lastaddr, sizeof(size)); 436 lastaddr += sizeof(size); 437 438 #ifdef ELF_VERBOSE 439 printf("\n%s: 0x%jx@0x%jx -> 0x%jx-0x%jx", secname, 440 (uintmax_t)shdr[i].sh_size, (uintmax_t)shdr[i].sh_offset, 441 (uintmax_t)lastaddr, (uintmax_t)(lastaddr + shdr[i].sh_size)); 442 #else 443 if (i == symstrindex) 444 printf("+"); 445 printf("0x%lx+0x%lx", (long)sizeof(size), (long)size); 446 #endif 447 448 if (lseek(ef->fd, (off_t)shdr[i].sh_offset, SEEK_SET) == -1) { 449 printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not seek for symbols - skipped!"); 450 lastaddr = ssym; 451 ssym = 0; 452 goto nosyms; 453 } 454 result = archsw.arch_readin(ef->fd, lastaddr, shdr[i].sh_size); 455 if (result < 0 || (size_t)result != shdr[i].sh_size) { 456 printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not read symbols - skipped!"); 457 lastaddr = ssym; 458 ssym = 0; 459 goto nosyms; 460 } 461 /* Reset offsets relative to ssym */ 462 lastaddr += shdr[i].sh_size; 463 lastaddr = roundup(lastaddr, sizeof(size)); 464 if (i == symtabindex) 465 symtabindex = -1; 466 else if (i == symstrindex) 467 symstrindex = -1; 468 } 469 esym = lastaddr; 470 #ifndef ELF_VERBOSE 471 printf("]"); 472 #endif 473 474 file_addmetadata(fp, MODINFOMD_SSYM, sizeof(ssym), &ssym); 475 file_addmetadata(fp, MODINFOMD_ESYM, sizeof(esym), &esym); 476 477 nosyms: 478 printf("\n"); 479 480 ret = lastaddr - firstaddr; 481 fp->f_addr = firstaddr; 482 483 php = NULL; 484 for (i = 0; i < ehdr->e_phnum; i++) { 485 if (phdr[i].p_type == PT_DYNAMIC) { 486 php = phdr + i; 487 adp = php->p_vaddr; 488 file_addmetadata(fp, MODINFOMD_DYNAMIC, sizeof(adp), &adp); 489 break; 490 } 491 } 492 493 if (php == NULL) /* this is bad, we cannot get to symbols or _DYNAMIC */ 494 goto out; 495 496 ndp = php->p_filesz / sizeof(Elf_Dyn); 497 if (ndp == 0) 498 goto out; 499 dp = malloc(php->p_filesz); 500 if (dp == NULL) 501 goto out; 502 archsw.arch_copyout(php->p_vaddr + off, dp, php->p_filesz); 503 504 ef->strsz = 0; 505 for (i = 0; i < ndp; i++) { 506 if (dp[i].d_tag == 0) 507 break; 508 switch (dp[i].d_tag) { 509 case DT_HASH: 510 ef->hashtab = (Elf_Hashelt*)(uintptr_t)(dp[i].d_un.d_ptr + off); 511 break; 512 case DT_STRTAB: 513 ef->strtab = (char *)(uintptr_t)(dp[i].d_un.d_ptr + off); 514 break; 515 case DT_STRSZ: 516 ef->strsz = dp[i].d_un.d_val; 517 break; 518 case DT_SYMTAB: 519 ef->symtab = (Elf_Sym*)(uintptr_t)(dp[i].d_un.d_ptr + off); 520 break; 521 case DT_REL: 522 ef->rel = (Elf_Rel *)(uintptr_t)(dp[i].d_un.d_ptr + off); 523 break; 524 case DT_RELSZ: 525 ef->relsz = dp[i].d_un.d_val; 526 break; 527 case DT_RELA: 528 ef->rela = (Elf_Rela *)(uintptr_t)(dp[i].d_un.d_ptr + off); 529 break; 530 case DT_RELASZ: 531 ef->relasz = dp[i].d_un.d_val; 532 break; 533 default: 534 break; 535 } 536 } 537 if (ef->hashtab == NULL || ef->symtab == NULL || 538 ef->strtab == NULL || ef->strsz == 0) 539 goto out; 540 COPYOUT(ef->hashtab, &ef->nbuckets, sizeof(ef->nbuckets)); 541 COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains)); 542 ef->buckets = ef->hashtab + 2; 543 ef->chains = ef->buckets + ef->nbuckets; 544 if (__elfN(parse_modmetadata)(fp, ef) == 0) 545 goto out; 546 547 if (ef->kernel) /* kernel must not depend on anything */ 548 goto out; 549 550 out: 551 if (dp) 552 free(dp); 553 if (shdr) 554 free(shdr); 555 return ret; 556 } 557 558 static char invalid_name[] = "bad"; 559 560 char * 561 fake_modname(const char *name) 562 { 563 const char *sp, *ep; 564 char *fp; 565 size_t len; 566 567 sp = strrchr(name, '/'); 568 if (sp) 569 sp++; 570 else 571 sp = name; 572 ep = strrchr(name, '.'); 573 if (ep) { 574 if (ep == name) { 575 sp = invalid_name; 576 ep = invalid_name + sizeof(invalid_name) - 1; 577 } 578 } else 579 ep = name + strlen(name); 580 len = ep - sp; 581 fp = malloc(len + 1); 582 if (fp == NULL) 583 return NULL; 584 memcpy(fp, sp, len); 585 fp[len] = '\0'; 586 return fp; 587 } 588 589 #if defined(__i386__) && __ELF_WORD_SIZE == 64 590 struct mod_metadata64 { 591 int md_version; /* structure version MDTV_* */ 592 int md_type; /* type of entry MDT_* */ 593 u_int64_t md_data; /* specific data */ 594 u_int64_t md_cval; /* common string label */ 595 }; 596 #endif 597 598 int 599 __elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef) 600 { 601 struct mod_metadata md; 602 #if defined(__i386__) && __ELF_WORD_SIZE == 64 603 struct mod_metadata64 md64; 604 #endif 605 struct mod_depend *mdepend; 606 struct mod_version mver; 607 Elf_Sym sym; 608 char *s; 609 int error, modcnt, minfolen; 610 Elf_Addr v, p, p_stop; 611 612 if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0) 613 return ENOENT; 614 p = sym.st_value + ef->off; 615 if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0) 616 return ENOENT; 617 p_stop = sym.st_value + ef->off; 618 619 modcnt = 0; 620 while (p < p_stop) { 621 COPYOUT(p, &v, sizeof(v)); 622 error = __elfN(reloc_ptr)(fp, ef, p, &v, sizeof(v)); 623 if (error == EOPNOTSUPP) 624 v += ef->off; 625 else if (error != 0) 626 return (error); 627 #if defined(__i386__) && __ELF_WORD_SIZE == 64 628 COPYOUT(v, &md64, sizeof(md64)); 629 error = __elfN(reloc_ptr)(fp, ef, v, &md64, sizeof(md64)); 630 if (error == EOPNOTSUPP) { 631 md64.md_cval += ef->off; 632 md64.md_data += ef->off; 633 } else if (error != 0) 634 return (error); 635 md.md_version = md64.md_version; 636 md.md_type = md64.md_type; 637 md.md_cval = (const char *)(uintptr_t)md64.md_cval; 638 md.md_data = (void *)(uintptr_t)md64.md_data; 639 #else 640 COPYOUT(v, &md, sizeof(md)); 641 error = __elfN(reloc_ptr)(fp, ef, v, &md, sizeof(md)); 642 if (error == EOPNOTSUPP) { 643 md.md_cval += ef->off; 644 md.md_data = (char *)md.md_data + ef->off; 645 } else if (error != 0) 646 return (error); 647 #endif 648 p += sizeof(Elf_Addr); 649 switch(md.md_type) { 650 case MDT_DEPEND: 651 if (ef->kernel) /* kernel must not depend on anything */ 652 break; 653 s = strdupout((vm_offset_t)md.md_cval); 654 minfolen = sizeof(*mdepend) + strlen(s) + 1; 655 mdepend = malloc(minfolen); 656 if (mdepend == NULL) 657 return ENOMEM; 658 COPYOUT((vm_offset_t)md.md_data, mdepend, sizeof(*mdepend)); 659 strcpy((char*)(mdepend + 1), s); 660 free(s); 661 file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen, mdepend); 662 free(mdepend); 663 break; 664 case MDT_VERSION: 665 s = strdupout((vm_offset_t)md.md_cval); 666 COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver)); 667 file_addmodule(fp, s, mver.mv_version, NULL); 668 free(s); 669 modcnt++; 670 break; 671 } 672 } 673 if (modcnt == 0) { 674 s = fake_modname(fp->f_name); 675 file_addmodule(fp, s, 1, NULL); 676 free(s); 677 } 678 return 0; 679 } 680 681 static unsigned long 682 elf_hash(const char *name) 683 { 684 const unsigned char *p = (const unsigned char *) name; 685 unsigned long h = 0; 686 unsigned long g; 687 688 while (*p != '\0') { 689 h = (h << 4) + *p++; 690 if ((g = h & 0xf0000000) != 0) 691 h ^= g >> 24; 692 h &= ~g; 693 } 694 return h; 695 } 696 697 static const char __elfN(bad_symtable)[] = "elf" __XSTRING(__ELF_WORD_SIZE) "_lookup_symbol: corrupt symbol table\n"; 698 int 699 __elfN(lookup_symbol)(struct preloaded_file *fp, elf_file_t ef, const char* name, 700 Elf_Sym *symp) 701 { 702 Elf_Hashelt symnum; 703 Elf_Sym sym; 704 char *strp; 705 unsigned long hash; 706 707 hash = elf_hash(name); 708 COPYOUT(&ef->buckets[hash % ef->nbuckets], &symnum, sizeof(symnum)); 709 710 while (symnum != STN_UNDEF) { 711 if (symnum >= ef->nchains) { 712 printf(__elfN(bad_symtable)); 713 return ENOENT; 714 } 715 716 COPYOUT(ef->symtab + symnum, &sym, sizeof(sym)); 717 if (sym.st_name == 0) { 718 printf(__elfN(bad_symtable)); 719 return ENOENT; 720 } 721 722 strp = strdupout((vm_offset_t)(ef->strtab + sym.st_name)); 723 if (strcmp(name, strp) == 0) { 724 free(strp); 725 if (sym.st_shndx != SHN_UNDEF || 726 (sym.st_value != 0 && 727 ELF_ST_TYPE(sym.st_info) == STT_FUNC)) { 728 *symp = sym; 729 return 0; 730 } 731 return ENOENT; 732 } 733 free(strp); 734 COPYOUT(&ef->chains[symnum], &symnum, sizeof(symnum)); 735 } 736 return ENOENT; 737 } 738 739 /* 740 * Apply any intra-module relocations to the value. p is the load address 741 * of the value and val/len is the value to be modified. This does NOT modify 742 * the image in-place, because this is done by kern_linker later on. 743 * 744 * Returns EOPNOTSUPP if no relocation method is supplied. 745 */ 746 static int 747 __elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, 748 Elf_Addr p, void *val, size_t len) 749 { 750 size_t n; 751 Elf_Rela a; 752 Elf_Rel r; 753 int error; 754 755 /* 756 * The kernel is already relocated, but we still want to apply 757 * offset adjustments. 758 */ 759 if (ef->kernel) 760 return (EOPNOTSUPP); 761 762 for (n = 0; n < ef->relsz / sizeof(r); n++) { 763 COPYOUT(ef->rel + n, &r, sizeof(r)); 764 765 error = __elfN(reloc)(ef, __elfN(symaddr), &r, ELF_RELOC_REL, 766 ef->off, p, val, len); 767 if (error != 0) 768 return (error); 769 } 770 for (n = 0; n < ef->relasz / sizeof(a); n++) { 771 COPYOUT(ef->rela + n, &a, sizeof(a)); 772 773 error = __elfN(reloc)(ef, __elfN(symaddr), &a, ELF_RELOC_RELA, 774 ef->off, p, val, len); 775 if (error != 0) 776 return (error); 777 } 778 779 return (0); 780 } 781 782 static Elf_Addr 783 __elfN(symaddr)(struct elf_file *ef, Elf_Size symidx) 784 { 785 786 /* Symbol lookup by index not required here. */ 787 return (0); 788 } 789