summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormp <mp@FreeBSD.org>2001-08-16 16:14:26 +0000
committermp <mp@FreeBSD.org>2001-08-16 16:14:26 +0000
commit02116da56f78945e44ba97aaf2f7774a11ebf518 (patch)
tree39fa0e018667d659b119ac4e5b4fcfed7738b386 /sys
parent5173ef4080b384dfe0dae40d923624285b1f4f12 (diff)
downloadFreeBSD-src-02116da56f78945e44ba97aaf2f7774a11ebf518.zip
FreeBSD-src-02116da56f78945e44ba97aaf2f7774a11ebf518.tar.gz
Reduce stack allocation (stack-fast?).
elf_load_file() => 352 to 52 bytes exec_elf_imgact() => 1072 to 48 bytes elf_corehdr() => 396 to 8 bytes Reviewed by: julian
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/imgact_elf.c105
1 files changed, 65 insertions, 40 deletions
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index ff18d0e..96ef2df 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -326,48 +326,57 @@ elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_o
static int
elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry)
{
+ struct {
+ struct nameidata nd;
+ struct vattr attr;
+ struct image_params image_params;
+ } *tempdata;
const Elf_Ehdr *hdr = NULL;
const Elf_Phdr *phdr = NULL;
- struct nameidata nd;
+ struct nameidata *nd;
struct vmspace *vmspace = p->p_vmspace;
- struct vattr attr;
- struct image_params image_params, *imgp;
+ struct vattr *attr;
+ struct image_params *imgp;
vm_prot_t prot;
u_long rbase;
u_long base_addr = 0;
int error, i, numsegs;
- imgp = &image_params;
+ tempdata = malloc(sizeof(*tempdata), M_TEMP, M_WAITOK);
+ nd = &tempdata->nd;
+ attr = &tempdata->attr;
+ imgp = &tempdata->image_params;
+
/*
* Initialize part of the common data
*/
imgp->proc = p;
imgp->uap = NULL;
- imgp->attr = &attr;
+ imgp->attr = attr;
imgp->firstpage = NULL;
imgp->image_header = (char *)kmem_alloc_wait(exec_map, PAGE_SIZE);
if (imgp->image_header == NULL) {
- nd.ni_vp = NULL;
+ nd->ni_vp = NULL;
error = ENOMEM;
goto fail;
}
- NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p);
+ NDINIT(nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p);
- if ((error = namei(&nd)) != 0) {
- nd.ni_vp = NULL;
+ if ((error = namei(nd)) != 0) {
+ nd->ni_vp = NULL;
goto fail;
}
- NDFREE(&nd, NDF_ONLY_PNBUF);
- imgp->vp = nd.ni_vp;
+ NDFREE(nd, NDF_ONLY_PNBUF);
+ imgp->vp = nd->ni_vp;
/*
* Check permissions, modes, uid, etc on the file, and "open" it.
*/
error = exec_check_permissions(imgp);
if (error) {
- VOP_UNLOCK(nd.ni_vp, 0, p);
+ VOP_UNLOCK(nd->ni_vp, 0, p);
goto fail;
}
@@ -377,8 +386,8 @@ elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry)
* its VTEXT flag, too.
*/
if (error == 0)
- nd.ni_vp->v_flag |= VTEXT;
- VOP_UNLOCK(nd.ni_vp, 0, p);
+ nd->ni_vp->v_flag |= VTEXT;
+ VOP_UNLOCK(nd->ni_vp, 0, p);
if (error)
goto fail;
@@ -413,7 +422,7 @@ elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry)
if (phdr[i].p_flags & PF_R)
prot |= VM_PROT_READ;
- if ((error = elf_load_section(p, vmspace, nd.ni_vp,
+ if ((error = elf_load_section(p, vmspace, nd->ni_vp,
phdr[i].p_offset,
(caddr_t)phdr[i].p_vaddr +
rbase,
@@ -438,8 +447,10 @@ fail:
if (imgp->image_header)
kmem_free_wakeup(exec_map, (vm_offset_t)imgp->image_header,
PAGE_SIZE);
- if (nd.ni_vp)
- vrele(nd.ni_vp);
+ if (nd->ni_vp)
+ vrele(nd->ni_vp);
+
+ free(tempdata, M_TEMP);
return error;
}
@@ -466,7 +477,7 @@ exec_elf_imgact(struct image_params *imgp)
int error, i;
const char *interp = NULL;
Elf_Brandinfo *brand_info;
- char path[MAXPATHLEN];
+ char *path;
GIANT_REQUIRED;
@@ -632,6 +643,7 @@ exec_elf_imgact(struct image_params *imgp)
imgp->proc->p_sysent = brand_info->sysvec;
if (interp != NULL) {
+ path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
snprintf(path, sizeof(path), "%s%s",
brand_info->emul_path, interp);
if ((error = elf_load_file(imgp->proc, path, &addr,
@@ -639,9 +651,11 @@ exec_elf_imgact(struct image_params *imgp)
if ((error = elf_load_file(imgp->proc, interp, &addr,
&imgp->entry_addr)) != 0) {
uprintf("ELF interpreter %s not found\n", path);
+ free(path, M_TEMP);
goto fail;
}
}
+ free(path, M_TEMP);
}
/*
@@ -898,36 +912,47 @@ elf_corehdr(p, vp, cred, numsegs, hdr, hdrsize)
size_t hdrsize;
void *hdr;
{
+ struct {
+ prstatus_t status;
+ prfpregset_t fpregset;
+ prpsinfo_t psinfo;
+ } *tempdata;
size_t off;
- prstatus_t status;
- prfpregset_t fpregset;
- prpsinfo_t psinfo;
+ prstatus_t *status;
+ prfpregset_t *fpregset;
+ prpsinfo_t *psinfo;
+
+ tempdata = malloc(sizeof(*tempdata), M_TEMP, M_ZERO);
+ status = &tempdata->status;
+ fpregset = &tempdata->fpregset;
+ psinfo = &tempdata->psinfo;
/* Gather the information for the header. */
- bzero(&status, sizeof status);
- status.pr_version = PRSTATUS_VERSION;
- status.pr_statussz = sizeof(prstatus_t);
- status.pr_gregsetsz = sizeof(gregset_t);
- status.pr_fpregsetsz = sizeof(fpregset_t);
- status.pr_osreldate = osreldate;
- status.pr_cursig = p->p_sig;
- status.pr_pid = p->p_pid;
- fill_regs(p, &status.pr_reg);
-
- fill_fpregs(p, &fpregset);
-
- bzero(&psinfo, sizeof psinfo);
- psinfo.pr_version = PRPSINFO_VERSION;
- psinfo.pr_psinfosz = sizeof(prpsinfo_t);
- strncpy(psinfo.pr_fname, p->p_comm, sizeof(psinfo.pr_fname) - 1);
- psinfo.pr_fname[sizeof(psinfo.pr_fname) - 1] = '\0';
+ status->pr_version = PRSTATUS_VERSION;
+ status->pr_statussz = sizeof(prstatus_t);
+ status->pr_gregsetsz = sizeof(gregset_t);
+ status->pr_fpregsetsz = sizeof(fpregset_t);
+ status->pr_osreldate = osreldate;
+ status->pr_cursig = p->p_sig;
+ status->pr_pid = p->p_pid;
+ fill_regs(p, &status->pr_reg);
+
+ fill_fpregs(p, fpregset);
+
+ psinfo->pr_version = PRPSINFO_VERSION;
+ psinfo->pr_psinfosz = sizeof(prpsinfo_t);
+ strncpy(psinfo->pr_fname, p->p_comm, sizeof(psinfo->pr_fname) - 1);
+ psinfo->pr_fname[sizeof(psinfo->pr_fname) - 1] = '\0';
+
/* XXX - We don't fill in the command line arguments properly yet. */
- strncpy(psinfo.pr_psargs, p->p_comm, PRARGSZ);
+ strncpy(psinfo->pr_psargs, p->p_comm, PRARGSZ);
/* Fill in the header. */
bzero(hdr, hdrsize);
off = 0;
- elf_puthdr(p, hdr, &off, &status, &fpregset, &psinfo, numsegs);
+ elf_puthdr(p, hdr, &off, status, fpregset, psinfo, numsegs);
+
+ free(tempdata, M_TEMP);
/* Write it to the core file. */
return vn_rdwr(UIO_WRITE, vp, hdr, hdrsize, (off_t)0,
OpenPOWER on IntegriCloud