VFS/RS support for ELF
This commit is contained in:
7
lib/libexec/Makefile
Normal file
7
lib/libexec/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
# Makefile for libexec
|
||||
|
||||
LIB= exec
|
||||
|
||||
SRCS= exec_aout.c exec_elf.c
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
86
lib/libexec/exec_aout.c
Normal file
86
lib/libexec/exec_aout.c
Normal file
@@ -0,0 +1,86 @@
|
||||
#define _SYSTEM 1
|
||||
|
||||
#include <minix/type.h>
|
||||
#include <minix/const.h>
|
||||
#include <a.out.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <libexec.h>
|
||||
|
||||
int read_header_aout(
|
||||
const char *exec_hdr, /* executable header */
|
||||
size_t exec_len, /* executable file size */
|
||||
int *sep_id, /* true iff sep I&D */
|
||||
vir_bytes *text_bytes, /* place to return text size */
|
||||
vir_bytes *data_bytes, /* place to return initialized data size */
|
||||
vir_bytes *bss_bytes, /* place to return bss size */
|
||||
phys_bytes *tot_bytes, /* place to return total size */
|
||||
vir_bytes *pc, /* program entry point (initial PC) */
|
||||
int *hdrlenp
|
||||
)
|
||||
{
|
||||
/* Read the header and extract the text, data, bss and total sizes from it. */
|
||||
struct exec *hdr; /* a.out header is read in here */
|
||||
|
||||
/* Read the header and check the magic number. The standard MINIX header
|
||||
* is defined in <a.out.h>. It consists of 8 chars followed by 6 longs.
|
||||
* Then come 4 more longs that are not used here.
|
||||
* Byte 0: magic number 0x01
|
||||
* Byte 1: magic number 0x03
|
||||
* Byte 2: normal = 0x10 (not checked, 0 is OK), separate I/D = 0x20
|
||||
* Byte 3: CPU type, Intel 16 bit = 0x04, Intel 32 bit = 0x10,
|
||||
* Motorola = 0x0B, Sun SPARC = 0x17
|
||||
* Byte 4: Header length = 0x20
|
||||
* Bytes 5-7 are not used.
|
||||
*
|
||||
* Now come the 6 longs
|
||||
* Bytes 8-11: size of text segments in bytes
|
||||
* Bytes 12-15: size of initialized data segment in bytes
|
||||
* Bytes 16-19: size of bss in bytes
|
||||
* Bytes 20-23: program entry point
|
||||
* Bytes 24-27: total memory allocated to program (text, data + stack)
|
||||
* Bytes 28-31: size of symbol table in bytes
|
||||
* The longs are represented in a machine dependent order,
|
||||
* little-endian on the 8088, big-endian on the 68000.
|
||||
* The header is followed directly by the text and data segments, and the
|
||||
* symbol table (if any). The sizes are given in the header. Only the
|
||||
* text and data segments are copied into memory by exec. The header is
|
||||
* used here only. The symbol table is for the benefit of a debugger and
|
||||
* is ignored here.
|
||||
*/
|
||||
|
||||
assert(exec_hdr != NULL);
|
||||
|
||||
hdr = (struct exec *)exec_hdr;
|
||||
if (exec_len < A_MINHDR) return(ENOEXEC);
|
||||
|
||||
/* Check magic number, cpu type, and flags. */
|
||||
if (BADMAG(*hdr)) return(ENOEXEC);
|
||||
#if (CHIP == INTEL && _WORD_SIZE == 2)
|
||||
if (hdr->a_cpu != A_I8086) return(ENOEXEC);
|
||||
#endif
|
||||
#if (CHIP == INTEL && _WORD_SIZE == 4)
|
||||
if (hdr->a_cpu != A_I80386) return(ENOEXEC);
|
||||
#endif
|
||||
if ((hdr->a_flags & ~(A_NSYM | A_EXEC | A_SEP)) != 0) return(ENOEXEC);
|
||||
|
||||
*sep_id = !!(hdr->a_flags & A_SEP); /* separate I & D or not */
|
||||
|
||||
/* Get text and data sizes. */
|
||||
*text_bytes = (vir_bytes) hdr->a_text; /* text size in bytes */
|
||||
*data_bytes = (vir_bytes) hdr->a_data; /* data size in bytes */
|
||||
*bss_bytes = (vir_bytes) hdr->a_bss; /* bss size in bytes */
|
||||
*tot_bytes = hdr->a_total; /* total bytes to allocate for prog */
|
||||
if (*tot_bytes == 0) return(ENOEXEC);
|
||||
|
||||
if (!*sep_id) {
|
||||
/* If I & D space is not separated, it is all considered data. Text=0*/
|
||||
*data_bytes += *text_bytes;
|
||||
*text_bytes = 0;
|
||||
}
|
||||
*pc = hdr->a_entry; /* initial address to start execution */
|
||||
*hdrlenp = hdr->a_hdrlen & BYTE; /* header length */
|
||||
|
||||
return(OK);
|
||||
}
|
||||
128
lib/libexec/exec_elf.c
Normal file
128
lib/libexec/exec_elf.c
Normal file
@@ -0,0 +1,128 @@
|
||||
#define _SYSTEM 1
|
||||
|
||||
#include <minix/type.h>
|
||||
#include <minix/const.h>
|
||||
#include <sys/param.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <libexec.h>
|
||||
|
||||
/* For verbose logging */
|
||||
#define ELF_DEBUG 0
|
||||
|
||||
/* Support only 32-bit ELF objects */
|
||||
#define __ELF_WORD_SIZE 32
|
||||
|
||||
static int __elfN(check_header)(const Elf_Ehdr *hdr);
|
||||
|
||||
int read_header_elf(
|
||||
const char *exec_hdr, /* executable header */
|
||||
vir_bytes *text_addr, /* text virtual address */
|
||||
vir_bytes *text_filebytes, /* text segment size (in the file) */
|
||||
vir_bytes *text_membytes, /* text segment size (in memory) */
|
||||
vir_bytes *data_addr, /* data virtual address */
|
||||
vir_bytes *data_filebytes, /* data segment size (in the file) */
|
||||
vir_bytes *data_membytes, /* data segment size (in memory) */
|
||||
phys_bytes *tot_bytes, /* total size */
|
||||
vir_bytes *pc, /* program entry point (initial PC) */
|
||||
off_t *text_offset, /* file offset to text segment */
|
||||
off_t *data_offset /* file offset to data segment */
|
||||
)
|
||||
{
|
||||
const Elf_Ehdr *hdr = NULL;
|
||||
const Elf_Phdr *phdr = NULL;
|
||||
unsigned long seg_filebytes, seg_membytes, seg_addr;
|
||||
int i = 0;
|
||||
|
||||
assert(exec_hdr != NULL);
|
||||
|
||||
*text_addr = *text_filebytes = *text_membytes = 0;
|
||||
*data_addr = *data_filebytes = *data_membytes = 0;
|
||||
*tot_bytes = *pc = *text_offset = *data_offset = 0;
|
||||
|
||||
hdr = (const Elf_Ehdr *)exec_hdr;
|
||||
if (__elfN(check_header)(hdr) != OK || (hdr->e_type != ET_EXEC))
|
||||
{
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
if ((hdr->e_phoff > PAGE_SIZE) ||
|
||||
(hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) {
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
phdr = (const Elf_Phdr *)(exec_hdr + hdr->e_phoff);
|
||||
if (!aligned(phdr, Elf_Addr)) {
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
#if ELF_DEBUG
|
||||
printf("Program header file offset (phoff): %d\n", hdr->e_phoff);
|
||||
printf("Section header file offset (shoff): %d\n", hdr->e_shoff);
|
||||
printf("Program header entry size (phentsize): %d\n", hdr->e_phentsize);
|
||||
printf("Program header entry num (phnum): %d\n", hdr->e_phnum);
|
||||
printf("Section header entry size (shentsize): %d\n", hdr->e_shentsize);
|
||||
printf("Section header entry num (shnum): %d\n", hdr->e_shnum);
|
||||
printf("Section name strings index (shstrndx): %d\n", hdr->e_shstrndx);
|
||||
printf("Entry Point: 0x%x\n", hdr->e_entry);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < hdr->e_phnum; i++) {
|
||||
switch (phdr[i].p_type) {
|
||||
case PT_LOAD:
|
||||
if (phdr[i].p_memsz == 0)
|
||||
break;
|
||||
seg_addr = phdr[i].p_vaddr;
|
||||
seg_filebytes = phdr[i].p_filesz;
|
||||
seg_membytes = round_page(phdr[i].p_memsz + phdr[i].p_vaddr -
|
||||
trunc_page(phdr[i].p_vaddr));
|
||||
|
||||
if (hdr->e_entry >= phdr[i].p_vaddr &&
|
||||
hdr->e_entry < (phdr[i].p_vaddr + phdr[i].p_memsz)) {
|
||||
*text_addr = seg_addr;
|
||||
*text_filebytes = seg_filebytes;
|
||||
*text_membytes = seg_membytes;
|
||||
*pc = (vir_bytes)hdr->e_entry;
|
||||
*text_offset = phdr[i].p_offset;
|
||||
} else {
|
||||
*data_addr = seg_addr;
|
||||
*data_filebytes = seg_filebytes;
|
||||
*data_membytes = seg_membytes;
|
||||
*data_offset = phdr[i].p_offset;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*tot_bytes = 0; /* Use default stack size */
|
||||
|
||||
#if ELF_DEBUG
|
||||
printf("Text addr: 0x%x\n", *text_addr);
|
||||
printf("Text filebytes: 0x%x\n", *text_filebytes);
|
||||
printf("Text membytes: 0x%x\n", *text_membytes);
|
||||
printf("Data addr: 0x%x\n", *data_addr);
|
||||
printf("Data filebyte: 0x%x\n", *data_filebytes);
|
||||
printf("Data membytes: 0x%x\n", *data_membytes);
|
||||
printf("Tot bytes: 0x%x\n", *tot_bytes);
|
||||
printf("PC: 0x%x\n", *pc);
|
||||
printf("Text offset: 0x%x\n", *text_offset);
|
||||
printf("Data offset: 0x%x\n", *data_offset);
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int __elfN(check_header)(const Elf_Ehdr *hdr)
|
||||
{
|
||||
if (!IS_ELF(*hdr) ||
|
||||
hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
|
||||
hdr->e_ident[EI_VERSION] != EV_CURRENT ||
|
||||
hdr->e_phentsize != sizeof(Elf_Phdr) ||
|
||||
hdr->e_version != ELF_TARG_VER)
|
||||
return ENOEXEC;
|
||||
|
||||
return OK;
|
||||
}
|
||||
Reference in New Issue
Block a user