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, &section_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;