int exec_elf(char* cmdline, int orphan) { char* execpath = strdup(cmdline); int ret = -1; int offset = 0; while(execpath[offset] != ' ' && execpath[offset] != '\0') offset++; execpath[offset] = '\0'; int fd = open(execpath, O_RDONLY); process_init_data_t init_data; if(fd != -1) { ret = 0; init_data.name = execpath; init_data.stack_size = 0x1000; init_data.priority = 0; init_data.args = cmdline; init_data.envp = environ; init_data.mem_size = elf_size(fd); init_data.data = malloc(init_data.mem_size); init_data.entry_point = load_elf(fd, init_data.data); init_data.file = load_elf_file(fd); init_data.ppid = orphan?0:getpid(); init_data.exec_type = EXEC_ELF; syscall(SYS_EXEC, (uint32_t)&init_data, (uint32_t)NULL, (uint32_t)NULL); free(init_data.data); } return ret; }
static int xc_dom_load_elf_symtab(struct xc_dom_image *dom, struct elf_binary *elf, int load) { struct elf_binary syms; const elf_shdr *shdr, *shdr2; xen_vaddr_t symtab, maxaddr; char *hdr; size_t size; int h, count, type, i, tables = 0; if ( elf_swap(elf) ) { xc_dom_printf("%s: non-native byte order, bsd symtab not supported\n", __FUNCTION__); return 0; } if ( load ) { if ( !dom->bsd_symtab_start ) return 0; size = dom->kernel_seg.vend - dom->bsd_symtab_start; hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start); *(int *)hdr = size - sizeof(int); } else { size = sizeof(int) + elf_size(elf, elf->ehdr) + elf_shdr_count(elf) * elf_size(elf, shdr); hdr = xc_dom_malloc(dom, size); if ( hdr == NULL ) return 0; dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend); } memcpy(hdr + sizeof(int), elf->image, elf_size(elf, elf->ehdr)); memcpy(hdr + sizeof(int) + elf_size(elf, elf->ehdr), elf->image + elf_uval(elf, elf->ehdr, e_shoff), elf_shdr_count(elf) * elf_size(elf, shdr)); if ( elf_64bit(elf) ) { Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int)); ehdr->e_phoff = 0; ehdr->e_phentsize = 0; ehdr->e_phnum = 0; ehdr->e_shoff = elf_size(elf, elf->ehdr); ehdr->e_shstrndx = SHN_UNDEF; } else { Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int)); ehdr->e_phoff = 0; ehdr->e_phentsize = 0; ehdr->e_phnum = 0; ehdr->e_shoff = elf_size(elf, elf->ehdr); ehdr->e_shstrndx = SHN_UNDEF; } if ( elf_init(&syms, hdr + sizeof(int), size - sizeof(int)) ) return -1; if ( xc_dom_logfile ) elf_set_logfile(&syms, xc_dom_logfile, 1); symtab = dom->bsd_symtab_start + sizeof(int); maxaddr = elf_round_up(&syms, symtab + elf_size(&syms, syms.ehdr) + elf_shdr_count(&syms) * elf_size(&syms, shdr)); xc_dom_printf("%s/%s: bsd_symtab_start=%" PRIx64 ", kernel.end=0x%" PRIx64 " -- symtab=0x%" PRIx64 ", maxaddr=0x%" PRIx64 "\n", __FUNCTION__, load ? "load" : "parse", dom->bsd_symtab_start, dom->kernel_seg.vend, symtab, maxaddr); count = elf_shdr_count(&syms); for ( h = 0; h < count; h++ ) { shdr = elf_shdr_by_index(&syms, h); type = elf_uval(&syms, shdr, sh_type); if ( type == SHT_STRTAB ) { /* Look for a strtab @i linked to symtab @h. */ for ( i = 0; i < count; i++ ) { shdr2 = elf_shdr_by_index(&syms, i); if ( (elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) && (elf_uval(&syms, shdr2, sh_link) == h) ) break; } /* Skip symtab @h if we found no corresponding strtab @i. */ if ( i == count ) { if ( elf_64bit(&syms) ) *(Elf64_Off*)(&shdr->e64.sh_offset) = 0; else *(Elf32_Off*)(&shdr->e32.sh_offset) = 0; continue; } } if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) ) { /* Mangled to be based on ELF header location. */ if ( elf_64bit(&syms) ) *(Elf64_Off*)(&shdr->e64.sh_offset) = maxaddr - symtab; else *(Elf32_Off*)(&shdr->e32.sh_offset) = maxaddr - symtab; size = elf_uval(&syms, shdr, sh_size); maxaddr = elf_round_up(&syms, maxaddr + size); tables++; xc_dom_printf("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "\n", __FUNCTION__, h, type == SHT_SYMTAB ? "symtab" : "strtab", size, maxaddr); if ( load ) { shdr2 = elf_shdr_by_index(elf, h); memcpy((void*)elf_section_start(&syms, shdr), elf_section_start(elf, shdr2), size); } } /* Name is NULL. */ if ( elf_64bit(&syms) ) *(Elf64_Half*)(&shdr->e64.sh_name) = 0; else *(Elf32_Word*)(&shdr->e32.sh_name) = 0; } if ( tables == 0 ) { xc_dom_printf("%s: no symbol table present\n", __FUNCTION__); dom->bsd_symtab_start = 0; return 0; } if ( !load ) dom->kernel_seg.vend = maxaddr; return 0; }