move elf in dedicated file
This commit is contained in:
parent
db0d3dff14
commit
7891554d8b
182
core/elf.c
Normal file
182
core/elf.c
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
#include "elf.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "klibc.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "paging.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure the program is in a valid ELF format, map it into memory,
|
||||||
|
* and return the address of its entry point (ie _start function)
|
||||||
|
*
|
||||||
|
* @return 0 when the program is not a valid ELF
|
||||||
|
*/
|
||||||
|
|
||||||
|
uaddr_t loadElfProg(const char *prog)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typedefs, constants and structure definitions as given by the ELF
|
||||||
|
* standard specifications.
|
||||||
|
*/
|
||||||
|
typedef unsigned long Elf32_Addr;
|
||||||
|
typedef unsigned long Elf32_Word;
|
||||||
|
typedef unsigned short Elf32_Half;
|
||||||
|
typedef unsigned long Elf32_Off;
|
||||||
|
// typedef signed long Elf32_Sword;
|
||||||
|
|
||||||
|
/* Elf identification */
|
||||||
|
|
||||||
|
#define EI_NIDENT 16
|
||||||
|
typedef struct {
|
||||||
|
unsigned char e_ident[EI_NIDENT];
|
||||||
|
Elf32_Half e_type;
|
||||||
|
Elf32_Half e_machine;
|
||||||
|
Elf32_Word e_version;
|
||||||
|
Elf32_Addr e_entry;
|
||||||
|
Elf32_Off e_phoff;
|
||||||
|
Elf32_Off e_shoff;
|
||||||
|
Elf32_Word e_flags;
|
||||||
|
Elf32_Half e_ehsize;
|
||||||
|
Elf32_Half e_phentsize;
|
||||||
|
Elf32_Half e_phnum;
|
||||||
|
Elf32_Half e_shentsize;
|
||||||
|
Elf32_Half e_shnum;
|
||||||
|
Elf32_Half e_shstrndx;
|
||||||
|
} __attribute__((packed)) Elf32_Ehdr_t;
|
||||||
|
|
||||||
|
/* e_ident value */
|
||||||
|
#define ELFMAG0 0x7f
|
||||||
|
#define ELFMAG1 'E'
|
||||||
|
#define ELFMAG2 'L'
|
||||||
|
#define ELFMAG3 'F'
|
||||||
|
|
||||||
|
/* e_ident offsets */
|
||||||
|
#define EI_MAG0 0
|
||||||
|
#define EI_MAG1 1
|
||||||
|
#define EI_MAG2 2
|
||||||
|
#define EI_MAG3 3
|
||||||
|
#define EI_CLASS 4
|
||||||
|
#define EI_DATA 5
|
||||||
|
#define EI_VERSION 6
|
||||||
|
#define EI_PAD 7
|
||||||
|
|
||||||
|
/* e_ident[EI_CLASS] */
|
||||||
|
#define ELFCLASSNONE 0
|
||||||
|
#define ELFCLASS32 1
|
||||||
|
#define ELFCLASS64 2
|
||||||
|
|
||||||
|
/* e_ident[EI_DATA] */
|
||||||
|
#define ELFDATANONE 0
|
||||||
|
#define ELFDATA2LSB 1
|
||||||
|
#define ELFDATA2MSB 2
|
||||||
|
|
||||||
|
/* e_type */
|
||||||
|
#define ET_NONE 0 /* No file type */
|
||||||
|
#define ET_REL 1 /* Relocatable file */
|
||||||
|
#define ET_EXEC 2 /* Executable file */
|
||||||
|
#define ET_DYN 3 /* Shared object file */
|
||||||
|
#define ET_CORE 4 /* Core file */
|
||||||
|
#define ET_LOPROC 0xff00 /* Processor-specific */
|
||||||
|
#define ET_HIPROC 0xffff /* Processor-specific */
|
||||||
|
|
||||||
|
/* e_machine */
|
||||||
|
#define EM_NONE 0 /* No machine */
|
||||||
|
#define EM_M32 1 /* AT&T WE 32100 */
|
||||||
|
#define EM_SPARC 2 /* SPARC */
|
||||||
|
#define EM_386 3 /* Intel 80386 */
|
||||||
|
#define EM_68K 4 /* Motorola 68000 */
|
||||||
|
#define EM_88K 5 /* Motorola 88000 */
|
||||||
|
#define EM_860 7 /* Intel 80860 */
|
||||||
|
#define EM_MIPS 8 /* MIPS RS3000 */
|
||||||
|
|
||||||
|
/* e_version */
|
||||||
|
#define EV_NONE 0 /* invalid version */
|
||||||
|
#define EV_CURRENT 1 /* current version */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Elf32_Word p_type;
|
||||||
|
Elf32_Off p_offset;
|
||||||
|
Elf32_Addr p_vaddr;
|
||||||
|
Elf32_Addr p_paddr;
|
||||||
|
Elf32_Word p_filesz;
|
||||||
|
Elf32_Word p_memsz;
|
||||||
|
Elf32_Word p_flags;
|
||||||
|
Elf32_Word p_align;
|
||||||
|
} __attribute__((packed)) Elf32_Phdr_t;
|
||||||
|
|
||||||
|
/* Reserved segment types p_type */
|
||||||
|
#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
|
||||||
|
|
||||||
|
/* p_flags */
|
||||||
|
#define PF_X 1
|
||||||
|
#define PF_W 2
|
||||||
|
#define PF_R 4
|
||||||
|
|
||||||
|
Elf32_Ehdr_t *elf_hdr = (Elf32_Ehdr_t *)prog;
|
||||||
|
Elf32_Phdr_t *elf_phdrs;
|
||||||
|
|
||||||
|
/* Macro to check expected values for some fields in the ELF header */
|
||||||
|
#define ELF_CHECK(hdr, field, expected_value) \
|
||||||
|
({ \
|
||||||
|
if ((hdr)->field != (expected_value)) { \
|
||||||
|
printf("ELF prog : for %s, expected %x, got %x\n", #field, \
|
||||||
|
(unsigned)(expected_value), (unsigned)(hdr)->field); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
|
ELF_CHECK(elf_hdr, e_ident[EI_MAG0], ELFMAG0);
|
||||||
|
ELF_CHECK(elf_hdr, e_ident[EI_MAG1], ELFMAG1);
|
||||||
|
ELF_CHECK(elf_hdr, e_ident[EI_MAG2], ELFMAG2);
|
||||||
|
ELF_CHECK(elf_hdr, e_ident[EI_MAG3], ELFMAG3);
|
||||||
|
ELF_CHECK(elf_hdr, e_ident[EI_CLASS], ELFCLASS32);
|
||||||
|
ELF_CHECK(elf_hdr, e_ident[EI_DATA], ELFDATA2LSB);
|
||||||
|
ELF_CHECK(elf_hdr, e_type, ET_EXEC);
|
||||||
|
ELF_CHECK(elf_hdr, e_version, EV_CURRENT);
|
||||||
|
|
||||||
|
/* Get the begining of the program header table */
|
||||||
|
elf_phdrs = (Elf32_Phdr_t *)(prog + elf_hdr->e_phoff);
|
||||||
|
|
||||||
|
/* Map the program segment in R/W mode. To make things clean, we
|
||||||
|
should iterate over the sections, not the program header */
|
||||||
|
for (i = 0; i < elf_hdr->e_phnum; i++) {
|
||||||
|
uaddr_t uaddr;
|
||||||
|
|
||||||
|
/* Ignore the empty program headers that are not marked "LOAD" */
|
||||||
|
if (elf_phdrs[i].p_type != PT_LOAD) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elf_phdrs[i].p_vaddr < PAGING_BASE_USER_ADDRESS) {
|
||||||
|
printf("User program has an incorrect address 0x%x\n", elf_phdrs[i].p_vaddr);
|
||||||
|
return (uaddr_t)NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Map pages of physical memory into user space */
|
||||||
|
for (uaddr = ALIGN_DOWN(elf_phdrs[i].p_vaddr, PAGE_SIZE);
|
||||||
|
uaddr < elf_phdrs[i].p_vaddr + elf_phdrs[i].p_memsz; uaddr += PAGE_SIZE) {
|
||||||
|
paddr_t ppage;
|
||||||
|
ppage = allocPhyPage(1);
|
||||||
|
|
||||||
|
assert(pageMap(uaddr, ppage,
|
||||||
|
PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ) == 0);
|
||||||
|
|
||||||
|
unrefPhyPage(ppage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy segment into memory */
|
||||||
|
memcpy((void *)elf_phdrs[i].p_vaddr, (void *)(prog + elf_phdrs[i].p_offset),
|
||||||
|
elf_phdrs[i].p_filesz);
|
||||||
|
}
|
||||||
|
|
||||||
|
return elf_hdr->e_entry;
|
||||||
|
}
|
4
core/elf.h
Normal file
4
core/elf.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
uaddr_t loadElfProg(const char *prog);
|
176
core/main.c
176
core/main.c
@ -1,6 +1,7 @@
|
|||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "allocArea.h"
|
#include "allocArea.h"
|
||||||
#include "ata.h"
|
#include "ata.h"
|
||||||
|
#include "elf.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
@ -39,181 +40,6 @@ void idleThread(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure the program is in a valid ELF format, map it into memory,
|
|
||||||
* and return the address of its entry point (ie _start function)
|
|
||||||
*
|
|
||||||
* @return 0 when the program is not a valid ELF
|
|
||||||
*/
|
|
||||||
static uaddr_t loadElfProg(const char *prog)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Typedefs, constants and structure definitions as given by the ELF
|
|
||||||
* standard specifications.
|
|
||||||
*/
|
|
||||||
typedef unsigned long Elf32_Addr;
|
|
||||||
typedef unsigned long Elf32_Word;
|
|
||||||
typedef unsigned short Elf32_Half;
|
|
||||||
typedef unsigned long Elf32_Off;
|
|
||||||
// typedef signed long Elf32_Sword;
|
|
||||||
|
|
||||||
/* Elf identification */
|
|
||||||
|
|
||||||
#define EI_NIDENT 16
|
|
||||||
typedef struct {
|
|
||||||
unsigned char e_ident[EI_NIDENT];
|
|
||||||
Elf32_Half e_type;
|
|
||||||
Elf32_Half e_machine;
|
|
||||||
Elf32_Word e_version;
|
|
||||||
Elf32_Addr e_entry;
|
|
||||||
Elf32_Off e_phoff;
|
|
||||||
Elf32_Off e_shoff;
|
|
||||||
Elf32_Word e_flags;
|
|
||||||
Elf32_Half e_ehsize;
|
|
||||||
Elf32_Half e_phentsize;
|
|
||||||
Elf32_Half e_phnum;
|
|
||||||
Elf32_Half e_shentsize;
|
|
||||||
Elf32_Half e_shnum;
|
|
||||||
Elf32_Half e_shstrndx;
|
|
||||||
} __attribute__((packed)) Elf32_Ehdr_t;
|
|
||||||
|
|
||||||
/* e_ident value */
|
|
||||||
#define ELFMAG0 0x7f
|
|
||||||
#define ELFMAG1 'E'
|
|
||||||
#define ELFMAG2 'L'
|
|
||||||
#define ELFMAG3 'F'
|
|
||||||
|
|
||||||
/* e_ident offsets */
|
|
||||||
#define EI_MAG0 0
|
|
||||||
#define EI_MAG1 1
|
|
||||||
#define EI_MAG2 2
|
|
||||||
#define EI_MAG3 3
|
|
||||||
#define EI_CLASS 4
|
|
||||||
#define EI_DATA 5
|
|
||||||
#define EI_VERSION 6
|
|
||||||
#define EI_PAD 7
|
|
||||||
|
|
||||||
/* e_ident[EI_CLASS] */
|
|
||||||
#define ELFCLASSNONE 0
|
|
||||||
#define ELFCLASS32 1
|
|
||||||
#define ELFCLASS64 2
|
|
||||||
|
|
||||||
/* e_ident[EI_DATA] */
|
|
||||||
#define ELFDATANONE 0
|
|
||||||
#define ELFDATA2LSB 1
|
|
||||||
#define ELFDATA2MSB 2
|
|
||||||
|
|
||||||
/* e_type */
|
|
||||||
#define ET_NONE 0 /* No file type */
|
|
||||||
#define ET_REL 1 /* Relocatable file */
|
|
||||||
#define ET_EXEC 2 /* Executable file */
|
|
||||||
#define ET_DYN 3 /* Shared object file */
|
|
||||||
#define ET_CORE 4 /* Core file */
|
|
||||||
#define ET_LOPROC 0xff00 /* Processor-specific */
|
|
||||||
#define ET_HIPROC 0xffff /* Processor-specific */
|
|
||||||
|
|
||||||
/* e_machine */
|
|
||||||
#define EM_NONE 0 /* No machine */
|
|
||||||
#define EM_M32 1 /* AT&T WE 32100 */
|
|
||||||
#define EM_SPARC 2 /* SPARC */
|
|
||||||
#define EM_386 3 /* Intel 80386 */
|
|
||||||
#define EM_68K 4 /* Motorola 68000 */
|
|
||||||
#define EM_88K 5 /* Motorola 88000 */
|
|
||||||
#define EM_860 7 /* Intel 80860 */
|
|
||||||
#define EM_MIPS 8 /* MIPS RS3000 */
|
|
||||||
|
|
||||||
/* e_version */
|
|
||||||
#define EV_NONE 0 /* invalid version */
|
|
||||||
#define EV_CURRENT 1 /* current version */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Elf32_Word p_type;
|
|
||||||
Elf32_Off p_offset;
|
|
||||||
Elf32_Addr p_vaddr;
|
|
||||||
Elf32_Addr p_paddr;
|
|
||||||
Elf32_Word p_filesz;
|
|
||||||
Elf32_Word p_memsz;
|
|
||||||
Elf32_Word p_flags;
|
|
||||||
Elf32_Word p_align;
|
|
||||||
} __attribute__((packed)) Elf32_Phdr_t;
|
|
||||||
|
|
||||||
/* Reserved segment types p_type */
|
|
||||||
#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
|
|
||||||
|
|
||||||
/* p_flags */
|
|
||||||
#define PF_X 1
|
|
||||||
#define PF_W 2
|
|
||||||
#define PF_R 4
|
|
||||||
|
|
||||||
Elf32_Ehdr_t *elf_hdr = (Elf32_Ehdr_t *)prog;
|
|
||||||
Elf32_Phdr_t *elf_phdrs;
|
|
||||||
|
|
||||||
/* Macro to check expected values for some fields in the ELF header */
|
|
||||||
#define ELF_CHECK(hdr, field, expected_value) \
|
|
||||||
({ \
|
|
||||||
if ((hdr)->field != (expected_value)) { \
|
|
||||||
printf("ELF prog : for %s, expected %x, got %x\n", #field, \
|
|
||||||
(unsigned)(expected_value), (unsigned)(hdr)->field); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
})
|
|
||||||
|
|
||||||
ELF_CHECK(elf_hdr, e_ident[EI_MAG0], ELFMAG0);
|
|
||||||
ELF_CHECK(elf_hdr, e_ident[EI_MAG1], ELFMAG1);
|
|
||||||
ELF_CHECK(elf_hdr, e_ident[EI_MAG2], ELFMAG2);
|
|
||||||
ELF_CHECK(elf_hdr, e_ident[EI_MAG3], ELFMAG3);
|
|
||||||
ELF_CHECK(elf_hdr, e_ident[EI_CLASS], ELFCLASS32);
|
|
||||||
ELF_CHECK(elf_hdr, e_ident[EI_DATA], ELFDATA2LSB);
|
|
||||||
ELF_CHECK(elf_hdr, e_type, ET_EXEC);
|
|
||||||
ELF_CHECK(elf_hdr, e_version, EV_CURRENT);
|
|
||||||
|
|
||||||
/* Get the begining of the program header table */
|
|
||||||
elf_phdrs = (Elf32_Phdr_t *)(prog + elf_hdr->e_phoff);
|
|
||||||
|
|
||||||
/* Map the program segment in R/W mode. To make things clean, we
|
|
||||||
should iterate over the sections, not the program header */
|
|
||||||
for (i = 0; i < elf_hdr->e_phnum; i++) {
|
|
||||||
uaddr_t uaddr;
|
|
||||||
|
|
||||||
/* Ignore the empty program headers that are not marked "LOAD" */
|
|
||||||
if (elf_phdrs[i].p_type != PT_LOAD) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elf_phdrs[i].p_vaddr < PAGING_BASE_USER_ADDRESS) {
|
|
||||||
printf("User program has an incorrect address 0x%x\n", elf_phdrs[i].p_vaddr);
|
|
||||||
return (uaddr_t)NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Map pages of physical memory into user space */
|
|
||||||
for (uaddr = ALIGN_DOWN(elf_phdrs[i].p_vaddr, PAGE_SIZE);
|
|
||||||
uaddr < elf_phdrs[i].p_vaddr + elf_phdrs[i].p_memsz; uaddr += PAGE_SIZE) {
|
|
||||||
paddr_t ppage;
|
|
||||||
ppage = allocPhyPage(1);
|
|
||||||
|
|
||||||
assert(pageMap(uaddr, ppage,
|
|
||||||
PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ) == 0);
|
|
||||||
|
|
||||||
unrefPhyPage(ppage);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy segment into memory */
|
|
||||||
memcpy((void *)elf_phdrs[i].p_vaddr, (void *)(prog + elf_phdrs[i].p_offset),
|
|
||||||
elf_phdrs[i].p_filesz);
|
|
||||||
}
|
|
||||||
|
|
||||||
return elf_hdr->e_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FILE_HEADER_SIZE 16
|
#define FILE_HEADER_SIZE 16
|
||||||
#define FILE_MAX_SIZE 64
|
#define FILE_MAX_SIZE 64
|
||||||
|
Loading…
Reference in New Issue
Block a user