From f1afec507a0d9a5be433ea80b3b4ba71ae28977d Mon Sep 17 00:00:00 2001 From: hzc1998 <2323168280@qq.com> Date: Sun, 6 Mar 2022 22:26:27 +0800 Subject: [PATCH] feat(process): add elf loader --- src/Makefile | 2 +- src/include/mods/thirdpart/cpio.h | 6 +- src/include/mods/thirdpart/elf.h | 383 +++++++++++++++++++++++++++++ src/include/sched/process.h | 2 + src/include/xbook/defines.h | 1 + src/sched/process.c | 393 ++++++++++++++++++++++++++---- 6 files changed, 735 insertions(+), 52 deletions(-) create mode 100644 src/include/mods/thirdpart/elf.h diff --git a/src/Makefile b/src/Makefile index f698ea9..c4dbc82 100644 --- a/src/Makefile +++ b/src/Makefile @@ -57,7 +57,7 @@ endif ifeq ($(strip $(ARCH)), amd64) DEFINES += -D__AMD64__ endif -ifeq ($(strip $(ARCH)), i386) +ifeq ($(strip $(ARCH)), x86) DEFINES += -D__I386__ endif diff --git a/src/include/mods/thirdpart/cpio.h b/src/include/mods/thirdpart/cpio.h index 2c3c81a..e34ec23 100644 --- a/src/include/mods/thirdpart/cpio.h +++ b/src/include/mods/thirdpart/cpio.h @@ -19,8 +19,8 @@ * @TAG(NICTA_BSD) */ -#ifndef __UTILS_LIB_CPIO__ -#define __UTILS_LIB_CPIO__ +#ifndef __THIRDPART_CPIO__ +#define __THIRDPART_CPIO__ /* Magic identifiers for the "cpio" file format. */ #define CPIO_HEADER_MAGIC "070701" @@ -96,4 +96,4 @@ int cpio_info(void *archive, struct cpio_info *info); */ void cpio_ls(void *archive, char **buf, unsigned long buf_len); -#endif /* __UTILS_LIB_CPIO__ */ +#endif /* __THIRDPART_CPIO__ */ diff --git a/src/include/mods/thirdpart/elf.h b/src/include/mods/thirdpart/elf.h new file mode 100644 index 0000000..3a2f230 --- /dev/null +++ b/src/include/mods/thirdpart/elf.h @@ -0,0 +1,383 @@ +/** + * Copyright (c) 2018-2022, NXOS Development Team + * SPDX-License-Identifier: Apache-2.0 + * + * Contains: elf header + * + * Change Logs: + * Date Author Notes + * 2022-3-6 JasonHu Init + */ + +#ifndef __THIRDPART_ELF__ +#define __THIRDPART_ELF__ + +#include + +#ifdef CONFIG_NX_CPU_64BITS +#define elfhdr elf64_hdr +#define elf_phdr elf64_phdr +#define elf_shdr elf64_shdr +#define elf_note elf64_note +#define elf_off Elf64_Off +#define Elf_Word Elf64_Word +#define Elf_Addr Elf64_Addr +#define Elf_Half Elf64_Half +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Phdr Elf64_Phdr +#define Elf_Shdr Elf64_Shdr +#else +#define elfhdr elf32_hdr +#define elf_phdr elf32_phdr +#define elf_shdr elf32_shdr +#define elf_note elf32_note +#define elf_off Elf32_Off +#define Elf_Word Elf32_Word +#define Elf_Addr Elf32_Addr +#define Elf_Half Elf32_Half +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Phdr Elf32_Phdr +#define Elf_Shdr Elf32_Shdr +#endif + +/* 32-bit ELF base types. */ +typedef NX_U32 Elf32_Addr; +typedef NX_U16 Elf32_Half; +typedef NX_U32 Elf32_Off; +typedef NX_I32 Elf32_Sword; +typedef NX_U32 Elf32_Word; + +/* 64-bit ELF base types. */ +typedef NX_U64 Elf64_Addr; +typedef NX_U16 Elf64_Half; +typedef NX_I16 Elf64_SHalf; +typedef NX_U64 Elf64_Off; +typedef NX_I32 Elf64_Sword; +typedef NX_U32 Elf64_Word; +typedef NX_U64 Elf64_Xword; +typedef NX_I64 Elf64_Sxword; + +/* These constants are for the segment types stored in the image headers */ +#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_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* OS-specific */ +#define PT_HIOS 0x6fffffff /* OS-specific */ +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_GNU_PROPERTY 0x6474e553 + +#define PT_GNU_STACK (PT_LOOS + 0x474e551) + +#define PN_XNUM 0xffff + +/* These constants define the different elf file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* This is the info that is needed to parse the dynamic section of the file */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_ENCODING 32 +#define OLD_DT_LOOS 0x60000000 +#define DT_LOOS 0x6000000d +#define DT_HIOS 0x6ffff000 +#define DT_VALRNGLO 0x6ffffd00 +#define DT_VALRNGHI 0x6ffffdff +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_VERSYM 0x6ffffff0 +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa +#define DT_FLAGS_1 0x6ffffffb +#define DT_VERDEF 0x6ffffffc +#define DT_VERDEFNUM 0x6ffffffd +#define DT_VERNEED 0x6ffffffe +#define DT_VERNEEDNUM 0x6fffffff +#define OLD_DT_HIOS 0x6fffffff +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* This info is needed when parsing the symbol table */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_COMMON 5 +#define STT_TLS 6 + +#define ELF_ST_BIND(x) ((x) >> 4) +#define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf) +#define ELF32_ST_BIND(x) ELF_ST_BIND(x) +#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) +#define ELF64_ST_BIND(x) ELF_ST_BIND(x) +#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x) + +typedef struct dynamic{ + Elf32_Sword d_tag; + union{ + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +typedef struct { + Elf64_Sxword d_tag; /* entry tag value */ + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +/* The following are used with relocations */ +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x) & 0xff) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) + +typedef struct elf32_rel { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf64_rel { + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ +} Elf64_Rel; + +typedef struct elf32_rela{ + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct elf64_rela { + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ + Elf64_Sxword r_addend; /* Constant addend used to compute value */ +} Elf64_Rela; + +typedef struct elf32_sym{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +typedef struct elf64_sym { + Elf64_Word st_name; /* Symbol name, index in string tbl */ + unsigned char st_info; /* Type and binding attributes */ + unsigned char st_other; /* No defined meaning, 0 */ + Elf64_Half st_shndx; /* Associated section index */ + Elf64_Addr st_value; /* Value of the symbol */ + Elf64_Xword st_size; /* Associated symbol size */ +} Elf64_Sym; + + +#define EI_NIDENT 16 + +typedef struct elf32_hdr{ + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; /* Entry point */ + 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; +} Elf32_Ehdr; + +typedef struct elf64_hdr { + unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* These constants define the permissions on sections in the program + header, p_flags. */ +#define PF_R 0x4 +#define PF_W 0x2 +#define PF_X 0x1 + +typedef struct elf32_phdr{ + 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; +} Elf32_Phdr; + +typedef struct elf64_phdr { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment, file & memory */ +} Elf64_Phdr; + +/* sh_type */ +#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_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* sh_flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_RELA_LIVEPATCH 0x00100000 +#define SHF_RO_AFTER_INIT 0x00200000 +#define SHF_MASKPROC 0xf0000000 + +/* special section indexes */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_LIVEPATCH 0xff20 +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +typedef struct elf32_shdr { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct elf64_shdr { + Elf64_Word sh_name; /* Section name, index in string tbl */ + Elf64_Word sh_type; /* Type of section */ + Elf64_Xword sh_flags; /* Miscellaneous section attributes */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Size of section in bytes */ + Elf64_Word sh_link; /* Index of another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +#define EI_MAG0 0 /* e_ident[] indexes */ +#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_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +/* Legal values for e_machine (architecture). */ +#define EM_NONE 0 /* No machine */ +#define EM_386 3 /* Intel 80386 */ +#define EM_ARM 40 /* ARM */ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_AARCH64 183 /* ARM AARCH64 */ +#define EM_RISCV 243 /* RISC-V */ + +#endif /* __THIRDPART_ELF__ */ diff --git a/src/include/sched/process.h b/src/include/sched/process.h index 7717ba7..edb12c5 100644 --- a/src/include/sched/process.h +++ b/src/include/sched/process.h @@ -17,6 +17,8 @@ #include #include +#define NX_PROCESS_USER_SATCK_SIZE (NX_PAGE_SIZE * 4) + struct NX_Process { NX_U32 flags; diff --git a/src/include/xbook/defines.h b/src/include/xbook/defines.h index 5a32424..fc0fba3 100644 --- a/src/include/xbook/defines.h +++ b/src/include/xbook/defines.h @@ -82,6 +82,7 @@ #define NX_ARRAY_CAST(p, size) (((char(*)[size])(p))) #define NX_MIN(x, y) ({typeof(x) _x = (x);typeof(y) _y = (y);(void)(&_x == &_y);_x < _y ? _x : _y; }) +#define NX_MAX(x, y) ({typeof(x) _x = (x);typeof(y) _y = (y);(void)(&_x == &_y);_x > _y ? _x : _y; }) #define NX_KB 1024 #define NX_MB (NX_KB * 1024) diff --git a/src/sched/process.c b/src/sched/process.c index 036acba..7d5c64e 100644 --- a/src/sched/process.c +++ b/src/sched/process.c @@ -25,6 +25,7 @@ #include #include +#include NX_PRIVATE void ProcessAppendThread(NX_Process *process, NX_Thread *thread) { @@ -108,6 +109,336 @@ NX_PRIVATE void ProcessThreadEntry(void *arg) NX_ProcessExecuteUser((void *)NX_USER_IMAGE_VADDR, (void *)NX_USER_STACK_TOP, thread->stackBase + thread->stackSize, NX_NULL); } +NX_PRIVATE NX_Error NX_LoadCheckMachine(NX_U16 machineType) +{ + NX_U16 type = EM_NONE; + char *machineStr = "None"; + +#if defined(__I386__) + type = EM_386; + machineStr = "Intel 80386"; +#elif defined(__AMD64__) + type = EM_X86_64; + machineStr = "AMD x86-64 architecture"; +#elif defined(__ARM__) + type = EM_ARM; + machineStr = "ARM"; +#elif defined(__ARM64__) + type = EM_AARCH64; + machineStr = "ARM AARCH64"; +#elif defined(__RISCV32__) || defined(__RISCV64__) + type = EM_RISCV; + machineStr = "RISC-V"; +#endif + + if (machineType != type) + { + NX_LOG_E("elf file not a %s format !", machineStr); + return NX_EINVAL; + } + return NX_EOK; +} + +NX_PRIVATE NX_Error NX_LoadCheck(char *path, NX_RomfsFile *file, NX_Size len, NX_Vmspace *space, Elf_Ehdr *elfHeader) +{ + NX_U8 elfMagic[SELFMAG]; + NX_Size loadLen = 0; + + if (len < sizeof(Elf_Ehdr)) + { + NX_LOG_E("file %s too small.", path); + return NX_EINVAL; + } + + /* check elf magic */ + if (NX_RomfsSeek(file, 0, NX_ROMFS_SEEK_SET, NX_NULL) != NX_EOK) + { + return NX_EFAULT; + } + if (NX_RomfsRead(file, elfMagic, sizeof(elfMagic), &loadLen) != NX_EOK) + { + return NX_EIO; + } + if (loadLen != sizeof(elfMagic)) + { + return NX_EIO; + } + + if (elfMagic[EI_MAG0] != ELFMAG0 || elfMagic[EI_MAG1] != ELFMAG1 || + elfMagic[EI_MAG2] != ELFMAG2 || elfMagic[EI_MAG3] != ELFMAG3) + { + NX_LOG_E("file %s not a elf format file!", path); + return NX_EINVAL; + } + + /* load header */ + if (NX_RomfsSeek(file, 0, NX_ROMFS_SEEK_SET, NX_NULL) != NX_EOK) + { + return NX_EFAULT; + } + if (NX_RomfsRead(file, elfHeader, sizeof(Elf_Ehdr), &loadLen) != NX_EOK) + { + return NX_EIO; + } + if (loadLen != sizeof(Elf_Ehdr)) + { + return NX_EIO; + } + + NX_LOG_D("elf ident: class %d, version %d, entry %p, machine %d", elfHeader->e_ident[EI_CLASS], elfHeader->e_ident[EI_VERSION], elfHeader->e_entry, elfHeader->e_machine); + + if (NX_LoadCheckMachine(elfHeader->e_machine) != NX_EOK) + { + return NX_EINVAL; + } + + /* check ident */ +#ifdef CONFIG_NX_CPU_64BITS + if (elfHeader->e_ident[EI_CLASS] != 2) /* must be 64 bit elf header */ + { + NX_LOG_E("elf file %s not 64 bit!", path); + return NX_EINVAL; + } +#else + if (elfHeader->e_ident[EI_CLASS] != 1) /* must be 32 bit elf header */ + { + NX_LOG_E("elf file %s not 32 bit!", path); + return NX_EINVAL; + } +#endif + + if (elfHeader->e_ident[EI_VERSION] != 1) + { + NX_LOG_E("elf file %s version must be 1!", path); + return NX_EINVAL; + } + + /* check entry point */ + if (elfHeader->e_entry != space->imageStart) + { + NX_LOG_E("elf file %s entry %p is invalid!", path, elfHeader->e_entry); + return NX_EINVAL; + } + + return NX_EOK; +} + + +NX_PRIVATE NX_Error NX_LoadMapUserSpace(NX_RomfsFile *file, NX_Size len, NX_Vmspace *space, Elf_Ehdr *elfHeader) +{ + Elf_Phdr progHeader; + NX_Offset off = 0; + NX_Size loadLen = 0; + int i; + + NX_LOG_D("elf program header info: numbers %d, off %p", elfHeader->e_phnum, elfHeader->e_phoff); + + /* if map failed, no need unmap the mapped space, because process destroy will unmap it. */ + off = elfHeader->e_phoff; + for (i = 0; i < elfHeader->e_phnum; i++, off += sizeof(progHeader)) + { + if (off > len) + { + return NX_EFAULT; + } + + if (NX_RomfsSeek(file, off, NX_ROMFS_SEEK_SET, NX_NULL) != NX_EOK) + { + return NX_EFAULT; + } + if (NX_RomfsRead(file, &progHeader, sizeof(progHeader), &loadLen) != NX_EOK) + { + return NX_EIO; + } + if (loadLen != sizeof(progHeader)) + { + return NX_EIO; + } + + NX_LOG_D("elf program header[%d]: type %d, vaddr %p, file sz %p, mem sz %p", i, progHeader.p_type, progHeader.p_vaddr, progHeader.p_filesz, progHeader.p_memsz); + + if (progHeader.p_type == PT_LOAD) + { + NX_Size size = NX_MAX(progHeader.p_filesz, progHeader.p_memsz); + NX_Addr addr = (NX_Addr)progHeader.p_vaddr; + void *mappedAddr; + + NX_LOG_D("elf programe header[%d] map addr %p size %p", i, addr, size); + + if (NX_VmspaceMap(space, addr, size, NX_PAGE_ATTR_USER, 0, &mappedAddr) != NX_EOK) + { + return NX_ENOMEM; + } + if ((NX_Addr)mappedAddr != addr) + { + return NX_EFAULT; + } + } + } + return NX_EOK; +} + +NX_PRIVATE NX_Error NX_LoadFileData(NX_RomfsFile *file, NX_Size len, NX_Vmspace *space, Elf_Ehdr *elfHeader) +{ + Elf_Phdr progHeader; + NX_Offset progOff; + NX_Size loadLen = 0; + NX_Size size; + NX_Addr vaddr; + NX_Addr paddr; + NX_Addr vaddrSelf; + NX_Size chunk; + NX_Size chunkRead; + NX_Size readLen; + NX_Size memSize = 0; + int i; + + /* load segment data */ + progOff = elfHeader->e_phoff; + for (i = 0; i < elfHeader->e_phnum; i++, progOff += sizeof(progHeader)) + { + if (progOff > len) + { + return NX_EFAULT; + } + + /* read program header */ + if (NX_RomfsSeek(file, progOff, NX_ROMFS_SEEK_SET, NX_NULL) != NX_EOK) + { + return NX_EFAULT; + } + if (NX_RomfsRead(file, &progHeader, sizeof(progHeader), &loadLen) != NX_EOK) + { + return NX_EIO; + } + if (loadLen != sizeof(progHeader)) + { + return NX_EIO; + } + + if (progHeader.p_type == PT_LOAD) + { + if (progHeader.p_filesz > progHeader.p_memsz) + { + NX_LOG_E("elf program header[%d]: file size %p large than mem size %p !", i, progHeader.p_filesz, progHeader.p_memsz); + return NX_ERROR; + } + + /* read program data */ + if (progHeader.p_offset > len) + { + return NX_ERROR; + } + + if (NX_RomfsSeek(file, progHeader.p_offset, NX_ROMFS_SEEK_SET, NX_NULL) != NX_EOK) + { + return NX_EIO; + } + + size = progHeader.p_filesz; + vaddr = (NX_Addr)progHeader.p_vaddr; + readLen = 0; + + while (size > 0) + { + paddr = (NX_Addr)NX_MmuVir2Phy(&space->mmu, vaddr); /* use mmu translate to phy addr */ + NX_ASSERT(paddr); + vaddrSelf = NX_Phy2Virt(paddr); /* translate physic addr to kernel virtual addr to access */ + + chunk = (size < NX_PAGE_SIZE) ? size : NX_PAGE_SIZE; + + if (NX_RomfsRead(file, (void *)vaddrSelf, chunk, &chunkRead) != NX_EOK) + { + return NX_EIO; + } + if (chunkRead != chunk) + { + return NX_EIO; + } + + size -= chunk; + vaddr += chunk; + readLen += chunk; + } + + if (readLen != progHeader.p_filesz) + { + return NX_EIO; + } + + /* clear bss */ + if (progHeader.p_filesz < progHeader.p_memsz) /* bss area is mem size > file size */ + { + NX_Offset bssOff; + NX_Size bssSize = progHeader.p_memsz - progHeader.p_filesz; + NX_LOG_D("elf program header[%d]: bss area size %p", i, bssSize); + + bssOff = progHeader.p_filesz & NX_PAGE_MASK; /* offset in page */ + vaddr = (progHeader.p_vaddr + progHeader.p_filesz) & NX_PAGE_ADDR_MASK; /* page alinged addr */ + while (bssSize > 0) + { + chunk = (bssSize < (NX_PAGE_SIZE - bssOff)) ? bssSize : NX_PAGE_SIZE - bssOff; + paddr = (NX_Addr)NX_MmuVir2Phy(&space->mmu, vaddr); + NX_ASSERT(paddr); + vaddrSelf = NX_Phy2Virt(paddr); + NX_LOG_D("elf program header[%d]: bss clear vaddr %p, paddr %p chunk size %p", i, vaddr + bssOff, (void *)((NX_U8 *)vaddrSelf + bssOff), chunk); + NX_MemZero((void *)((NX_U8 *)vaddrSelf + bssOff), chunk); + + bssOff = 0; + bssSize -= chunk; + vaddr += NX_PAGE_SIZE; + } + } + + memSize += progHeader.p_memsz; + } + } + + NX_LOG_D("elf used memory size %p", memSize); + + /* space resize image and heap size */ + space->imageEnd = NX_PAGE_ALIGNUP(space->imageStart + memSize); + if (space->imageEnd + NX_PAGE_SIZE < space->heapStart) + { + space->heapStart = space->imageEnd + NX_PAGE_SIZE; + } + + return NX_EOK; +} + +NX_PRIVATE NX_Error NX_LoadElf(char *path, NX_RomfsFile *file, NX_Size len, NX_Vmspace *space) +{ + if (!file || !len || !space) + { + return NX_EINVAL; + } + + Elf_Ehdr elfHeader; + NX_Error err = NX_EOK; + + err = NX_LoadCheck(path, file, len, space, &elfHeader); + if (err != NX_EOK) + { + return err; + } + + err = NX_LoadMapUserSpace(file, len, space, &elfHeader); + if (err != NX_EOK) + { + NX_LOG_E("file %s do space map failed!", path); + return err; + } + + err = NX_LoadFileData(file, len, space, &elfHeader); + if (err != NX_EOK) + { + NX_LOG_E("file %s load image failed!", path); + return err; + } + + return NX_EOK; +} + /** * Load code & data for process image */ @@ -117,7 +448,6 @@ NX_PRIVATE NX_Error NX_ProcessLoadImage(NX_Process *process, char *path) NX_RomfsFile *file = NX_NULL; NX_Error err; NX_Offset len; - void *addr = NX_NULL; NX_Size imageMaxSize; NX_Vmspace *space; @@ -136,17 +466,6 @@ NX_PRIVATE NX_Error NX_ProcessLoadImage(NX_Process *process, char *path) return NX_ENOSRCH; } - NX_LOG_D("process execute file %s size is %d\n", path, len); - - space = &process->vmspace; - imageMaxSize = space->imageEnd - space->imageStart; - if (len > imageMaxSize) - { - NX_LOG_E("image too large %p than %p !", len, imageMaxSize); - NX_RomfsClose(file); - return NX_EFAULT; - } - err = NX_RomfsSeek(file, 0, NX_ROMFS_SEEK_SET, NX_NULL); if (err != NX_EOK) { @@ -155,50 +474,28 @@ NX_PRIVATE NX_Error NX_ProcessLoadImage(NX_Process *process, char *path) return NX_ENOSRCH; } - /* map code & data memory */ - if (NX_VmspaceMap(space, space->imageStart, len, NX_PAGE_ATTR_USER, 0, &addr) != NX_EOK) + NX_LOG_D("process execute file %s size is %d", path, len); + + space = &process->vmspace; + imageMaxSize = space->imageEnd - space->imageStart; + if (len > imageMaxSize) { + NX_LOG_E("image too large %p than %p !", len, imageMaxSize); NX_RomfsClose(file); - return NX_ENOMEM; + return NX_EFAULT; } - /* read file */ - NX_Addr vaddr = space->imageStart; - NX_Addr paddr; - NX_Addr vaddrSelf; - NX_Size chunk; - NX_Size chunkRead; - - while (len > 0) + err = NX_LoadElf(path, file, len, space); + if (err != NX_EOK) { - paddr = (NX_Addr)NX_MmuVir2Phy(&space->mmu, vaddr); - NX_ASSERT(paddr); - vaddrSelf = NX_Phy2Virt(paddr); - - chunk = (len < NX_PAGE_SIZE) ? len : NX_PAGE_SIZE; - - NX_RomfsRead(file, (void *)vaddrSelf, chunk, &chunkRead); - - if (chunkRead != chunk) - { - NX_LOG_E("read file failed!"); - break; - } - - len -= chunk; - vaddr += chunk; + NX_LOG_E("load elf %s failed with err %d!", path, err); + NX_RomfsClose(file); + return err; } /* close file */ NX_RomfsClose(file); - /* space resize image and heap size */ - space->imageEnd = NX_PAGE_ALIGNUP(space->imageStart + len); - if (space->imageEnd + NX_PAGE_SIZE < space->heapStart) - { - space->heapStart = space->imageEnd + NX_PAGE_SIZE; - } - return NX_EOK; } @@ -240,7 +537,7 @@ NX_Error NX_ProcessExecute(char *name, char *path, NX_U32 flags) space = &process->vmspace; /* map user stack */ - if (NX_VmspaceMap(space, space->stackEnd - NX_PAGE_SIZE, NX_PAGE_SIZE, NX_PAGE_ATTR_USER, 0, NX_NULL) != NX_EOK) + if (NX_VmspaceMap(space, space->stackEnd - NX_PROCESS_USER_SATCK_SIZE, NX_PROCESS_USER_SATCK_SIZE, NX_PAGE_ATTR_USER, 0, NX_NULL) != NX_EOK) { NX_ASSERT(NX_VmspaceUnmap(space, space->imageStart, space->imageEnd - space->imageStart) == NX_EOK); NX_ProcessDestroy(process); @@ -252,7 +549,7 @@ NX_Error NX_ProcessExecute(char *name, char *path, NX_U32 flags) if (NX_ThreadRun(thread) != NX_EOK) { - NX_ASSERT(NX_VmspaceUnmap(space, space->stackEnd - NX_PAGE_SIZE, NX_PAGE_SIZE) == NX_EOK); + NX_ASSERT(NX_VmspaceUnmap(space, space->stackEnd - NX_PROCESS_USER_SATCK_SIZE, NX_PROCESS_USER_SATCK_SIZE) == NX_EOK); NX_ASSERT(NX_VmspaceUnmap(space, space->imageStart, space->imageEnd - space->imageStart) == NX_EOK); NX_ProcessDestroy(process); NX_ThreadDestroy(thread); -- Gitee