libsel4utils: transition to new libelf API
diff --git a/libsel4utils/include/sel4utils/elf.h b/libsel4utils/include/sel4utils/elf.h index 0da263e..517a80e 100644 --- a/libsel4utils/include/sel4utils/elf.h +++ b/libsel4utils/include/sel4utils/elf.h
@@ -16,7 +16,7 @@ #include <vka/vka.h> #include <vspace/vspace.h> -#include <elf.h> +#include <elf/elf.h> #if CONFIG_WORD_SIZE == 64 #define Elf_Phdr Elf64_Phdr @@ -69,7 +69,7 @@ */ void * sel4utils_elf_load_record_regions(vspace_t *loadee, vspace_t *loader, vka_t *loadee_vka, - vka_t *loader_vka, const char *image_name, sel4utils_elf_region_t *regions, int mapanywhere); + vka_t *loader_vka, elf_t *elf, sel4utils_elf_region_t *regions, int mapanywhere); /** * Wrapper for sel4utils_elf_load_record_regions. Does not record/perform reservations and @@ -85,7 +85,7 @@ */ void * sel4utils_elf_load(vspace_t *loadee, vspace_t *loader, vka_t *loadee_vka, - vka_t *loader_vka, const char *image_name); + vka_t *loader_vka, elf_t *elf); /** * Parses an elf file but does not actually load it. Merely reserves the regions in the vspace @@ -99,7 +99,7 @@ * @return The entry point of the elf, NULL on error */ void * -sel4utils_elf_reserve(vspace_t *loadee, const char *image_name, sel4utils_elf_region_t *regions); +sel4utils_elf_reserve(vspace_t *loadee, elf_t *elf, sel4utils_elf_region_t *regions); /** * Parses an elf file and returns the number of loadable regions. The result of this @@ -110,7 +110,7 @@ * @return Number of loadable regions in the elf */ int -sel4utils_elf_num_regions(const char *image_name); +sel4utils_elf_num_regions(elf_t *elf); /** * Looks for the __vsyscall section in an elf file and returns the value. This @@ -120,7 +120,7 @@ * * @return Address of vsyscall function or 0 if not found */ -uintptr_t sel4utils_elf_get_vsyscall(const char *image_name); +uintptr_t sel4utils_elf_get_vsyscall(elf_t *elf); /** * Finds the section_name section in an elf file and returns the address. @@ -133,7 +133,7 @@ * * @return Address of section or 0 if not found */ -uintptr_t sel4utils_elf_get_section(const char *image_name, const char *section_name, uint64_t* section_size); +uintptr_t sel4utils_elf_get_section(elf_t *elf, const char *section_name, uint64_t* section_size); /** * Parses an elf file and returns the number of phdrs. The result of this @@ -142,7 +142,7 @@ * @param image_name name of the image in the cpio archive to inspect * @return Number of phdrs in the elf */ -uint32_t sel4utils_elf_num_phdrs(const char *image_name); +uint32_t sel4utils_elf_num_phdrs(elf_t *elf); /** * Parse an elf file and retrieve all the phdrs @@ -153,5 +153,5 @@ * * @return Number of phdrs retrieved */ -void sel4utils_elf_read_phdrs(const char *image_name, uint32_t max_phdrs, Elf_Phdr *phdrs); +void sel4utils_elf_read_phdrs(elf_t *elf, size_t max_phdrs, Elf_Phdr *phdrs);
diff --git a/libsel4utils/src/elf.c b/libsel4utils/src/elf.c index aa6fc74..18db1f3 100644 --- a/libsel4utils/src/elf.c +++ b/libsel4utils/src/elf.c
@@ -14,16 +14,12 @@ #include <string.h> #include <sel4/sel4.h> #include <elf/elf.h> -#include <cpio/cpio.h> #include <vka/capops.h> #include <sel4utils/thread.h> #include <sel4utils/util.h> #include <sel4utils/mapping.h> #include <sel4utils/elf.h> -/* This library works with our cpio set up in the build system */ -extern char _cpio_archive[]; - /* * Convert ELF permissions into seL4 permissions. * @@ -172,15 +168,18 @@ */ static int load_segments(vspace_t *loadee_vspace, vspace_t *loader_vspace, - vka_t *loadee_vka, vka_t *loader_vka, char *elf_file, + vka_t *loadee_vka, vka_t *loader_vka, elf_t *elf_file, int num_regions, sel4utils_elf_region_t regions[num_regions]) { for (int i = 0; i < num_regions; i++) { int segment_index = regions[i].segment_index; - char *source_addr = elf_file + elf_getProgramHeaderOffset(elf_file, segment_index); + char *source_addr = elf_getProgramSegment(elf_file, segment_index); + if (source_addr == NULL) { + return 1; + } size_t file_size = elf_getProgramHeaderFileSize(elf_file, segment_index); int error = load_segment(loadee_vspace, loader_vspace, loadee_vka, loader_vka, - source_addr, file_size, num_regions, regions, i); + source_addr, file_size, num_regions, regions, i); if (error) { return error; } @@ -188,12 +187,12 @@ return 0; } -static bool is_loadable_section(char* elf_file, int index) { +static bool is_loadable_section(elf_t *elf_file, int index) { return elf_getProgramHeaderType(elf_file, index) == PT_LOAD; } static int -count_loadable_regions(char* elf_file) { +count_loadable_regions(elf_t *elf_file) { int num_headers = elf_getNumProgramHeaders(elf_file); int loadable_headers = 0; @@ -207,15 +206,8 @@ } int -sel4utils_elf_num_regions(const char *image_name) +sel4utils_elf_num_regions(elf_t *elf_file) { - unsigned long elf_size; - assert(image_name); - char *elf_file = cpio_get_file(_cpio_archive, image_name, &elf_size); - if (elf_file == NULL) { - ZF_LOGE("ERROR: failed to load elf file %s", image_name); - return 0; - } return count_loadable_regions(elf_file); } @@ -360,7 +352,7 @@ * @return 0 on success. */ static int -read_regions(char* elf_file, size_t total_regions, sel4utils_elf_region_t regions[total_regions]) { +read_regions(elf_t *elf_file, size_t total_regions, sel4utils_elf_region_t regions[total_regions]) { int num_headers = elf_getNumProgramHeaders(elf_file); int region_id = 0; for (int i = 0; i < num_headers; i++) { @@ -373,7 +365,7 @@ region->cacheable = 1; region->rights = rights_from_elf(elf_getProgramHeaderFlags(elf_file, i)); // elf_getProgramHeaderMemorySize should just return `uintptr_t` - region->elf_vstart = (void*)(uintptr_t)elf_getProgramHeaderVaddr(elf_file, i); + region->elf_vstart = (void *) elf_getProgramHeaderVaddr(elf_file, i); region->size = elf_getProgramHeaderMemorySize(elf_file, i); region->segment_index = i; region_id++; @@ -426,7 +418,7 @@ * @return 0 on success. */ static int -elf_reserve_regions_in_vspace(vspace_t *loadee, char* elf_file, +elf_reserve_regions_in_vspace(vspace_t *loadee, elf_t *elf_file, int num_regions, sel4utils_elf_region_t regions[num_regions], int mapanywhere) { int error = read_regions(elf_file, num_regions, regions); if (error) { @@ -451,7 +443,7 @@ } static void * -entry_point(char *elf_file) { +entry_point(elf_t *elf_file) { uint64_t entry_point = elf_getEntryPoint(elf_file); if ((uint32_t) (entry_point >> 32) != 0) { ZF_LOGE("ERROR: this code hasn't been tested for 64bit!"); @@ -464,15 +456,8 @@ void * -sel4utils_elf_reserve(vspace_t *loadee, const char *image_name, sel4utils_elf_region_t *regions) +sel4utils_elf_reserve(vspace_t *loadee, elf_t *elf_file, sel4utils_elf_region_t *regions) { - unsigned long elf_size; - char *elf_file = cpio_get_file(_cpio_archive, image_name, &elf_size); - if (elf_file == NULL) { - ZF_LOGE("ERROR: failed to load elf file %s", image_name); - return NULL; - } - /* Count number of loadable segments */ int num_regions = count_loadable_regions(elf_file); @@ -488,15 +473,8 @@ } void * -sel4utils_elf_load_record_regions(vspace_t *loadee, vspace_t *loader, vka_t *loadee_vka, vka_t *loader_vka, const char *image_name, sel4utils_elf_region_t *regions, int mapanywhere) +sel4utils_elf_load_record_regions(vspace_t *loadee, vspace_t *loader, vka_t *loadee_vka, vka_t *loader_vka, elf_t *elf_file, sel4utils_elf_region_t *regions, int mapanywhere) { - unsigned long elf_size; - char *elf_file = cpio_get_file(_cpio_archive, image_name, &elf_size); - if (elf_file == NULL) { - ZF_LOGE("ERROR: failed to load elf file %s", image_name); - return NULL; - } - /* Calculate number of loadable regions. Use stack array if one wasn't passed in */ int num_regions = count_loadable_regions(elf_file); bool clear_at_end = false; @@ -533,23 +511,17 @@ return entry_point(elf_file); } -uintptr_t sel4utils_elf_get_vsyscall(const char *image_name) +uintptr_t sel4utils_elf_get_vsyscall(elf_t *elf_file) { - uintptr_t* addr = (uintptr_t*)sel4utils_elf_get_section(image_name, "__vsyscall", NULL); + uintptr_t* addr = (uintptr_t*)sel4utils_elf_get_section(elf_file, "__vsyscall", NULL); /* Hope everything is good and just dereference it */ return *addr; } -uintptr_t sel4utils_elf_get_section(const char *image_name, const char *section_name, uint64_t* section_size) +uintptr_t sel4utils_elf_get_section(elf_t *elf_file, const char *section_name, uint64_t* section_size) { - unsigned long elf_size; - char *elf_file = cpio_get_file(_cpio_archive, image_name, &elf_size); - if (elf_file == NULL) { - ZF_LOGE("ERROR: failed to lookup elf file %s", image_name); - return 0; - } /* See if we can find the section */ - int section_id; + size_t section_id; void *addr = elf_getSectionNamed(elf_file, section_name, §ion_id); if (addr) { if (section_size != NULL) { @@ -562,38 +534,30 @@ } void * -sel4utils_elf_load(vspace_t *loadee, vspace_t *loader, vka_t *loadee_vka, vka_t *loader_vka, const char *image_name) +sel4utils_elf_load(vspace_t *loadee, vspace_t *loader, vka_t *loadee_vka, vka_t *loader_vka, elf_t *elf_file) { - return sel4utils_elf_load_record_regions(loadee, loader, loadee_vka, loader_vka, image_name, NULL, 0); + return sel4utils_elf_load_record_regions(loadee, loader, loadee_vka, loader_vka, elf_file, NULL, 0); } uint32_t -sel4utils_elf_num_phdrs(const char *image_name) +sel4utils_elf_num_phdrs(elf_t *elf_file) { - unsigned long elf_size; - char *elf_file = cpio_get_file(_cpio_archive, image_name, &elf_size); return elf_getNumProgramHeaders(elf_file); } void -sel4utils_elf_read_phdrs(const char *image_name, uint32_t max_phdrs, Elf_Phdr *phdrs) +sel4utils_elf_read_phdrs(elf_t *elf_file, size_t max_phdrs, Elf_Phdr *phdrs) { - unsigned long elf_size; - char *elf_file = cpio_get_file(_cpio_archive, image_name, &elf_size); - uint32_t num_phdrs = elf_getNumProgramHeaders(elf_file); - for (uint32_t i = 0; i < num_phdrs && i < max_phdrs; i++) { - /* cannot take addresses directly from the final struct as the types might - * be different, so store into locals first */ - uint64_t p_vaddr, p_paddr, p_filesz, p_offset, p_memsz; - elf_getProgramHeaderInfo(elf_file, i, &p_vaddr, &p_paddr, &p_filesz, &p_offset, &p_memsz); + size_t num_phdrs = elf_getNumProgramHeaders(elf_file); + for (size_t i = 0; i < num_phdrs && i < max_phdrs; i++) { phdrs[i] = (Elf_Phdr) { .p_type = elf_getProgramHeaderType(elf_file, i), - .p_offset = p_offset, - .p_vaddr = p_vaddr, - .p_paddr = p_paddr, - .p_filesz = p_filesz, - .p_memsz = p_memsz, - .p_flags = elf_getProgramHeaderFlags(elf_file,i), + .p_offset = elf_getProgramHeaderOffset(elf_file, i), + .p_vaddr = elf_getProgramHeaderVaddr(elf_file, i), + .p_paddr = elf_getProgramHeaderPaddr(elf_file, i), + .p_filesz = elf_getProgramHeaderFileSize(elf_file, i), + .p_memsz = elf_getProgramHeaderMemorySize(elf_file, i), + .p_flags = elf_getProgramHeaderFlags(elf_file, i), .p_align = elf_getProgramHeaderAlign(elf_file, i) }; }
diff --git a/libsel4utils/src/process.c b/libsel4utils/src/process.c index 9275e52..fb9bb63 100644 --- a/libsel4utils/src/process.c +++ b/libsel4utils/src/process.c
@@ -16,7 +16,8 @@ #include <string.h> #include <stdio.h> #include <inttypes.h> -#include <elf.h> +#include <elf/elf.h> +#include <cpio/cpio.h> #include <sel4/sel4.h> #include <vka/object.h> #include <vka/capops.h> @@ -28,6 +29,9 @@ #include <sel4utils/mapping.h> #include <sel4utils/helpers.h> +/* This library works with our cpio set up in the build system */ +extern char _cpio_archive[]; + void sel4utils_allocated_object(void *cookie, vka_object_t object) { @@ -581,16 +585,21 @@ /* finally elf load */ if (config.is_elf) { + unsigned long size; + char *file = cpio_get_file(_cpio_archive, config.image_name, &size); + elf_t elf; + elf_newFile(file, size, &elf); + if (config.do_elf_load) { - process->entry_point = sel4utils_elf_load(&process->vspace, spawner_vspace, vka, vka, config.image_name); + process->entry_point = sel4utils_elf_load(&process->vspace, spawner_vspace, vka, vka, &elf); } else { - process->num_elf_regions = sel4utils_elf_num_regions(config.image_name); + process->num_elf_regions = sel4utils_elf_num_regions(&elf); process->elf_regions = calloc(process->num_elf_regions, sizeof(*process->elf_regions)); if (!process->elf_regions) { ZF_LOGE("Failed to allocate memory for elf region information"); goto error; } - process->entry_point = sel4utils_elf_reserve(&process->vspace, config.image_name, process->elf_regions); + process->entry_point = sel4utils_elf_reserve(&process->vspace, &elf, process->elf_regions); } if (process->entry_point == NULL) { @@ -598,16 +607,16 @@ goto error; } - process->sysinfo = sel4utils_elf_get_vsyscall(config.image_name); + process->sysinfo = sel4utils_elf_get_vsyscall(&elf); /* Retrieve the ELF phdrs */ - process->num_elf_phdrs = sel4utils_elf_num_phdrs(config.image_name); + process->num_elf_phdrs = sel4utils_elf_num_phdrs(&elf); process->elf_phdrs = calloc(process->num_elf_phdrs, sizeof(Elf_Phdr)); if (!process->elf_phdrs) { ZF_LOGE("Failed to allocate memory for elf phdr information"); goto error; } - sel4utils_elf_read_phdrs(config.image_name, process->num_elf_phdrs, process->elf_phdrs); + sel4utils_elf_read_phdrs(&elf, process->num_elf_phdrs, process->elf_phdrs); } else { process->entry_point = config.entry_point; process->sysinfo = config.sysinfo;