From owner-p4-projects Sat May 25 5:40:55 2002 Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 6D98B37B409; Sat, 25 May 2002 05:39:55 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 1C83E37B405 for ; Sat, 25 May 2002 05:39:54 -0700 (PDT) Received: (from perforce@localhost) by freefall.freebsd.org (8.11.6/8.11.6) id g4PCdsE61031 for perforce@freebsd.org; Sat, 25 May 2002 05:39:54 -0700 (PDT) (envelope-from dfr@freebsd.org) Date: Sat, 25 May 2002 05:39:54 -0700 (PDT) Message-Id: <200205251239.g4PCdsE61031@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: perforce set sender to dfr@freebsd.org using -f From: Doug Rabson Subject: PERFORCE change 11864 for review To: Perforce Change Reviews Sender: owner-p4-projects@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG http://people.freebsd.org/~peter/p4db/chv.cgi?CH=11864 Change 11864 by dfr@dfr_home on 2002/05/25 05:38:56 Updates to ELF image activater to allow the ia32 emulation to use the system's ELF32 activater instead of rolling its own. It should also be possible to use the ELF32 activater to run ia64 ILP32 binaries. Affected files ... ... //depot/projects/ia64/sys/conf/files.ia64#8 edit ... //depot/projects/ia64/sys/i386/i386/elf_machdep.c#3 edit ... //depot/projects/ia64/sys/ia64/ia32/ia32_misc.c#3 edit ... //depot/projects/ia64/sys/ia64/ia32/ia32_sysvec.c#1 add ... //depot/projects/ia64/sys/ia64/ia32/imgact_ia32.c#5 delete ... //depot/projects/ia64/sys/ia64/ia32/imgact_ia32.h#2 delete ... //depot/projects/ia64/sys/ia64/ia64/elf_machdep.c#5 edit ... //depot/projects/ia64/sys/kern/imgact_elf.c#6 edit ... //depot/projects/ia64/sys/powerpc/powerpc/elf_machdep.c#3 edit ... //depot/projects/ia64/sys/sparc64/sparc64/elf_machdep.c#3 edit ... //depot/projects/ia64/sys/sys/imgact_elf.h#4 edit ... //depot/projects/ia64/sys/sys/sysent.h#7 edit Differences ... ==== //depot/projects/ia64/sys/conf/files.ia64#8 (text+ko) ==== @@ -24,7 +24,7 @@ ia64/acpica/madt.c optional acpica ia64/ia32/ia32_misc.c optional ia32 ia64/ia32/ia32_sysent.c optional ia32 -ia64/ia32/imgact_ia32.c optional ia32 +ia64/ia32/ia32_sysvec.c optional ia32 ia64/ia64/ia64-gdbstub.c optional ddb ia64/ia64/autoconf.c standard ia64/ia64/busdma_machdep.c standard ==== //depot/projects/ia64/sys/i386/i386/elf_machdep.c#3 (text+ko) ==== @@ -30,6 +30,39 @@ #include #include +struct sysentvec elf32_freebsd_sysvec = { + SYS_MAXSYSCALL, + sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf32_freebsd_fixup, + sendsig, + sigcode, + &szsigcode, + 0, + "FreeBSD ELF32", + __elfN(coredump), + NULL, + MINSIGSTKSZ +}; + +static Elf32_Brandinfo freebsd_brand_info = { + ELFOSABI_FREEBSD, + EM_386, + "FreeBSD", + "", + "/usr/libexec/ld-elf.so.1", + &elf32_freebsd_sysvec + }; + +SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf32_insert_brand_entry, + &freebsd_brand_info); + /* Process one elf relocation with addend. */ int elf_reloc(linker_file_t lf, const void *data, int type) ==== //depot/projects/ia64/sys/ia64/ia32/ia32_misc.c#3 (text+ko) ==== ==== //depot/projects/ia64/sys/ia64/ia64/elf_machdep.c#5 (text+ko) ==== @@ -34,7 +34,45 @@ #include #include #include +#include +#include +#include +#include #include +#include + +struct sysentvec elf64_freebsd_sysvec = { + SYS_MAXSYSCALL, + sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf64_freebsd_fixup, + sendsig, + sigcode, + &szsigcode, + 0, + "FreeBSD ELF64", + __elfN(coredump), + NULL, + MINSIGSTKSZ +}; + +static Elf64_Brandinfo freebsd_brand_info = { + ELFOSABI_FREEBSD, + EM_IA_64, + "FreeBSD", + "", + "/usr/libexec/ld-elf.so.1", + &elf64_freebsd_sysvec + }; + +SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf64_insert_brand_entry, + &freebsd_brand_info); Elf_Addr link_elf_get_gp(linker_file_t); ==== //depot/projects/ia64/sys/kern/imgact_elf.c#6 (text+ko) ==== @@ -71,14 +71,12 @@ __ElfType(Auxargs); static int __elfN(check_header)(const Elf_Ehdr *hdr); -static int __elfN(freebsd_fixup)(register_t **stack_base, - struct image_params *imgp); static int __elfN(load_file)(struct proc *p, const char *file, u_long *addr, - u_long *entry); + u_long *entry, size_t pagesize); static int __elfN(load_section)(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, - vm_prot_t prot); + vm_prot_t prot, size_t pagesize); static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp); static int elf_trace = 0; @@ -88,45 +86,14 @@ SYSCTL_INT(_debug, OID_AUTO, elf64_trace, CTLFLAG_RW, &elf_trace, 0, ""); #endif -struct sysentvec __elfN(freebsd_sysvec) = { - SYS_MAXSYSCALL, - sysent, - 0, - 0, - 0, - 0, - 0, - 0, - __elfN(freebsd_fixup), - sendsig, - sigcode, - &szsigcode, - 0, - "FreeBSD ELF", - __elfN(coredump), - NULL, - MINSIGSTKSZ -}; +static Elf_Brandinfo *elf_brand_list[MAX_BRANDS]; -static Elf_Brandinfo freebsd_brand_info = { - ELFOSABI_FREEBSD, - "FreeBSD", - "", - "/usr/libexec/ld-elf.so.1", - &__elfN(freebsd_sysvec) - }; -static Elf_Brandinfo *elf_brand_list[MAX_BRANDS] = { - &freebsd_brand_info, - NULL, NULL, NULL, - NULL, NULL, NULL, NULL - }; - int __elfN(insert_brand_entry)(Elf_Brandinfo *entry) { int i; - for (i=1; ie_ident[EI_CLASS] != ELF_TARG_CLASS || hdr->e_ident[EI_DATA] != ELF_TARG_DATA || hdr->e_ident[EI_VERSION] != EV_CURRENT) return ENOEXEC; - if (!ELF_MACHINE_OK(hdr->e_machine)) + /* + * Make sure we have at least one brand for this machine. + */ + + for (i=0; imachine == hdr->e_machine) + break; + } + if (i == MAX_BRANDS) return ENOEXEC; if (hdr->e_version != ELF_TARG_VER) @@ -190,7 +167,136 @@ } static int -__elfN(load_section)(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot) +__elfN(map_partial)(vm_map_t map, vm_object_t object, vm_ooffset_t offset, + vm_offset_t start, vm_offset_t end, vm_prot_t prot, + vm_prot_t max) +{ + int error, rv; + vm_offset_t off; + vm_offset_t data_buf = 0; + + /* + * Create the page if it doesn't exist yet. Ignore errors. + */ + vm_map_lock(map); + vm_map_insert(map, NULL, 0, trunc_page(start), round_page(end), + max, max, 0); + vm_map_unlock(map); + + /* + * Find the page from the underlying object. + */ + if (object) { + vm_object_reference(object); + rv = vm_map_find(exec_map, + object, + trunc_page(offset), + &data_buf, + PAGE_SIZE, + TRUE, + VM_PROT_READ, + VM_PROT_ALL, + MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL); + if (rv != KERN_SUCCESS) { + vm_object_deallocate(object); + return rv; + } + + off = offset - trunc_page(offset); + error = copyout((caddr_t)data_buf+off, (caddr_t)start, end - start); + vm_map_remove(exec_map, data_buf, data_buf + PAGE_SIZE); + if (error) { + return KERN_FAILURE; + } + } + + return KERN_SUCCESS; +} + +static int +__elfN(map_insert)(vm_map_t map, vm_object_t object, vm_ooffset_t offset, + vm_offset_t start, vm_offset_t end, vm_prot_t prot, + vm_prot_t max, int cow) +{ + int rv; + + if (start != trunc_page(start)) { + rv = __elfN(map_partial)(map, object, offset, + start, round_page(start), prot, max); + if (rv) + return rv; + offset += round_page(start) - start; + start = round_page(start); + } + if (end != round_page(end)) { + rv = __elfN(map_partial)(map, object, + offset + trunc_page(end) - start, + trunc_page(end), end, prot, max); + if (rv) + return rv; + end = trunc_page(end); + } + if (end > start) { + if (offset & PAGE_MASK) { + vm_offset_t data_buf, off; + vm_size_t sz; + int error; + + /* + * The mapping is not page aligned. This means we have + * to copy the data. Sigh. + */ + rv = vm_map_find(map, 0, 0, + &start, end - start, + FALSE, prot, max, 0); + if (rv) + return rv; + while (start < end) { + vm_object_reference(object); + rv = vm_map_find(exec_map, + object, + trunc_page(offset), + &data_buf, + 2*PAGE_SIZE, + TRUE, + VM_PROT_READ, + VM_PROT_ALL, + (MAP_COPY_ON_WRITE + | MAP_PREFAULT_PARTIAL)); + if (rv != KERN_SUCCESS) { + vm_object_deallocate(object); + return rv; + } + off = offset - trunc_page(offset); + sz = end - start; + if (sz > PAGE_SIZE) + sz = PAGE_SIZE; + error = copyout((caddr_t)data_buf+off, + (caddr_t)start, sz); + vm_map_remove(exec_map, data_buf, + data_buf + 2*PAGE_SIZE); + if (error) { + return KERN_FAILURE; + } + start += sz; + } + rv = KERN_SUCCESS; + } else { + vm_map_lock(map); + rv = vm_map_insert(map, object, offset, start, end, + prot, max, cow); + vm_map_unlock(map); + } + return rv; + } else { + return KERN_SUCCESS; + } +} + +static int +__elfN(load_section)(struct proc *p, struct vmspace *vmspace, + struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, + size_t memsz, size_t filsz, vm_prot_t prot, size_t pagesize) { size_t map_len; vm_offset_t map_addr; @@ -220,8 +326,11 @@ return (ENOEXEC); } - map_addr = trunc_page((vm_offset_t)vmaddr); - file_addr = trunc_page(offset); +#define trunc_page_ps(va, ps) ((va) & ~(ps - 1)) +#define round_page_ps(va, ps) (((va) + (ps - 1)) & ~(ps - 1)) + + map_addr = trunc_page_ps((vm_offset_t)vmaddr, pagesize); + file_addr = trunc_page_ps(offset, pagesize); /* * We have two choices. We can either clear the data in the last page @@ -230,14 +339,13 @@ * choose the second.. */ if (memsz > filsz) - map_len = trunc_page(offset+filsz) - file_addr; + map_len = trunc_page_ps(offset+filsz, pagesize) - file_addr; else - map_len = round_page(offset+filsz) - file_addr; + map_len = round_page_ps(offset+filsz, pagesize) - file_addr; if (map_len != 0) { vm_object_reference(object); - vm_map_lock(&vmspace->vm_map); - rv = vm_map_insert(&vmspace->vm_map, + rv = __elfN(map_insert)(&vmspace->vm_map, object, file_addr, /* file offset */ map_addr, /* virtual start */ @@ -245,7 +353,6 @@ prot, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_PREFAULT); - vm_map_unlock(&vmspace->vm_map); if (rv != KERN_SUCCESS) { vm_object_deallocate(object); return EINVAL; @@ -264,23 +371,22 @@ * segment in the file is extended to provide bss. It's a neat idea * to try and save a page, but it's a pain in the behind to implement. */ - copy_len = (offset + filsz) - trunc_page(offset + filsz); - map_addr = trunc_page((vm_offset_t)vmaddr + filsz); - map_len = round_page((vm_offset_t)vmaddr + memsz) - map_addr; + copy_len = (offset + filsz) - trunc_page_ps(offset + filsz, pagesize); + map_addr = trunc_page_ps((vm_offset_t)vmaddr + filsz, pagesize); + map_len = round_page_ps((vm_offset_t)vmaddr + memsz, pagesize) - map_addr; /* This had damn well better be true! */ if (map_len != 0) { - vm_map_lock(&vmspace->vm_map); - rv = vm_map_insert(&vmspace->vm_map, NULL, 0, - map_addr, map_addr + map_len, - VM_PROT_ALL, VM_PROT_ALL, 0); - vm_map_unlock(&vmspace->vm_map); + rv = __elfN(map_insert)(&vmspace->vm_map, NULL, 0, + map_addr, map_addr + map_len, + VM_PROT_ALL, VM_PROT_ALL, 0); if (rv != KERN_SUCCESS) { return EINVAL; } } if (copy_len != 0) { + vm_offset_t off; vm_object_reference(object); rv = vm_map_find(exec_map, object, @@ -297,7 +403,10 @@ } /* send the page fragment to user space */ - error = copyout((caddr_t)data_buf, (caddr_t)map_addr, copy_len); + off = trunc_page_ps(offset + filsz, pagesize) + - trunc_page(offset + filsz); + error = copyout((caddr_t)data_buf+off, (caddr_t)map_addr, + copy_len); vm_map_remove(exec_map, data_buf, data_buf + PAGE_SIZE); if (error) { return (error); @@ -326,7 +435,8 @@ * the entry point for the loaded file. */ static int -__elfN(load_file)(struct proc *p, const char *file, u_long *addr, u_long *entry) +__elfN(load_file)(struct proc *p, const char *file, u_long *addr, + u_long *entry, size_t pagesize) { struct { struct nameidata nd; @@ -434,7 +544,7 @@ (caddr_t)(uintptr_t)phdr[i].p_vaddr + rbase, phdr[i].p_memsz, - phdr[i].p_filesz, prot)) != 0) + phdr[i].p_filesz, prot, pagesize)) != 0) goto fail; /* * Establish the base address if this is the @@ -475,6 +585,7 @@ u_long text_size = 0, data_size = 0; u_long text_addr = 0, data_addr = 0; u_long addr, entry = 0, proghdr = 0; + vm_offset_t maxuser, usrstack, pagesize; int error, i; const char *interp = NULL; Elf_Brandinfo *brand_info; @@ -517,8 +628,38 @@ if ((error = exec_extract_strings(imgp)) != 0) goto fail; - exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, - USRSTACK); + /* + * Tentatively identify the brand based on the machine so that + * we can figure out VM ranges and page sizes. + */ + brand_info = NULL; + for (i = 0; i < MAX_BRANDS; i++) { + Elf_Brandinfo *bi = elf_brand_list[i]; + + if (bi != NULL && + hdr->e_machine == bi->machine && + (hdr->e_ident[EI_OSABI] == bi->brand + || 0 == + strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND], + bi->compat_3_brand, strlen(bi->compat_3_brand)))) { + brand_info = bi; + break; + } + } + + pagesize = PAGE_SIZE; + maxuser = VM_MAXUSER_ADDRESS; + usrstack = USRSTACK; + if (brand_info) { + if (brand_info->sysvec->sv_pagesize) + pagesize = brand_info->sysvec->sv_pagesize; + if (brand_info->sysvec->sv_maxuser) + maxuser = brand_info->sysvec->sv_maxuser; + if (brand_info->sysvec->sv_usrstack) + usrstack = brand_info->sysvec->sv_usrstack; + } + + exec_new_vmspace(imgp, VM_MIN_ADDRESS, maxuser, usrstack); vmspace = imgp->proc->p_vmspace; @@ -540,7 +681,7 @@ phdr[i].p_offset, (caddr_t)(uintptr_t)phdr[i].p_vaddr, phdr[i].p_memsz, - phdr[i].p_filesz, prot)) != 0) + phdr[i].p_filesz, prot, pagesize)) != 0) goto fail; /* @@ -602,6 +743,7 @@ Elf_Brandinfo *bi = elf_brand_list[i]; if (bi != NULL && + hdr->e_machine == bi->machine && (hdr->e_ident[EI_OSABI] == bi->brand || 0 == strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND], @@ -618,6 +760,7 @@ Elf_Brandinfo *bi = elf_brand_list[i]; if (bi != NULL && + hdr->e_machine == bi->machine && strcmp(interp, bi->interp_path) == 0) { brand_info = bi; break; @@ -630,7 +773,9 @@ for (i = 0; i < MAX_BRANDS; i++) { Elf_Brandinfo *bi = elf_brand_list[i]; - if (bi != NULL && fallback_elf_brand == bi->brand) { + if (bi != NULL && + hdr->e_machine == bi->machine && + fallback_elf_brand == bi->brand) { brand_info = bi; break; } @@ -650,10 +795,11 @@ snprintf(path, MAXPATHLEN, "%s%s", brand_info->emul_path, interp); if ((error = __elfN(load_file)(imgp->proc, path, &addr, - &imgp->entry_addr)) != 0) { + &imgp->entry_addr, + pagesize)) != 0) { if ((error = __elfN(load_file) (imgp->proc, interp, &addr, - &imgp->entry_addr)) != 0) { + &imgp->entry_addr, pagesize)) != 0) { uprintf("ELF interpreter %s not found\n", path); free(path, M_TEMP); goto fail; @@ -683,7 +829,13 @@ return error; } -static int +#if __ELF_WORD_SIZE == 32 +#define suword suword32 +#else +#define suword suword64 +#endif + +int __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp) { Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs; ==== //depot/projects/ia64/sys/powerpc/powerpc/elf_machdep.c#3 (text+ko) ==== @@ -36,6 +36,39 @@ #include #include +struct sysentvec elf32_freebsd_sysvec = { + SYS_MAXSYSCALL, + sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf32_freebsd_fixup, + sendsig, + sigcode, + &szsigcode, + 0, + "FreeBSD ELF32", + __elfN(coredump), + NULL, + MINSIGSTKSZ +}; + +static Elf32_Brandinfo freebsd_brand_info = { + ELFOSABI_FREEBSD, + EM_PPC, + "FreeBSD", + "", + "/usr/libexec/ld-elf.so.1", + &elf32_freebsd_sysvec + }; + +SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf32_insert_brand_entry, + &freebsd_brand_info); + /* Process one elf relocation with addend. */ int elf_reloc(linker_file_t lf, const void *data, int type) ==== //depot/projects/ia64/sys/sparc64/sparc64/elf_machdep.c#3 (text+ko) ==== @@ -46,6 +46,39 @@ #include "linker_if.h" +struct sysentvec elf64_freebsd_sysvec = { + SYS_MAXSYSCALL, + sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf64_freebsd_fixup, + sendsig, + sigcode, + &szsigcode, + 0, + "FreeBSD ELF64", + __elfN(coredump), + NULL, + MINSIGSTKSZ +}; + +static Elf64_Brandinfo freebsd_brand_info = { + ELFOSABI_FREEBSD, + EM_SPARCV9, + "FreeBSD", + "", + "/usr/libexec/ld-elf.so.1", + &elf64_freebsd_sysvec + }; + +SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf64_insert_brand_entry, + &freebsd_brand_info); + /* * The following table holds for each relocation type: * - the width in bits of the memory location the relocation ==== //depot/projects/ia64/sys/sys/imgact_elf.h#4 (text+ko) ==== @@ -59,6 +59,7 @@ typedef struct { int brand; + int machine; const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */ const char *emul_path; const char *interp_path; @@ -70,6 +71,7 @@ int elf32_brand_inuse(Elf32_Brandinfo *entry); int elf32_insert_brand_entry(Elf32_Brandinfo *entry); int elf32_remove_brand_entry(Elf32_Brandinfo *entry); +int elf32_freebsd_fixup(register_t **, struct image_params *); int elf32_coredump(struct thread *, struct vnode *, off_t); #else /* !(ELF_TARG_CLASS == ELFCLASS32) */ @@ -92,6 +94,7 @@ typedef struct { int brand; + int machine; const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */ const char *emul_path; const char *interp_path; @@ -103,6 +106,7 @@ int elf64_brand_inuse(Elf64_Brandinfo *entry); int elf64_insert_brand_entry(Elf64_Brandinfo *entry); int elf64_remove_brand_entry(Elf64_Brandinfo *entry); +int elf64_freebsd_fixup(register_t **, struct image_params *); int elf64_coredump(struct thread *, struct vnode *, off_t); #endif /* ELF_TARG_CLASS == ELFCLASS32 */ ==== //depot/projects/ia64/sys/sys/sysent.h#7 (text+ko) ==== @@ -79,6 +79,9 @@ /* function to dump core, or NULL */ int (*sv_imgact_try)(struct image_params *); int sv_minsigstksz; /* minimum signal stack size */ + int sv_pagesize; /* pagesize override */ + vm_offset_t sv_maxuser; /* VM_MAXUSER_ADDRESS override */ + vm_offset_t sv_usrstack; /* USRSTACK override */ register_t *(*sv_copyout_strings)(struct image_params *); void (*sv_setregs)(struct thread *, u_long, u_long, u_long); }; To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe p4-projects" in the body of the message