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