First implementation of syssgi(SGI_ELFMAP).
This commit is contained in:
parent
7054731317
commit
cde20c2503
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: irix_syssgi.c,v 1.1 2001/11/28 12:00:54 manu Exp $ */
|
||||
/* $NetBSD: irix_syssgi.c,v 1.2 2001/11/30 21:56:03 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -37,9 +37,29 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: irix_syssgi.c,v 1.1 2001/11/28 12:00:54 manu Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: irix_syssgi.c,v 1.2 2001/11/30 21:56:03 manu Exp $");
|
||||
|
||||
#ifndef ELFSIZE
|
||||
#define ELFSIZE 32
|
||||
#endif
|
||||
|
||||
/* round up and down to page boundaries. Borrowed from sys/kern/exec_elf32.c */
|
||||
#define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1))
|
||||
#define ELF_TRUNC(a, b) ((a) & ~((b) - 1))
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/filedesc.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/exec_elf.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
#include <compat/svr4/svr4_types.h>
|
||||
|
||||
|
@ -48,6 +68,9 @@ __KERNEL_RCSID(0, "$NetBSD: irix_syssgi.c,v 1.1 2001/11/28 12:00:54 manu Exp $")
|
|||
#include <compat/irix/irix_syscallargs.h>
|
||||
#include <compat/irix/irix_syssgi.h>
|
||||
|
||||
static int irix_syssgi_mapelf __P((int, Elf_Phdr *, int,
|
||||
struct proc *, register_t *));
|
||||
|
||||
int
|
||||
irix_sys_syssgi(p, v, retval)
|
||||
struct proc *p;
|
||||
|
@ -62,9 +85,224 @@ irix_sys_syssgi(p, v, retval)
|
|||
syscallarg(void *) arg4;
|
||||
syscallarg(void *) arg5;
|
||||
} */ *uap = v;
|
||||
int request = SCARG(uap, request);
|
||||
void *arg1, *arg2, *arg3;
|
||||
|
||||
#ifdef DEBUG_IRIX
|
||||
printf("irix_syssgi(): request = %d\n", SCARG(uap, request));
|
||||
printf("irix_syssgi(): request = %d\n", request);
|
||||
#endif
|
||||
switch(request) {
|
||||
case IRIX_SGI_SYSID: /* Get HostID */
|
||||
*retval = (register_t)hostid;
|
||||
break;
|
||||
|
||||
case IRIX_SGI_RDNAME: { /* Read Processes' name */
|
||||
struct proc *tp;
|
||||
|
||||
arg1 = SCARG(uap, arg1); /* PID of the process */
|
||||
arg2 = SCARG(uap, arg2); /* Adress of user buffer */
|
||||
arg3 = SCARG(uap, arg3); /* Length of user buffer */
|
||||
if (!uvm_useracc((caddr_t)arg2, (size_t)arg2, B_WRITE))
|
||||
return EACCES;
|
||||
|
||||
tp = pfind((pid_t)arg1);
|
||||
if (tp == NULL || \
|
||||
tp->p_psstr == NULL || \
|
||||
tp->p_psstr->ps_argvstr == NULL || \
|
||||
tp->p_psstr->ps_argvstr[0] == NULL)
|
||||
return 0;
|
||||
|
||||
*retval = (register_t)copyout(tp->p_psstr->ps_argvstr[0],
|
||||
(void *)arg2, (size_t)arg3);
|
||||
|
||||
break;
|
||||
}
|
||||
case IRIX_SGI_TUNE: /* Tune system variables */
|
||||
case IRIX_SGI_IDBG: /* Kernel debugging */
|
||||
case IRIX_SGI_INVENT: /* Get system inventory */
|
||||
case IRIX_SGI_SETLED: /* Turn on/off LEDs */
|
||||
case IRIX_SGI_SETNVRAM: /* Sets a NVRAM variable value */
|
||||
case IRIX_SGI_GETNVRAM: /* Gets a NVRAM variable value */
|
||||
return EINVAL;
|
||||
break;
|
||||
|
||||
case IRIX_SGI_ELFMAP: /* Maps an ELF image */
|
||||
arg1 = SCARG(uap, arg1); /* file descriptor */
|
||||
arg2 = SCARG(uap, arg2); /* ptr to ELF program header array */
|
||||
arg3 = SCARG(uap, arg3); /* array's length */
|
||||
return irix_syssgi_mapelf((int)arg1, (Elf_Phdr *)arg2,
|
||||
(int)arg3, p, retval);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Warning: call to unimplemented syssgi() command %d\n",
|
||||
request);
|
||||
return EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define INSANE_DEBUG_IRIX
|
||||
static int
|
||||
irix_syssgi_mapelf(fd, ph, count, p, retval)
|
||||
int fd;
|
||||
Elf_Phdr *ph;
|
||||
int count;
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
{
|
||||
Elf_Phdr *kph;
|
||||
Elf_Phdr *pht;
|
||||
int error = 0;
|
||||
int i,j;
|
||||
int prot;
|
||||
int flags;
|
||||
u_long size;
|
||||
u_long addr, uaddr, msize, psize, rm, rf;
|
||||
long diff, offset;
|
||||
struct file *fp;
|
||||
struct filedesc *fdp;
|
||||
struct exec_vmcmd_set vcset;
|
||||
struct exec_vmcmd *base_vcp = NULL;
|
||||
struct vnode *vp;
|
||||
|
||||
#ifdef INSANE_DEBUG_IRIX
|
||||
printf("irix_syssgi_mapelf(): fd = %d, *ph = %p, count = %d\n",
|
||||
fd, ph, count);
|
||||
#endif
|
||||
/* Check that the program header array is readable by the process */
|
||||
if (!uvm_useracc((caddr_t)ph, sizeof(Elf_Phdr) * count, B_READ))
|
||||
return EACCES;
|
||||
|
||||
kph = (Elf_Phdr *)malloc(sizeof(Elf_Phdr) * count,
|
||||
M_TEMP, M_WAITOK);
|
||||
|
||||
error = copyin(ph, kph, sizeof(Elf_Phdr) * count);
|
||||
if (error)
|
||||
goto bad;
|
||||
|
||||
/* Check that each ELF sections is loadable */
|
||||
pht = kph;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (pht->p_type != PT_LOAD) {
|
||||
error = ENOEXEC;
|
||||
goto bad;
|
||||
}
|
||||
pht++;
|
||||
}
|
||||
|
||||
/* Find the file's vnode */
|
||||
fdp = p->p_fd;
|
||||
fp = fd_getfile(fdp, fd);
|
||||
if (fp == NULL) {
|
||||
error = EBADF;
|
||||
goto bad;
|
||||
}
|
||||
vp = (struct vnode *)fp->f_data;
|
||||
|
||||
/* Map each sections. Borrowed from sys/kern/exec_elf32.c */
|
||||
FILE_USE(fp);
|
||||
pht = kph;
|
||||
for (i = 0; i < count; i++) {
|
||||
vcset.evs_cnt = 0;
|
||||
vcset.evs_used = 0;
|
||||
|
||||
addr = pht->p_vaddr;
|
||||
uaddr = pht->p_vaddr;
|
||||
if (pht->p_align > 1)
|
||||
addr = ELF_TRUNC(uaddr, pht->p_align);
|
||||
diff = uaddr - addr;
|
||||
|
||||
prot |= (pht->p_flags & PF_R) ? VM_PROT_READ : 0;
|
||||
prot |= (pht->p_flags & PF_W) ? VM_PROT_WRITE : 0;
|
||||
prot |= (pht->p_flags & PF_X) ? VM_PROT_EXECUTE : 0;
|
||||
|
||||
offset = pht->p_offset - diff;
|
||||
size = pht->p_filesz + diff;
|
||||
msize = pht->p_memsz + diff;
|
||||
|
||||
if (pht->p_align >= PAGE_SIZE) {
|
||||
if ((pht->p_flags & PF_W) != 0) {
|
||||
/*
|
||||
* Because the pagedvn pager can't handle zero
|
||||
* fill of the last data page if it's not
|
||||
* page aligned we map the last page readvn.
|
||||
*/
|
||||
psize = trunc_page(size);
|
||||
} else {
|
||||
psize = round_page(size);
|
||||
}
|
||||
} else {
|
||||
psize = size;
|
||||
}
|
||||
|
||||
if (psize > 0) {
|
||||
#ifdef INSANE_DEBUG_IRIX
|
||||
printf("irix_mapelf(): psize > 0; NEW_VMCMD2\n");
|
||||
printf("psize = 0x%lx, addr = 0x%lx\n", psize, addr);
|
||||
printf("vp = %p, offset = 0x%lx\n", vp, offset);
|
||||
printf("pht->p_align = 0x%lx\n", (long)pht->p_align);
|
||||
#endif
|
||||
NEW_VMCMD2(&vcset, pht->p_align < PAGE_SIZE ?
|
||||
vmcmd_map_readvn : vmcmd_map_pagedvn, psize,
|
||||
addr, vp, offset, prot, flags);
|
||||
}
|
||||
if (psize < size) {
|
||||
#ifdef INSANE_DEBUG_IRIX
|
||||
printf("irix_mapelf(): psize < size; NEW_VMCMD2\n");
|
||||
#endif
|
||||
NEW_VMCMD2(&vcset, vmcmd_map_readvn, size - psize,
|
||||
addr + psize, vp, offset + psize, prot,
|
||||
psize > 0 ? flags & VMCMD_RELATIVE : flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we need to extend the size of the segment
|
||||
*/
|
||||
rm = round_page(addr + msize);
|
||||
rf = round_page(addr + size);
|
||||
|
||||
if (rm != rf) {
|
||||
#ifdef INSANE_DEBUG_IRIX
|
||||
printf("irix_mapelf(): rm != rf; NEW_VMCMD2\n");
|
||||
#endif
|
||||
NEW_VMCMD2(&vcset, vmcmd_map_zero, rm - rf, rf, NULLVP,
|
||||
0, prot, flags & VMCMD_RELATIVE);
|
||||
size = msize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run the vmcmds
|
||||
*/
|
||||
for (j = 0; j < vcset.evs_used && !error; j++) {
|
||||
struct exec_vmcmd *vcp;
|
||||
|
||||
vcp = &vcset.evs_cmds[j];
|
||||
if (vcp->ev_flags & VMCMD_RELATIVE) {
|
||||
vcp->ev_addr += base_vcp->ev_addr;
|
||||
}
|
||||
#ifdef INSANE_DEBUG_IRIX
|
||||
printf("irix_syssgi_mapelf(): mapping i = %d, j = %d, *pht = %p\n",
|
||||
i, j, pht);
|
||||
printf("addr = 0x%lx, uaddr = 0x%lx, size = 0x%lx, msize = 0x%lx\n",
|
||||
addr, uaddr, size, msize);
|
||||
printf("psize = 0x%lx, rm = 0x%lx, rf = 0x%lx\n",
|
||||
psize, rm, rf);
|
||||
#endif
|
||||
error = (*vcp->ev_proc)(p, vcp);
|
||||
|
||||
if (vcp->ev_flags & VMCMD_BASE)
|
||||
base_vcp = vcp;
|
||||
}
|
||||
pht++;
|
||||
}
|
||||
|
||||
FILE_UNUSE(fp, p);
|
||||
|
||||
*retval = (register_t)kph->p_vaddr;
|
||||
bad:
|
||||
free(kph, M_TEMP);
|
||||
return error;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue