]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
posix: remove -1 returns from ELF loader
authorTulio A M Mendes <[email protected]>
Sun, 8 Feb 2026 03:08:41 +0000 (00:08 -0300)
committerTulio A M Mendes <[email protected]>
Sun, 8 Feb 2026 03:08:41 +0000 (00:08 -0300)
Convert elf32 loader helpers to return -errno codes (EINVAL/ENOMEM/ENOENT/EIO/EFAULT) instead of -1, aligning with kernel-wide -errno syscall convention.

src/kernel/elf.c

index e13cabd834f459b41f34c830a504813fa841bb54..455022f03671caca73ee4aec79fddef816f9e50a 100644 (file)
@@ -7,6 +7,8 @@
 #include "utils.h"
 #include "vmm.h"
 
+#include "errno.h"
+
 #include "hal/cpu.h"
 
 #include <stdint.h>
@@ -27,49 +29,49 @@ static void* pmm_alloc_page_low_16mb(void) {
 }
 
 static int elf32_validate(const elf32_ehdr_t* eh, size_t file_len) {
-    if (!eh) return -1;
-    if (file_len < sizeof(*eh)) return -1;
+    if (!eh) return -EFAULT;
+    if (file_len < sizeof(*eh)) return -EINVAL;
 
     if (eh->e_ident[0] != ELF_MAGIC0 ||
         eh->e_ident[1] != ELF_MAGIC1 ||
         eh->e_ident[2] != ELF_MAGIC2 ||
         eh->e_ident[3] != ELF_MAGIC3) {
-        return -1;
+        return -EINVAL;
     }
-    if (eh->e_ident[4] != ELFCLASS32) return -1;
-    if (eh->e_ident[5] != ELFDATA2LSB) return -1;
+    if (eh->e_ident[4] != ELFCLASS32) return -EINVAL;
+    if (eh->e_ident[5] != ELFDATA2LSB) return -EINVAL;
 
-    if (eh->e_type != ET_EXEC) return -1;
-    if (eh->e_machine != EM_386) return -1;
+    if (eh->e_type != ET_EXEC) return -EINVAL;
+    if (eh->e_machine != EM_386) return -EINVAL;
 
-    if (eh->e_phentsize != sizeof(elf32_phdr_t)) return -1;
-    if (eh->e_phnum == 0) return -1;
+    if (eh->e_phentsize != sizeof(elf32_phdr_t)) return -EINVAL;
+    if (eh->e_phnum == 0) return -EINVAL;
 
     uint32_t ph_end = eh->e_phoff + (uint32_t)eh->e_phnum * (uint32_t)sizeof(elf32_phdr_t);
-    if (ph_end < eh->e_phoff) return -1;
-    if (ph_end > file_len) return -1;
+    if (ph_end < eh->e_phoff) return -EINVAL;
+    if (ph_end > file_len) return -EINVAL;
 
-    if (eh->e_entry == 0) return -1;
-    if (eh->e_entry >= X86_KERNEL_VIRT_BASE) return -1;
+    if (eh->e_entry == 0) return -EINVAL;
+    if (eh->e_entry >= X86_KERNEL_VIRT_BASE) return -EINVAL;
 
     return 0;
 }
 
 static int elf32_map_user_range(uintptr_t as, uintptr_t vaddr, size_t len, uint32_t flags) {
     if (len == 0) return 0;
-    if (vaddr == 0) return -1;
-    if (vaddr >= X86_KERNEL_VIRT_BASE) return -1;
+    if (vaddr == 0) return -EINVAL;
+    if (vaddr >= X86_KERNEL_VIRT_BASE) return -EINVAL;
 
     uintptr_t end = vaddr + len - 1;
-    if (end < vaddr) return -1;
-    if (end >= X86_KERNEL_VIRT_BASE) return -1;
+    if (end < vaddr) return -EINVAL;
+    if (end >= X86_KERNEL_VIRT_BASE) return -EINVAL;
 
     uintptr_t start_page = vaddr & ~(uintptr_t)0xFFF;
     uintptr_t end_page = end & ~(uintptr_t)0xFFF;
 
     for (uintptr_t va = start_page;; va += 0x1000) {
         void* phys = pmm_alloc_page_low_16mb();
-        if (!phys) return -1;
+        if (!phys) return -ENOMEM;
 
         vmm_as_map_page(as, (uint64_t)(uintptr_t)phys, (uint64_t)va, flags | VMM_FLAG_PRESENT | VMM_FLAG_USER);
 
@@ -80,11 +82,11 @@ static int elf32_map_user_range(uintptr_t as, uintptr_t vaddr, size_t len, uint3
 }
 
 int elf32_load_user_from_initrd(const char* filename, uintptr_t* entry_out, uintptr_t* user_stack_top_out, uintptr_t* addr_space_out) {
-    if (!filename || !entry_out || !user_stack_top_out || !addr_space_out) return -1;
-    if (!fs_root) return -1;
+    if (!filename || !entry_out || !user_stack_top_out || !addr_space_out) return -EFAULT;
+    if (!fs_root) return -EINVAL;
 
     uintptr_t new_as = vmm_as_create_kernel_clone();
-    if (!new_as) return -1;
+    if (!new_as) return -ENOMEM;
 
     uintptr_t old_as = hal_cpu_get_address_space();
     vmm_as_activate(new_as);
@@ -94,30 +96,41 @@ int elf32_load_user_from_initrd(const char* filename, uintptr_t* entry_out, uint
         uart_print("[ELF] file not found: ");
         uart_print(filename);
         uart_print("\n");
-        return -1;
+        vmm_as_activate(old_as);
+        vmm_as_destroy(new_as);
+        return -ENOENT;
     }
 
     uint32_t file_len = node->length;
-    if (file_len < sizeof(elf32_ehdr_t)) return -1;
+    if (file_len < sizeof(elf32_ehdr_t)) {
+        vmm_as_activate(old_as);
+        vmm_as_destroy(new_as);
+        return -EINVAL;
+    }
 
     uint8_t* file = (uint8_t*)kmalloc(file_len);
-    if (!file) return -1;
+    if (!file) {
+        vmm_as_activate(old_as);
+        vmm_as_destroy(new_as);
+        return -ENOMEM;
+    }
 
     uint32_t rd = vfs_read(node, 0, file_len, file);
     if (rd != file_len) {
         kfree(file);
         vmm_as_activate(old_as);
         vmm_as_destroy(new_as);
-        return -1;
+        return -EIO;
     }
 
     const elf32_ehdr_t* eh = (const elf32_ehdr_t*)file;
-    if (elf32_validate(eh, file_len) < 0) {
+    int vrc = elf32_validate(eh, file_len);
+    if (vrc < 0) {
         uart_print("[ELF] invalid ELF header\n");
         kfree(file);
         vmm_as_activate(old_as);
         vmm_as_destroy(new_as);
-        return -1;
+        return vrc;
     }
 
     const elf32_phdr_t* ph = (const elf32_phdr_t*)(file + eh->e_phoff);
@@ -131,40 +144,47 @@ int elf32_load_user_from_initrd(const char* filename, uintptr_t* entry_out, uint
             kfree(file);
             vmm_as_activate(old_as);
             vmm_as_destroy(new_as);
-            return -1;
+            return -EINVAL;
         }
         if (ph[i].p_vaddr >= X86_KERNEL_VIRT_BASE) {
             uart_print("[ELF] PT_LOAD in kernel range rejected\n");
             kfree(file);
             vmm_as_activate(old_as);
             vmm_as_destroy(new_as);
-            return -1;
+            return -EINVAL;
         }
 
         uint32_t seg_end = ph[i].p_vaddr + ph[i].p_memsz;
         if (seg_end < ph[i].p_vaddr) {
             kfree(file);
-            return -1;
+            vmm_as_activate(old_as);
+            vmm_as_destroy(new_as);
+            return -EINVAL;
         }
         if (seg_end >= X86_KERNEL_VIRT_BASE) {
             kfree(file);
-            return -1;
+            vmm_as_activate(old_as);
+            vmm_as_destroy(new_as);
+            return -EINVAL;
         }
 
         if ((uint64_t)ph[i].p_offset + (uint64_t)ph[i].p_filesz > (uint64_t)file_len) {
             uart_print("[ELF] segment outside file\n");
             kfree(file);
-            return -1;
+            vmm_as_activate(old_as);
+            vmm_as_destroy(new_as);
+            return -EINVAL;
         }
 
         const uint32_t map_flags = VMM_FLAG_RW;
 
-        if (elf32_map_user_range(new_as, (uintptr_t)ph[i].p_vaddr, (size_t)ph[i].p_memsz, map_flags) < 0) {
+        int mrc = elf32_map_user_range(new_as, (uintptr_t)ph[i].p_vaddr, (size_t)ph[i].p_memsz, map_flags);
+        if (mrc < 0) {
             uart_print("[ELF] OOM mapping user segment\n");
             kfree(file);
             vmm_as_activate(old_as);
             vmm_as_destroy(new_as);
-            return -1;
+            return mrc;
         }
 
         if (ph[i].p_filesz) {
@@ -184,12 +204,13 @@ int elf32_load_user_from_initrd(const char* filename, uintptr_t* entry_out, uint
     const uintptr_t user_stack_base = 0x00800000U;
     const size_t user_stack_size = 0x1000;
 
-    if (elf32_map_user_range(new_as, user_stack_base, user_stack_size, VMM_FLAG_RW) < 0) {
+    int src2 = elf32_map_user_range(new_as, user_stack_base, user_stack_size, VMM_FLAG_RW);
+    if (src2 < 0) {
         uart_print("[ELF] OOM mapping user stack\n");
         kfree(file);
         vmm_as_activate(old_as);
         vmm_as_destroy(new_as);
-        return -1;
+        return src2;
     }
 
     *entry_out = (uintptr_t)eh->e_entry;