Subversion Repositories HelenOS-historic

Compare Revisions

Ignore whitespace Rev 937 → Rev 938

/kernel/trunk/generic/include/elf32.h
File deleted
/kernel/trunk/generic/include/elf64.h
File deleted
/kernel/trunk/generic/include/elf.h
30,5 → 30,305
#define __ELF_H__
 
#include <arch/elf.h>
#include <arch/types.h>
#include <mm/as.h>
 
/**
* current ELF version
*/
#define EV_CURRENT 1
 
/**
* ELF types
*/
#define ET_NONE 0 /* No type */
#define ET_REL 1 /* Relocatable file */
#define ET_EXEC 2 /* Executable */
#define ET_DYN 3 /* Shared object */
#define ET_CORE 4 /* Core */
#define ET_LOPROC 0xff00 /* Processor specific */
#define ET_HIPROC 0xffff /* Processor specific */
 
/**
* ELF machine types
*/
#define EM_NO 0 /* No machine */
#define EM_SPARC 2 /* SPARC */
#define EM_386 3 /* i386 */
#define EM_MIPS 8 /* MIPS RS3000 */
#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 LE */
#define EM_PPC 20 /* PPC32 */
#define EM_PPC64 21 /* PPC64 */
#define EM_SPARCV9 43 /* SPARC64 */
#define EM_IA_64 50 /* IA-64 */
#define EM_X86_64 62 /* AMD64/EMT64 */
 
/**
* ELF identification indexes
*/
#define EI_MAG0 0
#define EI_MAG1 1
#define EI_MAG2 2
#define EI_MAG3 3
#define EI_CLASS 4 /* File class */
#define EI_DATA 5 /* Data encoding */
#define EI_VERSION 6 /* File version */
#define EI_OSABI 7
#define EI_ABIVERSION 8
#define EI_PAD 9 /* Start of padding bytes */
#define EI_NIDENT 16 /* ELF identification table size */
 
/**
* ELF magic number
*/
#define ELFMAG0 0x7f
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
 
/**
* ELF file classes
*/
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
 
/**
* ELF data encoding types
*/
#define ELFDATANONE 0
#define ELFDATA2LSB 1 /* Least significant byte first (little endian) */
#define ELFDATA2MSB 2 /* Most signigicant byte first (big endian) */
 
/**
* ELF error return codes
*/
#define EE_OK 0 /* No error */
#define EE_INVALID 1 /* Invalid ELF image */
#define EE_MEMORY 2 /* Cannot allocate address space */
#define EE_INCOMPATIBLE 3 /* ELF image is not compatible with current architecture */
#define EE_UNSUPPORTED 4 /* Non-supported ELF (e.g. dynamic ELFs) */
#define EE_IRRECOVERABLE 5
 
/**
* ELF section types
*/
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define SHT_LOOS 0x60000000
#define SHT_HIOS 0x6fffffff
#define SHT_LOPROC 0x70000000
#define SHT_HIPROC 0x7fffffff
#define SHT_LOUSER 0x80000000
#define SHT_HIUSER 0xffffffff
 
/**
* ELF section flags
*/
#define SHF_WRITE 0x1
#define SHF_ALLOC 0x2
#define SHF_EXECINSTR 0x4
#define SHF_MASKPROC 0xf0000000
 
/**
* Symbol binding
*/
#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STB_WEAK 2
#define STB_LOPROC 13
#define STB_HIPROC 15
 
/**
* Symbol types
*/
#define STT_NOTYPE 0
#define STT_OBJECT 1
#define STT_FUNC 2
#define STT_SECTION 3
#define STT_FILE 4
#define STT_LOPROC 13
#define STT_HIPROC 15
 
/**
* Program segment types
*/
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_SHLIB 5
#define PT_PHDR 6
#define PT_LOPROC 0x70000000
#define PT_HIPROC 0x7fffffff
 
/**
* Program segment attributes.
*/
#define PF_X 1
#define PF_W 2
#define PF_R 4
 
/**
* ELF data types
*
* These types are found to be identical in both 32-bit and 64-bit
* ELF object file specifications. They are the only types used
* in ELF header.
*/
typedef __u64 elf_xword;
typedef __s64 elf_sxword;
typedef __u32 elf_word;
typedef __s32 elf_sword;
typedef __u16 elf_half;
 
/**
* 32-bit ELF data types.
*
* These types are specific for 32-bit format.
*/
typedef __u32 elf32_addr;
typedef __u32 elf32_off;
 
/**
* 64-bit ELF data types.
*
* These types are specific for 64-bit format.
*/
typedef __u64 elf64_addr;
typedef __u64 elf64_off;
 
/** ELF header */
struct elf32_header {
__u8 e_ident[EI_NIDENT];
elf_half e_type;
elf_half e_machine;
elf_word e_version;
elf32_addr e_entry;
elf32_off e_phoff;
elf32_off e_shoff;
elf_word e_flags;
elf_half e_ehsize;
elf_half e_phentsize;
elf_half e_phnum;
elf_half e_shentsize;
elf_half e_shnum;
elf_half e_shstrndx;
};
struct elf64_header {
__u8 e_ident[EI_NIDENT];
elf_half e_type;
elf_half e_machine;
elf_word e_version;
elf64_addr e_entry;
elf64_off e_phoff;
elf64_off e_shoff;
elf_word e_flags;
elf_half e_ehsize;
elf_half e_phentsize;
elf_half e_phnum;
elf_half e_shentsize;
elf_half e_shnum;
elf_half e_shstrndx;
};
 
/*
* ELF section header
*/
struct elf32_section_header {
elf_word sh_name;
elf_word sh_type;
elf_word sh_flags;
elf32_addr sh_addr;
elf32_off sh_offset;
elf_word sh_size;
elf_word sh_link;
elf_word sh_info;
elf_word sh_addralign;
elf_word sh_entsize;
};
struct elf64_section_header {
elf_word sh_name;
elf_word sh_type;
elf_xword sh_flags;
elf64_addr sh_addr;
elf64_off sh_offset;
elf_xword sh_size;
elf_word sh_link;
elf_word sh_info;
elf_xword sh_addralign;
elf_xword sh_entsize;
};
 
/*
* ELF symbol table entry
*/
struct elf32_symbol {
elf_word st_name;
elf32_addr st_value;
elf_word st_size;
__u8 st_info;
__u8 st_other;
elf_half st_shndx;
};
struct elf64_symbol {
elf_word st_name;
__u8 st_info;
__u8 st_other;
elf_half st_shndx;
elf64_addr st_value;
elf_xword st_size;
};
 
/*
* ELF program header entry
*/
struct elf32_ph_entry {
elf_word p_type;
elf32_off p_offset;
elf32_addr p_vaddr;
elf32_addr p_paddr;
elf_word p_filesz;
elf_word p_memsz;
elf_word p_flags;
elf_word p_align;
};
struct elf64_ph_entry {
elf_word p_type;
elf_word p_flags;
elf64_off p_offset;
elf64_addr p_vaddr;
elf64_addr p_paddr;
elf_xword p_filesz;
elf_xword p_memsz;
elf_xword p_align;
};
 
#ifdef __32_BITS__
typedef struct elf32_header elf_header_t;
typedef struct elf32_section_header elf_section_header_t;
typedef struct elf32_symbol elf_symbol_t;
typedef struct elf32_ph_entry elf_ph_entry_t;
#endif
#ifdef __64_BITS__
typedef struct elf64_header elf_header_t;
typedef struct elf64_section_header elf_section_header_t;
typedef struct elf64_symbol elf_symbol_t;
typedef struct elf64_ph_entry elf_ph_entry_t;
#endif
 
extern int elf_load(elf_header_t *header, as_t * as);
extern char *elf_error(int rc);
 
#endif
/kernel/trunk/generic/include/userspace.h
29,6 → 29,8
#ifndef __USERSPACE_H__
#define __USERSPACE_H__
 
extern void userspace(void) __attribute__ ((noreturn)); /**< Switch to user-space (CPU user priviledge level) */
#include <arch/types.h>
 
extern void userspace(__address entry) __attribute__ ((noreturn)); /**< Switch to user-space (CPU user priviledge level) */
 
#endif
/kernel/trunk/generic/src/main/kinit.c
46,6 → 46,7
#include <console/console.h>
#include <interrupt.h>
#include <console/kconsole.h>
#include <elf.h>
 
#ifdef CONFIG_SMP
#include <arch/smp/mps.h>
71,9 → 72,7
thread_t *t;
as_t *as;
as_area_t *a;
__address frame;
count_t frames;
int i;
int rc;
task_t *u;
 
interrupts_disable();
150,38 → 149,27
as = as_create(0);
if (!as)
panic("as_create\n");
u = task_create(as);
if (!u)
panic("task_create\n");
t = thread_create(uinit, NULL, u, THREAD_USER_STACK);
if (!t)
panic("thread_create\n");
/*
* Create the text as_area and initialize its mapping.
*/
frame = config.init_addr;
if (IS_KA(frame))
frame = KA2PA(frame);
 
frames = SIZE2FRAMES(config.init_size);
rc = elf_load((elf_header_t *) config.init_addr, as);
if (rc != EE_OK) {
printf("elf_load failed: %s\n", elf_error(rc));
} else {
u = task_create(as);
if (!u)
panic("task_create\n");
t = thread_create(uinit, (void *)((elf_header_t *) config.init_addr)->e_entry, u, THREAD_USER_STACK);
if (!t)
panic("thread_create\n");
a = as_area_create(as, AS_AREA_TEXT, frames, UTEXT_ADDRESS);
if (!a)
panic("as_area_create: text\n");
/*
* Create the data as_area.
*/
a = as_area_create(as, AS_AREA_STACK, 1, USTACK_ADDRESS);
if (!a)
panic("as_area_create: stack\n");
 
for (i = 0; i < frames; i++)
as_set_mapping(as, UTEXT_ADDRESS + i * PAGE_SIZE, frame + i * FRAME_SIZE);
 
/*
* Create the data as_area.
*/
a = as_area_create(as, AS_AREA_STACK, 1, USTACK_ADDRESS);
if (!a)
panic("as_area_create: stack\n");
 
thread_ready(t);
thread_ready(t);
}
}
 
#ifdef CONFIG_TEST
/kernel/trunk/generic/src/main/uinit.c
32,9 → 32,8
#include <userspace.h>
#include <print.h>
 
 
void uinit(void *arg)
{
printf("USER task, uinit thread: kernel mode\n");
userspace();
userspace((__address)(arg));
}
/kernel/trunk/generic/src/lib/elf32.c
File deleted
/kernel/trunk/generic/src/lib/elf64.c
File deleted
/kernel/trunk/generic/src/lib/elf.c
0,0 → 1,173
/*
* Copyright (C) 2006 Sergey Bondari
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <elf.h>
#include <debug.h>
#include <arch/types.h>
#include <typedefs.h>
#include <mm/as.h>
#include <mm/frame.h>
#include <print.h>
#include <align.h>
 
static char *error_codes[] = {
"no error",
"invalid image",
"address space error",
"incompatible image",
"unsupported image type",
"irrecoverable error"
};
 
static int program_header_entry(elf_header_t *header, elf_ph_entry_t *entry, as_t *as);
static int load_segment(elf_header_t *header, elf_ph_entry_t *entry, as_t *as);
 
/** ELF loader
*
* @param header Pointer to ELF header in memory
* @param as Created and properly mapped address space
* @return EE_OK on success
*/
int elf_load(elf_header_t *header, as_t * as)
{
int i, rc;
 
/* Identify ELF */
if (header->e_ident[EI_MAG0] != ELFMAG0 || header->e_ident[EI_MAG1] != ELFMAG1 ||
header->e_ident[EI_MAG2] != ELFMAG2 || header->e_ident[EI_MAG3] != ELFMAG3) {
return EE_INVALID;
}
/* Identify ELF compatibility */
if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING || header->e_machine != ELF_MACHINE ||
header->e_ident[EI_VERSION] != EV_CURRENT || header->e_version != EV_CURRENT ||
header->e_ident[EI_CLASS] != ELF_CLASS) {
return EE_INCOMPATIBLE;
}
 
if (header->e_phentsize != sizeof(elf_ph_entry_t))
return EE_INCOMPATIBLE;
 
/* Check if the object type is supported. */
if (header->e_type != ET_EXEC)
return EE_UNSUPPORTED;
 
/* Walk through all program header entries and process them. */
for (i = 0; i < header->e_phnum; i++) {
rc = program_header_entry(header, &((elf_ph_entry_t *)(((__u8 *) header) + header->e_phoff))[i], as);
if (rc != EE_OK)
return rc;
}
 
return EE_OK;
}
 
/** Print error message according to error code.
*
* @param rc Return code returned by elf_load().
*
* @return NULL terminated description of error.
*/
char *elf_error(int rc)
{
ASSERT(rc < sizeof(error_codes)/sizeof(char *));
 
return error_codes[rc];
}
 
/** Process program header entry.
*
* @param entry Program header entry.
* @param as Address space into wich the ELF is being loaded.
*
* @return EE_OK on success, error code otherwise.
*/
static int program_header_entry(elf_header_t *header, elf_ph_entry_t *entry, as_t *as)
{
switch (entry->p_type) {
case PT_NULL:
case PT_PHDR:
break;
case PT_LOAD:
return load_segment(header, entry, as);
break;
case PT_DYNAMIC:
case PT_INTERP:
case PT_SHLIB:
case PT_NOTE:
case PT_LOPROC:
case PT_HIPROC:
default:
return EE_UNSUPPORTED;
break;
}
return EE_OK;
}
 
/** Load segment described by program header entry.
*
* @param entry Program header entry describing segment to be loaded.
* @parma as Address space into wich the ELF is being loaded.
*
* @return EE_OK on success, error code otherwise.
*/
int load_segment(elf_header_t *header, elf_ph_entry_t *entry, as_t *as)
{
as_area_t *a;
int i, type = 0;
 
if (entry->p_align > 1) {
if ((entry->p_offset % entry->p_align) != (entry->p_vaddr % entry->p_align)) {
return EE_INVALID;
}
}
 
/*
* Check if the segment doesn't interfere with kernel address space.
*/
if (entry->p_vaddr + ALIGN_UP(entry->p_memsz, PAGE_SIZE) >= USER_ADDRESS_SPACE_END)
return EE_MEMORY;
if (entry->p_flags & PF_X) {
type = AS_AREA_TEXT;
} else if (entry->p_flags & PF_W) {
type = AS_AREA_DATA;
} else {
return EE_UNSUPPORTED;
}
 
a = as_area_create(as, AS_AREA_TEXT, SIZE2FRAMES(entry->p_memsz), entry->p_vaddr);
if (!a)
return EE_IRRECOVERABLE;
for (i = 0; i < SIZE2FRAMES(entry->p_filesz); i++) {
as_set_mapping(as, entry->p_vaddr + i*PAGE_SIZE, KA2PA(((__address) header) + entry->p_offset + i*PAGE_SIZE));
}
return EE_OK;
}