exec_elf32.c revision 1.41
1/* $NetBSD: exec_elf32.c,v 1.41 1999/01/06 11:52:53 christos Exp $ */ 2 3/*- 4 * Copyright (c) 1994 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39/* 40 * Copyright (c) 1996 Christopher G. Demetriou 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. The name of the author may not be used to endorse or promote products 52 * derived from this software without specific prior written permission 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 55 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 56 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 57 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 58 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 59 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 60 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 61 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 62 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 63 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 64 */ 65 66/* If not included by exec_elf64.c, ELFSIZE won't be defined. */ 67#ifndef ELFSIZE 68#define ELFSIZE 32 69#endif 70 71#include "opt_compat_linux.h" 72#include "opt_compat_ibcs2.h" 73#include "opt_compat_svr4.h" 74 75#include <sys/param.h> 76#include <sys/systm.h> 77#include <sys/kernel.h> 78#include <sys/proc.h> 79#include <sys/malloc.h> 80#include <sys/namei.h> 81#include <sys/vnode.h> 82#include <sys/exec.h> 83#include <sys/exec_elf.h> 84#include <sys/fcntl.h> 85#include <sys/syscall.h> 86#include <sys/signalvar.h> 87#include <sys/mount.h> 88#include <sys/stat.h> 89 90#include <sys/mman.h> 91#include <vm/vm.h> 92#include <vm/vm_param.h> 93#include <vm/vm_map.h> 94 95#include <machine/cpu.h> 96#include <machine/reg.h> 97 98#ifdef COMPAT_LINUX 99#include <compat/linux/common/linux_exec.h> 100#endif 101 102#ifdef COMPAT_SVR4 103#include <compat/svr4/svr4_exec.h> 104#endif 105 106#ifdef COMPAT_IBCS2 107#include <compat/ibcs2/ibcs2_exec.h> 108#endif 109 110int ELFNAME(check_header) __P((Elf_Ehdr *, int)); 111int ELFNAME(load_file) __P((struct proc *, struct exec_package *, char *, 112 struct exec_vmcmd_set *, u_long *, struct elf_args *, Elf_Addr *)); 113void ELFNAME(load_psection) __P((struct exec_vmcmd_set *, struct vnode *, 114 Elf_Phdr *, Elf_Addr *, u_long *, int *)); 115 116static int ELFNAME2(netbsd,signature) __P((struct proc *, struct exec_package *, 117 Elf_Ehdr *)); 118static int ELFNAME2(netbsd,probe) __P((struct proc *, struct exec_package *, 119 Elf_Ehdr *, char *, Elf_Addr *)); 120 121extern char sigcode[], esigcode[]; 122#ifdef SYSCALL_DEBUG 123extern char *syscallnames[]; 124#endif 125 126struct emul ELFNAMEEND(emul_netbsd) = { 127 "netbsd", 128 NULL, 129 sendsig, 130 SYS_syscall, 131 SYS_MAXSYSCALL, 132 sysent, 133#ifdef SYSCALL_DEBUG 134 syscallnames, 135#else 136 NULL, 137#endif 138 ELF_AUX_ENTRIES * sizeof(AuxInfo), 139 ELFNAME(copyargs), 140 setregs, 141 sigcode, 142 esigcode, 143}; 144 145int (*ELFNAME(probe_funcs)[]) __P((struct proc *, struct exec_package *, 146 Elf_Ehdr *, char *, Elf_Addr *)) = { 147 ELFNAME2(netbsd,probe), 148#if defined(COMPAT_LINUX) 149 ELFNAME2(linux,probe), 150#endif 151#if defined(COMPAT_SVR4) && (ELFSIZE == 32) 152 ELFNAME2(svr4,probe), /* XXX not 64-bit safe */ 153#endif 154#if defined(COMPAT_IBCS2) && (ELFSIZE == 32) 155 ELFNAME2(ibcs2,probe), /* XXX not 64-bit safe */ 156#endif 157}; 158 159/* round up and down to page boundaries. */ 160#define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1)) 161#define ELF_TRUNC(a, b) ((a) & ~((b) - 1)) 162 163/* 164 * Copy arguments onto the stack in the normal way, but add some 165 * extra information in case of dynamic binding. 166 */ 167void * 168ELFNAME(copyargs)(pack, arginfo, stack, argp) 169 struct exec_package *pack; 170 struct ps_strings *arginfo; 171 void *stack; 172 void *argp; 173{ 174 size_t len; 175 AuxInfo ai[ELF_AUX_ENTRIES], *a; 176 struct elf_args *ap; 177 178 stack = copyargs(pack, arginfo, stack, argp); 179 if (!stack) 180 return NULL; 181 182 a = ai; 183 184 /* 185 * Push extra arguments on the stack needed by dynamically 186 * linked binaries 187 */ 188 if ((ap = (struct elf_args *)pack->ep_emul_arg)) { 189 190 a->au_id = AUX_phdr; 191 a->au_v = ap->arg_phaddr; 192 a++; 193 194 a->au_id = AUX_phent; 195 a->au_v = ap->arg_phentsize; 196 a++; 197 198 a->au_id = AUX_phnum; 199 a->au_v = ap->arg_phnum; 200 a++; 201 202 a->au_id = AUX_pagesz; 203 a->au_v = NBPG; 204 a++; 205 206 a->au_id = AUX_base; 207 a->au_v = ap->arg_interp; 208 a++; 209 210 a->au_id = AUX_flags; 211 a->au_v = 0; 212 a++; 213 214 a->au_id = AUX_entry; 215 a->au_v = ap->arg_entry; 216 a++; 217 218 free((char *)ap, M_TEMP); 219 pack->ep_emul_arg = NULL; 220 } 221 222 a->au_id = AUX_null; 223 a->au_v = 0; 224 a++; 225 226 len = (a - ai) * sizeof(AuxInfo); 227 if (copyout(ai, stack, len)) 228 return NULL; 229 (caddr_t)stack += len; 230 231 return stack; 232} 233 234/* 235 * elf_check_header(): 236 * 237 * Check header for validity; return 0 of ok ENOEXEC if error 238 */ 239int 240ELFNAME(check_header)(eh, type) 241 Elf_Ehdr *eh; 242 int type; 243{ 244 245 if (memcmp(eh->e_ident, Elf_e_ident, Elf_e_siz) != 0) 246 return ENOEXEC; 247 248 switch (eh->e_machine) { 249 250 ELFDEFNNAME(MACHDEP_ID_CASES) 251 252 default: 253 return ENOEXEC; 254 } 255 256 if (eh->e_type != type) 257 return ENOEXEC; 258 259 return 0; 260} 261 262/* 263 * elf_load_psection(): 264 * 265 * Load a psection at the appropriate address 266 */ 267void 268ELFNAME(load_psection)(vcset, vp, ph, addr, size, prot) 269 struct exec_vmcmd_set *vcset; 270 struct vnode *vp; 271 Elf_Phdr *ph; 272 Elf_Addr *addr; 273 u_long *size; 274 int *prot; 275{ 276 u_long uaddr, msize, psize, rm, rf; 277 long diff, offset; 278 279 /* 280 * If the user specified an address, then we load there. 281 */ 282 if (*addr != ELFDEFNNAME(NO_ADDR)) { 283 if (ph->p_align > 1) { 284 *addr = ELF_ROUND(*addr, ph->p_align); 285 uaddr = ELF_TRUNC(ph->p_vaddr, ph->p_align); 286 } else 287 uaddr = ph->p_vaddr; 288 diff = ph->p_vaddr - uaddr; 289 } else { 290 *addr = uaddr = ph->p_vaddr; 291 if (ph->p_align > 1) 292 *addr = ELF_TRUNC(uaddr, ph->p_align); 293 diff = uaddr - *addr; 294 } 295 296 *prot |= (ph->p_flags & Elf_pf_r) ? VM_PROT_READ : 0; 297 *prot |= (ph->p_flags & Elf_pf_w) ? VM_PROT_WRITE : 0; 298 *prot |= (ph->p_flags & Elf_pf_x) ? VM_PROT_EXECUTE : 0; 299 300 offset = ph->p_offset - diff; 301 *size = ph->p_filesz + diff; 302 msize = ph->p_memsz + diff; 303 psize = round_page(*size); 304 305 if ((ph->p_flags & Elf_pf_w) != 0) { 306 /* 307 * Because the pagedvn pager can't handle zero fill of the last 308 * data page if it's not page aligned we map the last page 309 * readvn. 310 */ 311 psize = trunc_page(*size); 312 NEW_VMCMD(vcset, vmcmd_map_pagedvn, psize, *addr, vp, 313 offset, *prot); 314 if(psize != *size) 315 NEW_VMCMD(vcset, vmcmd_map_readvn, *size - psize, 316 *addr + psize, vp, offset + psize, *prot); 317 } else 318 NEW_VMCMD(vcset, vmcmd_map_pagedvn, psize, *addr, vp, 319 offset, *prot); 320 321 /* 322 * Check if we need to extend the size of the segment 323 */ 324 rm = round_page(*addr + msize); 325 rf = round_page(*addr + *size); 326 327 if (rm != rf) { 328 NEW_VMCMD(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 329 0, *prot); 330 *size = msize; 331 } 332} 333 334/* 335 * elf_read_from(): 336 * 337 * Read from vnode into buffer at offset. 338 */ 339int 340ELFNAME(read_from)(p, vp, off, buf, size) 341 struct vnode *vp; 342 u_long off; 343 struct proc *p; 344 caddr_t buf; 345 int size; 346{ 347 int error; 348 size_t resid; 349 350 if ((error = vn_rdwr(UIO_READ, vp, buf, size, off, UIO_SYSSPACE, 351 0, p->p_ucred, &resid, p)) != 0) 352 return error; 353 /* 354 * See if we got all of it 355 */ 356 if (resid != 0) 357 return ENOEXEC; 358 return 0; 359} 360 361/* 362 * elf_load_file(): 363 * 364 * Load a file (interpreter/library) pointed to by path 365 * [stolen from coff_load_shlib()]. Made slightly generic 366 * so it might be used externally. 367 */ 368int 369ELFNAME(load_file)(p, epp, path, vcset, entry, ap, last) 370 struct proc *p; 371 struct exec_package *epp; 372 char *path; 373 struct exec_vmcmd_set *vcset; 374 u_long *entry; 375 struct elf_args *ap; 376 Elf_Addr *last; 377{ 378 int error, i; 379 struct nameidata nd; 380 struct vnode *vp; 381 struct vattr attr; 382 Elf_Ehdr eh; 383 Elf_Phdr *ph = NULL; 384 u_long phsize; 385 char *bp = NULL; 386 Elf_Addr addr = *last; 387 388 bp = path; 389 /* 390 * 1. open file 391 * 2. read filehdr 392 * 3. map text, data, and bss out of it using VM_* 393 */ 394 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p); 395 if ((error = namei(&nd)) != 0) 396 return error; 397 vp = nd.ni_vp; 398 399 /* 400 * Similarly, if it's not marked as executable, or it's not a regular 401 * file, we don't allow it to be used. 402 */ 403 if (vp->v_type != VREG) { 404 error = EACCES; 405 goto badunlock; 406 } 407 if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0) 408 goto badunlock; 409 410 /* get attributes */ 411 if ((error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) != 0) 412 goto badunlock; 413 414 /* 415 * Check mount point. Though we're not trying to exec this binary, 416 * we will be executing code from it, so if the mount point 417 * disallows execution or set-id-ness, we punt or kill the set-id. 418 */ 419 if (vp->v_mount->mnt_flag & MNT_NOEXEC) { 420 error = EACCES; 421 goto badunlock; 422 } 423 if (vp->v_mount->mnt_flag & MNT_NOSUID) 424 epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID); 425 426#ifdef notyet /* XXX cgd 960926 */ 427 XXX cgd 960926: (maybe) VOP_OPEN it (and VOP_CLOSE in copyargs?) 428#endif 429 VOP_UNLOCK(vp, 0); 430 431 if ((error = ELFNAME(read_from)(p, vp, 0, (caddr_t) &eh, 432 sizeof(eh))) != 0) 433 goto bad; 434 435 if ((error = ELFNAME(check_header)(&eh, Elf_et_dyn)) != 0) 436 goto bad; 437 438 phsize = eh.e_phnum * sizeof(Elf_Phdr); 439 ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 440 441 if ((error = ELFNAME(read_from)(p, vp, eh.e_phoff, 442 (caddr_t) ph, phsize)) != 0) 443 goto bad; 444 445 /* 446 * Load all the necessary sections 447 */ 448 for (i = 0; i < eh.e_phnum; i++) { 449 u_long size = 0; 450 int prot = 0; 451 452 switch (ph[i].p_type) { 453 case Elf_pt_load: 454 ELFNAME(load_psection)(vcset, vp, &ph[i], &addr, 455 &size, &prot); 456 /* If entry is within this section it must be text */ 457 if (eh.e_entry >= ph[i].p_vaddr && 458 eh.e_entry < (ph[i].p_vaddr + size)) { 459 /* XXX */ 460 *entry = addr + eh.e_entry; 461#ifdef mips 462 *entry -= ph[i].p_vaddr; 463#endif 464 ap->arg_interp = addr; 465 } 466 addr += size; 467 break; 468 469 case Elf_pt_dynamic: 470 case Elf_pt_phdr: 471 case Elf_pt_note: 472 break; 473 474 default: 475 break; 476 } 477 } 478 479 free((char *)ph, M_TEMP); 480 *last = addr; 481 vrele(vp); 482 return 0; 483 484badunlock: 485 VOP_UNLOCK(vp, 0); 486 487bad: 488 if (ph != NULL) 489 free((char *)ph, M_TEMP); 490#ifdef notyet /* XXX cgd 960926 */ 491 (maybe) VOP_CLOSE it 492#endif 493 vrele(vp); 494 return error; 495} 496 497/* 498 * exec_elf_makecmds(): Prepare an Elf binary's exec package 499 * 500 * First, set of the various offsets/lengths in the exec package. 501 * 502 * Then, mark the text image busy (so it can be demand paged) or error 503 * out if this is not possible. Finally, set up vmcmds for the 504 * text, data, bss, and stack segments. 505 */ 506int 507ELFNAME2(exec,makecmds)(p, epp) 508 struct proc *p; 509 struct exec_package *epp; 510{ 511 Elf_Ehdr *eh = epp->ep_hdr; 512 Elf_Phdr *ph, *pp; 513 Elf_Addr phdr = 0, pos = 0; 514 int error, i, n, nload; 515 char interp[MAXPATHLEN]; 516 u_long phsize; 517 518 if (epp->ep_hdrvalid < sizeof(Elf_Ehdr)) 519 return ENOEXEC; 520 521 if (ELFNAME(check_header)(eh, Elf_et_exec)) 522 return ENOEXEC; 523 524 /* 525 * check if vnode is in open for writing, because we want to 526 * demand-page out of it. if it is, don't do it, for various 527 * reasons 528 */ 529 if (epp->ep_vp->v_writecount != 0) { 530#ifdef DIAGNOSTIC 531 if (epp->ep_vp->v_flag & VTEXT) 532 panic("exec: a VTEXT vnode has writecount != 0\n"); 533#endif 534 return ETXTBSY; 535 } 536 /* 537 * Allocate space to hold all the program headers, and read them 538 * from the file 539 */ 540 phsize = eh->e_phnum * sizeof(Elf_Phdr); 541 ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 542 543 if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff, 544 (caddr_t) ph, phsize)) != 0) 545 goto bad; 546 547 epp->ep_taddr = epp->ep_tsize = ELFDEFNNAME(NO_ADDR); 548 epp->ep_daddr = epp->ep_dsize = ELFDEFNNAME(NO_ADDR); 549 550 interp[0] = '\0'; 551 552 for (i = 0; i < eh->e_phnum; i++) { 553 pp = &ph[i]; 554 if (pp->p_type == Elf_pt_interp) { 555 if (pp->p_filesz >= sizeof(interp)) 556 goto bad; 557 if ((error = ELFNAME(read_from)(p, epp->ep_vp, 558 pp->p_offset, (caddr_t) interp, 559 pp->p_filesz)) != 0) 560 goto bad; 561 break; 562 } 563 } 564 565 /* 566 * Setup things for native emulation. 567 */ 568 epp->ep_emul = &ELFNAMEEND(emul_netbsd); 569 pos = ELFDEFNNAME(NO_ADDR); 570 571 /* 572 * On the same architecture, we may be emulating different systems. 573 * See which one will accept this executable. This currently only 574 * applies to SVR4, and IBCS2 on the i386 and Linux on the i386 575 * and the Alpha. 576 * 577 * Probe functions would normally see if the interpreter (if any) 578 * exists. Emulation packages may possibly replace the interpreter in 579 * interp[] with a changed path (/emul/xxx/<path>), and also 580 * set the ep_emul field in the exec package structure. 581 */ 582 n = sizeof(ELFNAME(probe_funcs)) / sizeof(ELFNAME(probe_funcs)[0]); 583 if (n != 0) { 584 error = ENOEXEC; 585 for (i = 0; i < n && error; i++) 586 error = ELFNAME(probe_funcs)[i](p, epp, eh, 587 interp, &pos); 588#ifdef notyet 589 /* 590 * We should really use a signature in our native binaries 591 * and have our own probe function for matching binaries, 592 * before trying the emulations. For now, if the emulation 593 * probes failed we default to native. 594 */ 595 if (error) 596 goto bad; 597#endif 598 } 599 600 /* 601 * Load all the necessary sections 602 */ 603 for (i = nload = 0; i < eh->e_phnum; i++) { 604 Elf_Addr addr = ELFDEFNNAME(NO_ADDR); 605 u_long size = 0; 606 int prot = 0; 607 608 pp = &ph[i]; 609 610 switch (ph[i].p_type) { 611 case Elf_pt_load: 612 /* 613 * XXX 614 * Can handle only 2 sections: text and data 615 */ 616 if (nload++ == 2) 617 goto bad; 618 ELFNAME(load_psection)(&epp->ep_vmcmds, epp->ep_vp, 619 &ph[i], &addr, &size, &prot); 620 621 /* 622 * Decide whether it's text or data by looking 623 * at the entry point. 624 */ 625 if (eh->e_entry >= addr && 626 eh->e_entry < (addr + size)) { 627 epp->ep_taddr = addr; 628 epp->ep_tsize = size; 629 if (epp->ep_daddr == ELFDEFNNAME(NO_ADDR)) { 630 epp->ep_daddr = addr; 631 epp->ep_dsize = size; 632 } 633 } else { 634 epp->ep_daddr = addr; 635 epp->ep_dsize = size; 636 } 637 break; 638 639 case Elf_pt_shlib: 640#ifndef COMPAT_IBCS2 /* SCO has these sections */ 641 error = ENOEXEC; 642 goto bad; 643#endif 644 645 case Elf_pt_interp: 646 /* Already did this one */ 647 case Elf_pt_dynamic: 648 case Elf_pt_note: 649 break; 650 651 case Elf_pt_phdr: 652 /* Note address of program headers (in text segment) */ 653 phdr = pp->p_vaddr; 654 break; 655 656 default: 657 /* 658 * Not fatal; we don't need to understand everything. 659 */ 660 break; 661 } 662 } 663 664 /* this breaks on, e.g., OpenBSD-compatible mips shared binaries. */ 665#ifndef ELF_INTERP_NON_RELOCATABLE 666 /* 667 * If no position to load the interpreter was set by a probe 668 * function, pick the same address that a non-fixed mmap(0, ..) 669 * would (i.e. something safely out of the way). 670 */ 671 if (pos == ELFDEFNNAME(NO_ADDR)) 672 pos = round_page(epp->ep_daddr + MAXDSIZ); 673#endif /* !ELF_INTERP_NON_RELOCATABLE */ 674 675 /* 676 * Check if we found a dynamically linked binary and arrange to load 677 * it's interpreter 678 */ 679 if (interp[0]) { 680 struct elf_args *ap; 681 682 ap = (struct elf_args *)malloc(sizeof(struct elf_args), 683 M_TEMP, M_WAITOK); 684 if ((error = ELFNAME(load_file)(p, epp, interp, 685 &epp->ep_vmcmds, &epp->ep_entry, ap, &pos)) != 0) { 686 free((char *)ap, M_TEMP); 687 goto bad; 688 } 689 pos += phsize; 690 ap->arg_phaddr = phdr; 691 692 ap->arg_phentsize = eh->e_phentsize; 693 ap->arg_phnum = eh->e_phnum; 694 ap->arg_entry = eh->e_entry; 695 696 epp->ep_emul_arg = ap; 697 } else 698 epp->ep_entry = eh->e_entry; 699 700#ifdef ELF_MAP_PAGE_ZERO 701 /* Dell SVR4 maps page zero, yeuch! */ 702 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, NBPG, 0, epp->ep_vp, 0, 703 VM_PROT_READ); 704#endif 705 free((char *)ph, M_TEMP); 706 epp->ep_vp->v_flag |= VTEXT; 707 return exec_elf_setup_stack(p, epp); 708 709bad: 710 free((char *)ph, M_TEMP); 711 kill_vmcmds(&epp->ep_vmcmds); 712 return ENOEXEC; 713} 714 715static int 716ELFNAME2(netbsd,signature)(p, epp, eh) 717 struct proc *p; 718 struct exec_package *epp; 719 Elf_Ehdr *eh; 720{ 721 Elf_Phdr *hph, *ph; 722 Elf_Note *np = NULL; 723 size_t phsize; 724 int error; 725 726 phsize = eh->e_phnum * sizeof(Elf_Phdr); 727 hph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 728 if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff, 729 (caddr_t)hph, phsize)) != 0) 730 goto out1; 731 732 for (ph = hph; ph < &hph[eh->e_phnum]; ph++) { 733 if (ph->p_type != Elf_pt_note || 734 ph->p_filesz < sizeof(Elf_Note) + ELF_NOTE_NETBSD_NAMESZ) 735 continue; 736 737 np = (Elf_Note *)malloc(ph->p_filesz, M_TEMP, M_WAITOK); 738 if ((error = ELFNAME(read_from)(p, epp->ep_vp, ph->p_offset, 739 (caddr_t)np, ph->p_filesz)) != 0) 740 goto out2; 741 742 if (np->type != ELF_NOTE_TYPE_OSVERSION) { 743 free(np, M_TEMP); 744 np = NULL; 745 continue; 746 } 747 748 /* Check the name and description sizes. */ 749 if (np->namesz != ELF_NOTE_NETBSD_NAMESZ || 750 np->descsz != ELF_NOTE_NETBSD_DESCSZ) 751 goto out3; 752 753 /* Is the name "NetBSD\0\0"? */ 754 if (memcmp((np + 1), ELF_NOTE_NETBSD_NAME, 755 ELF_NOTE_NETBSD_NAMESZ)) 756 goto out3; 757 758 /* XXX: We could check for the specific emulation here */ 759 /* All checks succeeded. */ 760 error = 0; 761 goto out2; 762 } 763 764out3: 765 error = ENOEXEC; 766out2: 767 if (np) 768 free(np, M_TEMP); 769out1: 770 free(hph, M_TEMP); 771 return error; 772} 773 774static int 775ELFNAME2(netbsd,probe)(p, epp, eh, itp, pos) 776 struct proc *p; 777 struct exec_package *epp; 778 Elf_Ehdr *eh; 779 char *itp; 780 Elf_Addr *pos; 781{ 782 int error; 783 784 if ((error = ELFNAME2(netbsd,signature)(p, epp, eh)) != 0) 785 return error; 786 787 epp->ep_emul = &ELFNAMEEND(emul_netbsd); 788 *pos = ELFDEFNNAME(NO_ADDR); 789 return 0; 790} 791