From 7891554d8b7d93ab8063435462268c66f95ea004 Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Mon, 25 Jul 2022 17:10:28 +0200 Subject: [PATCH] move elf in dedicated file --- core/elf.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++++ core/elf.h | 4 ++ core/main.c | 176 +------------------------------------------------- 3 files changed, 187 insertions(+), 175 deletions(-) create mode 100644 core/elf.c create mode 100644 core/elf.h diff --git a/core/elf.c b/core/elf.c new file mode 100644 index 0000000..2098510 --- /dev/null +++ b/core/elf.c @@ -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; +} diff --git a/core/elf.h b/core/elf.h new file mode 100644 index 0000000..efbeb58 --- /dev/null +++ b/core/elf.h @@ -0,0 +1,4 @@ +#pragma once + +#include "types.h" +uaddr_t loadElfProg(const char *prog); diff --git a/core/main.c b/core/main.c index d296eaa..92d56d3 100644 --- a/core/main.c +++ b/core/main.c @@ -1,6 +1,7 @@ #include "alloc.h" #include "allocArea.h" #include "ata.h" +#include "elf.h" #include "exception.h" #include "gdt.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_MAX_SIZE 64