add support for more than 2 PT_LOAD sections. from OpenBSD.

This commit is contained in:
chs 2003-12-07 02:18:53 +00:00
parent 961d62cfa5
commit 291c877a9c

View File

@ -1,4 +1,4 @@
/* $NetBSD: exec_elf32.c,v 1.95 2003/10/31 14:00:52 drochner Exp $ */
/* $NetBSD: exec_elf32.c,v 1.96 2003/12/07 02:18:53 chs Exp $ */
/*-
* Copyright (c) 1994, 2000 The NetBSD Foundation, Inc.
@ -64,7 +64,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(1, "$NetBSD: exec_elf32.c,v 1.95 2003/10/31 14:00:52 drochner Exp $");
__KERNEL_RCSID(1, "$NetBSD: exec_elf32.c,v 1.96 2003/12/07 02:18:53 chs Exp $");
/* If not included by exec_elf64.c, ELFSIZE won't be defined. */
#ifndef ELFSIZE
@ -537,7 +537,7 @@ ELFNAME2(exec,makecmds)(struct proc *p, struct exec_package *epp)
Elf_Ehdr *eh = epp->ep_hdr;
Elf_Phdr *ph, *pp;
Elf_Addr phdr = 0, pos = 0;
int error, i, nload;
int error, i;
char *interp = NULL;
u_long phsize;
@ -611,7 +611,7 @@ ELFNAME2(exec,makecmds)(struct proc *p, struct exec_package *epp)
/*
* Load all the necessary sections
*/
for (i = nload = 0; i < eh->e_phnum; i++) {
for (i = 0; i < eh->e_phnum; i++) {
Elf_Addr addr = ELFDEFNNAME(NO_ADDR);
u_long size = 0;
int prot = 0;
@ -620,30 +620,49 @@ ELFNAME2(exec,makecmds)(struct proc *p, struct exec_package *epp)
switch (ph[i].p_type) {
case PT_LOAD:
/*
* XXX
* Can handle only 2 sections: text and data
* Calcuate size of the text and data segments
* by starting at first and going to end of last.
* 'rwx' sections are treated as data.
*/
if (nload++ == 2)
goto bad;
ELFNAME(load_psection)(&epp->ep_vmcmds, epp->ep_vp,
&ph[i], &addr, &size, &prot, VMCMD_FIXED);
/*
* Decide whether it's text or data by looking
* at the entry point.
* at the protection of the section.
*/
if (eh->e_entry >= addr &&
eh->e_entry < (addr + size)) {
if (prot & VM_PROT_WRITE) {
/* data section */
if (epp->ep_dsize == ELFDEFNNAME(NO_ADDR)) {
epp->ep_daddr = addr;
epp->ep_dsize = size;
} else {
if (addr < epp->ep_daddr) {
epp->ep_dsize =
epp->ep_dsize +
epp->ep_daddr - addr;
epp->ep_daddr = addr;
} else
epp->ep_dsize = addr + size -
epp->ep_daddr;
}
} else if (prot & VM_PROT_EXECUTE) {
/* text section */
if (epp->ep_tsize == ELFDEFNNAME(NO_ADDR)) {
epp->ep_taddr = addr;
epp->ep_tsize = size;
if (epp->ep_daddr == ELFDEFNNAME(NO_ADDR)) {
epp->ep_daddr = addr;
epp->ep_dsize = size;
}
} else {
epp->ep_daddr = addr;
epp->ep_dsize = size;
if (addr < epp->ep_taddr) {
epp->ep_tsize =
epp->ep_tsize +
epp->ep_taddr - addr;
epp->ep_taddr = addr;
} else
epp->ep_tsize = addr + size -
epp->ep_taddr;
}
}
break;