/* return < 0 if error, otherwise the number of bytes loaded in memory */ int load_elf(const char *filename, int64_t virt_to_phys_addend, uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr) { int fd, data_order, host_data_order, must_swab, ret; uint8_t e_ident[EI_NIDENT]; fd = open(filename, O_RDONLY | O_BINARY); if (fd < 0) { perror(filename); return -1; } if (read(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident)) goto fail; if (e_ident[0] != ELFMAG0 || e_ident[1] != ELFMAG1 || e_ident[2] != ELFMAG2 || e_ident[3] != ELFMAG3) goto fail; #ifdef WORDS_BIGENDIAN data_order = ELFDATA2MSB; #else data_order = ELFDATA2LSB; #endif must_swab = data_order != e_ident[EI_DATA]; #ifdef TARGET_WORDS_BIGENDIAN host_data_order = ELFDATA2MSB; #else host_data_order = ELFDATA2LSB; #endif if (host_data_order != e_ident[EI_DATA]) return -1; lseek(fd, 0, SEEK_SET); if (e_ident[EI_CLASS] == ELFCLASS64) { ret = load_elf64(fd, virt_to_phys_addend, must_swab, pentry, lowaddr, highaddr); } else { ret = load_elf32(fd, virt_to_phys_addend, must_swab, pentry, lowaddr, highaddr); } close(fd); return ret; fail: close(fd); return -1; }
static int acrn_load_elf(struct vmctx *ctx, char *elf_file_name, unsigned long *entry, uint32_t *multiboot_flags) { int i, ret = 0; FILE *fp; size_t read_len = 0; unsigned int *ptr32; char *elf_buf; Elf32_Ehdr *elf_ehdr; elf_buf = calloc(1, ELF_BUF_LEN); if (elf_buf == NULL) { fprintf(stderr, "Can't allocate elf buf\r\n"); return -1; } fp = fopen(elf_file_name, "r"); if (fp == NULL) { fprintf(stderr, "Can't open elf file: %s\r\n", elf_file_name); free(elf_buf); return -1; } read_len = fread(elf_buf, 1, ELF_BUF_LEN, fp); if (read_len != ELF_BUF_LEN) { fprintf(stderr, "Can't get %ld data from elf file\n", ELF_BUF_LEN); } /* Scan the first 8k to detect whether the elf needs multboot * info prepared. */ ptr32 = (unsigned int *) elf_buf; for (i = 0; i <= ((ELF_BUF_LEN/4) - 3); i++) { if (ptr32[i] == MULTIBOOT_HEAD_MAGIC) { int j = 0; unsigned int sum = 0; /* According to multiboot spec 0.6.96 sec 3.1.2. * There are three u32: * offset field * 0 multiboot_head_magic * 4 flags * 8 checksum * The sum of these three u32 should be u32 zero. */ for (j = 0; j < 3; j++) { sum += ptr32[j + i]; } if (0 == sum) { multiboot_image = 1; *multiboot_flags = ptr32[i + 1]; } break; } } elf_ehdr = (Elf32_Ehdr *) elf_buf; if ((elf_ehdr->e_ident[EI_MAG0] != ELFMAG0) || (elf_ehdr->e_ident[EI_MAG1] != ELFMAG1) || (elf_ehdr->e_ident[EI_MAG2] != ELFMAG2) || (elf_ehdr->e_ident[EI_MAG3] != ELFMAG3)) { fprintf(stderr, "This is not elf file\n"); fclose(fp); free(elf_buf); return -1; } if (elf_ehdr->e_ident[EI_CLASS] == ELFCLASS32) { ret = load_elf32(ctx, fp, elf_buf); } else { fprintf(stderr, "No available 64bit elf loader ready yet\n"); fclose(fp); free(elf_buf); return -1; } *entry = elf_ehdr->e_entry; free(elf_buf); return ret; }
/* * Executes a program. */ PUBLIC int sys_execve(const char *filename, const char **argv, const char **envp) { int i; /* Loop index. */ struct inode *inode; /* File inode. */ struct region *reg; /* Process region. */ addr_t entry; /* Program entry point. */ addr_t sp; /* User stack pointer. */ char *name; /* File name. */ char stack[ARG_MAX]; /* Stack size. */ /* Get file name. */ if ((name = getname(filename)) == NULL) return (curr_proc->errno); /* Build arguments before freeing user memory. */ kmemset(stack, 0, ARG_MAX); if (!(sp = buildargs(stack, ARG_MAX, argv, envp))) { putname(name); return (curr_proc->errno); } /* Get file's inode. */ if ((inode = inode_name(name)) == NULL) { putname(name); return (curr_proc->errno); } /* Not a regular file. */ if (!S_ISREG(inode->mode)) { putname(name); inode_put(inode); return (-EACCES); } /* Not allowed. */ if (!permission(inode->mode, inode->uid, inode->gid, curr_proc, MAY_EXEC, 0)) { putname(name); inode_put(inode); return (-EACCES); } /* Close file descriptors. */ for (i = 0; i < OPEN_MAX; i++) { if (curr_proc->close & (1 << i)) do_close(i); } /* Detach process memory regions. */ for (i = 0; i < NR_PREGIONS; i++) detachreg(curr_proc, &curr_proc->pregs[i]); /* Reset signal handlers. */ curr_proc->restorer = NULL; for (i = 0; i < NR_SIGNALS; i++) { if (curr_proc->handlers[i] != SIG_DFL) { if (curr_proc->handlers[i] != SIG_IGN) curr_proc->handlers[i] = SIG_DFL; } } /* Load executable. */ if (!(entry = load_elf32(inode))) goto die0; /* Attach stack region. */ if ((reg = allocreg(S_IRUSR | S_IWUSR, PAGE_SIZE, REGION_DOWNWARDS)) == NULL) goto die0; if (attachreg(curr_proc, STACK(curr_proc), USTACK_ADDR - 1, reg)) goto die1; unlockreg(reg); /* Attach heap region. */ if ((reg = allocreg(S_IRUSR | S_IWUSR, PAGE_SIZE, REGION_UPWARDS)) == NULL) goto die0; if (attachreg(curr_proc, HEAP(curr_proc), UHEAP_ADDR, reg)) goto die1; unlockreg(reg); inode_put(inode); putname(name); kmemcpy((void *)(USTACK_ADDR - ARG_MAX), stack, ARG_MAX); user_mode(entry, sp); /* Will not return. */ return (0); die1: unlockreg(reg); freereg(reg); die0: inode_put(inode); putname(name); die(((SIGSEGV & 0xff) << 16) | (1 << 9)); return (-1); }