bool elf_loadFile(void *elfFile, bool phys, intptr_t offset) { int i; if (elf_checkFile(elfFile) != 0) { return false; } for(i=0; i < elf_getNumProgramHeaders(elfFile); i++) { /* Load that section */ uintptr_t dest, src; size_t len; if (phys) { dest = (uintptr_t) elf_getProgramHeaderPaddr(elfFile, i); } else { dest = (uintptr_t) elf_getProgramHeaderVaddr(elfFile, i); } dest += offset; len = elf_getProgramHeaderFileSize(elfFile, i); src = (uintptr_t) elfFile + elf_getProgramHeaderOffset(elfFile, i); memcpy((void*) dest, (void*) src, len); dest += len; memset((void*) dest, 0, elf_getProgramHeaderMemorySize(elfFile, i) - len); } return true; }
/* * Load an ELF file into physical memory at the given physical address. * * Return the byte past the last byte of the physical address used. */ static paddr_t load_elf(const char *name, void *elf, paddr_t dest_paddr, struct image_info *info) { uint64_t min_vaddr, max_vaddr; size_t image_size; /* Fetch image info. */ elf_getMemoryBounds(elf, 0, &min_vaddr, &max_vaddr); max_vaddr = ROUND_UP(max_vaddr, PAGE_BITS); image_size = (size_t)(max_vaddr - min_vaddr); /* Ensure our starting physical address is aligned. */ if (!IS_ALIGNED(dest_paddr, PAGE_BITS)) { printf("Attempting to load ELF at unaligned physical address!\n"); abort(); } /* Ensure that the ELF file itself is 4-byte aligned in memory, so that * libelf can perform word accesses on it. */ if (!IS_ALIGNED(dest_paddr, 2)) { printf("Input ELF file not 4-byte aligned in memory!\n"); abort(); } /* Print diagnostics. */ printf("ELF-loading image '%s'\n", name); printf(" paddr=[%lx..%lx]\n", dest_paddr, dest_paddr + image_size - 1); printf(" vaddr=[%lx..%lx]\n", (vaddr_t)min_vaddr, (vaddr_t)max_vaddr - 1); printf(" virt_entry=%lx\n", (vaddr_t)elf_getEntryPoint(elf)); /* Ensure the ELF file is valid. */ if (elf_checkFile(elf) != 0) { printf("Attempting to load invalid ELF file '%s'.\n", name); abort(); } /* Ensure sane alignment of the image. */ if (!IS_ALIGNED(min_vaddr, PAGE_BITS)) { printf("Start of image '%s' is not 4K-aligned!\n", name); abort(); } /* Ensure that we region we want to write to is sane. */ ensure_phys_range_valid(dest_paddr, dest_paddr + image_size); /* Copy the data. */ unpack_elf_to_paddr(elf, dest_paddr); /* Record information about the placement of the image. */ info->phys_region_start = dest_paddr; info->phys_region_end = dest_paddr + image_size; info->virt_region_start = (vaddr_t)min_vaddr; info->virt_region_end = (vaddr_t)max_vaddr; info->virt_entry = (vaddr_t)elf_getEntryPoint(elf); info->phys_virt_offset = dest_paddr - (vaddr_t)min_vaddr; /* Return address of next free physical frame. */ return ROUND_UP(dest_paddr + image_size, PAGE_BITS); }
bool reios_loadElf(const string& elf) { FILE* f = fopen(elf.c_str(), "rb"); if (!f) { return false; } fseek(f, 0, SEEK_END); size_t size = ftell(f); if (size > 16 * 1024 * 1024) { return false; } void* elfFile = malloc(size); memset(elfFile, 0, size); fseek(f, 0, SEEK_SET); fread(elfFile, 1, size, f); fclose(f); int i; bool phys = false; if (elf_checkFile(elfFile) != 0) { free(elfFile); return false; } for (i = 0; i < elf_getNumProgramHeaders(elfFile); i++) { /* Load that section */ uint64_t dest, src; size_t len; if (phys) { dest = elf_getProgramHeaderPaddr(elfFile, i); } else { dest = elf_getProgramHeaderVaddr(elfFile, i); } len = elf_getProgramHeaderFileSize(elfFile, i); src = (uint64_t)(uintptr_t)elfFile + elf_getProgramHeaderOffset(elfFile, i); u8* ptr = GetMemPtr(dest, len); memcpy((void*)ptr, (void*)(uintptr_t)src, len); ptr += len; memset((void*)ptr, 0, elf_getProgramHeaderMemorySize(elfFile, i) - len); } return true; }
/* * ELF-loader for ARM systems. * * We are currently running out of physical memory, with an ELF file for the * kernel and one or more ELF files for the userspace image. (Typically there * will only be one userspace ELF file, though if we are running a multi-core * CPU, we may have multiple userspace images; one per CPU.) These ELF files * are packed into an 'ar' archive. * * The kernel ELF file indicates what physical address it wants to be loaded * at, while userspace images run out of virtual memory, so don't have any * requirements about where they are located. We place the kernel at its * desired location, and then load userspace images straight after it in * physical memory. * * Several things could possibly go wrong: * * 1. The physical load address of the kernel might want to overwrite this * ELF-loader; * * 2. The physical load addresses of the kernel might not actually be in * physical memory; * * 3. Userspace images may not fit in physical memory, or may try to overlap * the ELF-loader. * * We attempt to check for some of these, but some may go unnoticed. */ void load_images(struct image_info *kernel_info, struct image_info *user_info, int max_user_images, int *num_images) { int i; uint64_t kernel_phys_start, kernel_phys_end; paddr_t next_phys_addr; const char *elf_filename; unsigned long unused; /* Load kernel. */ void *kernel_elf = cpio_get_file(_archive_start, "kernel.elf", &unused); if (kernel_elf == NULL) { printf("No kernel image present in archive!\n"); abort(); } if (elf_checkFile(kernel_elf)) { printf("Kernel image not a valid ELF file!\n"); abort(); } elf_getMemoryBounds(kernel_elf, 1, &kernel_phys_start, &kernel_phys_end); next_phys_addr = load_elf("kernel", kernel_elf, (paddr_t)kernel_phys_start, kernel_info); /* * Load userspace images. * * We assume (and check) that the kernel is the first file in the archive, * and then load the (n+1)'th file in the archive onto the (n)'th CPU. */ (void)cpio_get_entry(_archive_start, 0, &elf_filename, &unused); if (strcmp(elf_filename, "kernel.elf") != 0) { printf("Kernel image not first image in archive.\n"); abort(); } *num_images = 0; for (i = 0; i < max_user_images; i++) { /* Fetch info about the next ELF file in the archive. */ void *user_elf = cpio_get_entry(_archive_start, i + 1, &elf_filename, &unused); if (user_elf == NULL) { break; } /* Load the file into memory. */ next_phys_addr = load_elf(elf_filename, user_elf, next_phys_addr, &user_info[*num_images]); *num_images = i + 1; } }
int elf_load (addrspace_t dest_as, char *elf_file) { int num_headers; int err; int i; /* Ensure that the ELF file looks sane. */ if (elf_checkFile(elf_file)){ return seL4_InvalidArgument; } num_headers = elf_getNumProgramHeaders(elf_file); for (i = 0; i < num_headers; i++) { char *source_addr; unsigned long flags, file_size, segment_size, vaddr; /* Skip non-loadable segments (such as debugging data). */ if (elf_getProgramHeaderType(elf_file, i) != PT_LOAD) continue; /* Fetch information about this segment. */ source_addr = elf_file + elf_getProgramHeaderOffset(elf_file, i); file_size = elf_getProgramHeaderFileSize(elf_file, i); segment_size = elf_getProgramHeaderMemorySize(elf_file, i); vaddr = elf_getProgramHeaderVaddr(elf_file, i); flags = elf_getProgramHeaderFlags(elf_file, i); /* Copy it across into the vspace. */ err = load_segment_directly_into_vspace(dest_as, source_addr, segment_size, file_size, vaddr, get_sel4_rights_from_elf(flags) & seL4_AllRights); if (err != 0) { return 1; } } return 0; }
bool elf_getMemoryBounds(void *elfFile, bool phys, uint64_t *min, uint64_t *max) { uint64_t mem_min = UINT64_MAX; uint64_t mem_max = 0; int i; if (elf_checkFile(elfFile) != 0) { return false; } for(i=0; i < elf_getNumProgramHeaders(elfFile); i++) { uint64_t sect_min, sect_max; if (elf_getProgramHeaderMemorySize(elfFile, i) == 0) { continue; } if (phys) { sect_min = elf_getProgramHeaderPaddr(elfFile, i); } else { sect_min = elf_getProgramHeaderVaddr(elfFile, i); } sect_max = sect_min + elf_getProgramHeaderMemorySize(elfFile, i); if (sect_max > mem_max) { mem_max = sect_max; } if (sect_min < mem_min) { mem_min = sect_min; } } *min = mem_min; *max = mem_max; return true; };
int elf_load(seL4_RISCV_PageDirectory dest_as, char *elf_file) { int num_headers; int err; int i; /* Ensure that the ELF file looks sane. */ if (elf_checkFile(elf_file)){ return seL4_InvalidArgument; } num_headers = elf_getNumProgramHeaders(elf_file); for (i = 0; i < num_headers; i++) { char *source_addr; unsigned long flags, file_size, segment_size, vaddr; /* Skip non-loadable segments (such as debugging data). */ if (elf_getProgramHeaderType(elf_file, i) != PT_LOAD) continue; /* Fetch information about this segment. */ source_addr = elf_file + elf_getProgramHeaderOffset(elf_file, i); file_size = elf_getProgramHeaderFileSize(elf_file, i); segment_size = elf_getProgramHeaderMemorySize(elf_file, i); vaddr = elf_getProgramHeaderVaddr(elf_file, i); flags = elf_getProgramHeaderFlags(elf_file, i); /* Copy it across into the vspace. */ dprintf(1, " * Loading segment %08x-->%08x\n", (int)vaddr, (int)(vaddr + segment_size)); err = load_segment_into_vspace(dest_as, source_addr, segment_size, file_size, vaddr, get_sel4_rights_from_elf(flags) & seL4_AllRights); conditional_panic(err != 0, "Elf loading failed!\n"); } return 0; }
static void elf_syms(FILE* out,const char* libfile) { struct stat statbuf; printf("LIBFILE \"%s\"\n", libfile); int fd = open(libfile, O_RDONLY, 0); if (!fd) { printf("Failed to open file \"%s\"\n", libfile); return; } if (fstat(fd, &statbuf) < 0) { printf("Failed to fstat file \"%s\"\n", libfile); return; } { void* data = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); close(fd); if (data == (void*)-1) { printf("Failed to mmap file \"%s\"\n", libfile); return; } //printf("MMap: %08p, %08X\n",data,statbuf.st_size); int dynsym=-1; int dynstr=-1; int strtab=-1; int symtab=-1; if (elf_checkFile(data)>=0) { int scnt=elf_getNumSections(data); for (int si=0;si<scnt;si++) { uint32_t section_type = elf_getSectionType(data, si); uint64_t section_link = elf_getSectionLink(data, si); switch (section_type) { case SHT_DYNSYM: fprintf(stderr, "DYNSYM"); dynsym = si; if (section_link < scnt) dynstr = section_link; break; case SHT_SYMTAB: fprintf(stderr, "SYMTAB"); symtab = si; if (section_link < scnt) strtab = section_link; break; default: break;; } } } else { printf("Invalid elf file\n"); } // Use SHT_SYMTAB if available insteaf of SHT_DYNSYM // (there is more info here): if (symtab >= 0 && strtab >= 0) { dynsym = symtab; dynstr = strtab; } if (dynsym >= 0) { prof_head(out,"libsym",libfile); // printf("Found dymsym %d, and dynstr %d!\n",dynsym,dynstr); elf_symbol* sym=(elf_symbol*)elf_getSection(data,dynsym); elf64_symbol* sym64 = (elf64_symbol*) sym; bool elf32 = ((struct Elf32_Header*)data)->e_ident[EI_CLASS] == ELFCLASS32; size_t symbol_size = elf32 ? sizeof(elf_symbol) : sizeof(elf64_symbol); int symcnt = elf_getSectionSize(data,dynsym) / symbol_size; for (int i=0; i < symcnt; i++) { uint64_t st_value = elf32 ? sym[i].st_value : sym64[i].st_value; uint32_t st_name = elf32 ? sym[i].st_name : sym64[i].st_name; uint16_t st_shndx = elf32 ? sym[i].st_shndx : sym64[i].st_shndx; uint16_t st_type = (elf32 ? sym[i].st_info : sym64[i].st_info) & 0xf; uint64_t st_size = elf32 ? sym[i].st_size : sym64[i].st_size; if (st_type == STT_FUNC && st_value && st_name && st_shndx) { char* name=(char*)elf_getSection(data,dynstr);// sym[i].st_shndx // printf("Symbol %d: %s, %08" PRIx64 ", % " PRIi64 " bytes\n", // i, name + st_name, st_value, st_size); //PRIx64 & friends not in android ndk (yet?) fprintf(out,"%08x %d %s\n", (int)st_value, (int)st_size, name + st_name); } } } else { printf("No dynsym\n"); } munmap(data,statbuf.st_size); } }
BOOT_CODE static paddr_t load_boot_module(multiboot_module_t* boot_module, paddr_t load_paddr) { v_region_t v_reg; word_t entry; Elf_Header_t* elf_file = (Elf_Header_t*)(word_t)boot_module->start; if (!elf_checkFile(elf_file)) { printf("Boot module does not contain a valid ELF image\n"); return 0; } v_reg = elf_getMemoryBounds(elf_file); entry = elf_file->e_entry; if (v_reg.end == 0) { printf("ELF image in boot module does not contain any segments\n"); return 0; } v_reg.end = ROUND_UP(v_reg.end, PAGE_BITS); printf("size=0x%lx v_entry=%p v_start=%p v_end=%p ", v_reg.end - v_reg.start, (void*)entry, (void*)v_reg.start, (void*)v_reg.end ); if (!IS_ALIGNED(v_reg.start, PAGE_BITS)) { printf("Userland image virtual start address must be 4KB-aligned\n"); return 0; } if (v_reg.end + 2 * BIT(PAGE_BITS) > PPTR_USER_TOP) { /* for IPC buffer frame and bootinfo frame, need 2*4K of additional userland virtual memory */ printf("Userland image virtual end address too high\n"); return 0; } if ((entry < v_reg.start) || (entry >= v_reg.end)) { printf("Userland image entry point does not lie within userland image\n"); return 0; } load_paddr = find_load_paddr(load_paddr, v_reg.end - v_reg.start); assert(load_paddr); /* fill ui_info struct */ boot_state.ui_info.pv_offset = load_paddr - v_reg.start; boot_state.ui_info.p_reg.start = load_paddr; load_paddr += v_reg.end - v_reg.start; boot_state.ui_info.p_reg.end = load_paddr; boot_state.ui_info.v_entry = entry; printf("p_start=0x%lx p_end=0x%lx\n", boot_state.ui_info.p_reg.start, boot_state.ui_info.p_reg.end ); if (!module_paddr_region_valid( boot_state.ui_info.p_reg.start, boot_state.ui_info.p_reg.end)) { printf("End of loaded userland image lies outside of usable physical memory\n"); return 0; } /* initialise all initial userland memory and load potentially sparse ELF image */ memzero( (void*)boot_state.ui_info.p_reg.start, boot_state.ui_info.p_reg.end - boot_state.ui_info.p_reg.start ); elf_load(elf_file, boot_state.ui_info.pv_offset); return load_paddr; }
void elf_load(int pid, seL4_CPtr reply_cap, void *_args, int err) { if (TMP_DEBUG) printf("elf_load\n"); elf_load_args *args = (elf_load_args *) _args; if (err) { eprintf("Error caught in elf_load\n"); args->cb(pid, reply_cap, args->cb_args, err); free(args); return; } char *elf_file = args->elf_file; int curr_header = args->curr_header; //addr_space *as = proc_table[pid]; /* Ensure that the ELF file looks sane. */ if (elf_checkFile(elf_file)){ eprintf("Error caught in elf_load\n"); args->cb(pid, reply_cap, args->cb_args, -1); free(args); return; } int num_headers = elf_getNumProgramHeaders(elf_file); if (curr_header < num_headers) { char *source_addr; unsigned long flags, file_size, segment_size, vaddr; /* Skip non-loadable segments (such as debugging data). */ if (elf_getProgramHeaderType(elf_file, curr_header) != PT_LOAD) { args->curr_header++; elf_load(pid, reply_cap, args, 0); } else { /* Fetch information about this segment. */ source_addr = elf_file + elf_getProgramHeaderOffset(elf_file, curr_header); file_size = elf_getProgramHeaderFileSize(elf_file, curr_header); segment_size = elf_getProgramHeaderMemorySize(elf_file, curr_header); vaddr = elf_getProgramHeaderVaddr(elf_file, curr_header); flags = elf_getProgramHeaderFlags(elf_file, curr_header); /* Copy it across into the vspace. */ dprintf(1, " * Loading segment %08x-->%08x\n", (int)vaddr, (int)(vaddr + segment_size)); // Set up load segment arguments args->curr_header++; load_segment_args *segment_args = malloc(sizeof(load_segment_args)); if (segment_args == NULL) { eprintf("Error caught in elf_load\n"); args->cb(pid, reply_cap, args->cb_args, -1); free(args); return; } segment_args->src = source_addr; segment_args->dst = vaddr; segment_args->pos = 0; segment_args->segment_size = segment_size; segment_args->file_size = file_size; segment_args->permissions = get_sel4_rights_from_elf(flags) & seL4_AllRights; segment_args->cb = elf_load; segment_args->cb_args = args; load_segment_into_vspace(pid, reply_cap, segment_args, 0); } //conditional_panic(err != 0, "Elf loading failed!\n"); } else { // Do callback printf("Doing callback with pid :%d\n", pid); args->cb(pid, reply_cap, args->cb_args, 0); free(args); } if (TMP_DEBUG) printf("elf_load end\n"); }
void elf_syms(FILE* out,const char* libfile) { struct stat statbuf; printf("LIBFILE \"%s\"\n", libfile); int fd = open(libfile, O_RDONLY, 0); if (!fd) { printf("Failed to open file \"%s\"\n", libfile); return; } if (fstat(fd, &statbuf) < 0) { printf("Failed to fstat file \"%s\"\n", libfile); return; } { void* data = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); close(fd); if (data == (void*)-1) { printf("Failed to mmap file \"%s\"\n", libfile); return; } //printf("MMap: %08p, %08X\n",data,statbuf.st_size); int dynsym=-1; int dynstr=-1; /* Section: 2 -> .dynsym Section: 3 -> .dynstr */ if (elf_checkFile(data)>=0) { int scnt=elf_getNumSections(data); for (int si=0;si<scnt;si++) { if (strcmp(".dynsym",elf_getSectionName(data,si))==0) dynsym=si; if (strcmp(".dynstr",elf_getSectionName(data,si))==0) dynstr=si; } } else { printf("Invalid elf file\n"); } if (dynsym >= 0) { prof_head(out,"libsym",libfile); // printf("Found dymsym %d, and dynstr %d!\n",dynsym,dynstr); elf_symbol* sym=(elf_symbol*)elf_getSection(data,dynsym); int symcnt=elf_getSectionSize(data,dynsym)/sizeof(elf_symbol); for (int i=0;i<symcnt;i++) { if (sym[i].st_value && sym[i].st_name && sym[i].st_shndx) { char* name=(char*)elf_getSection(data,dynstr);// sym[i].st_shndx // printf("Symbol %d: %s, %08X, %d bytes\n",i,name+sym[i].st_name,sym[i].st_value,sym[i].st_size); fprintf(out,"%08X %d %s\n",sym[i].st_value,sym[i].st_size,name+sym[i].st_name); } } } else { printf("No dynsym\n"); } munmap(data,statbuf.st_size); } }