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