Fix bugs. Implement a.out symbols and relocations.
authorcoderain <coderain@sdf.org>
Sat, 11 Feb 2017 05:19:01 +0000 (06:19 +0100)
committercoderain <coderain@sdf.org>
Sat, 11 Feb 2017 05:19:01 +0000 (06:19 +0100)
kernel/include/exec/aout.h
kernel/src/char_device.c
kernel/src/exec/aout.c

index 296173f8df2e4f5324d31d78fa2d2f471a1db689..4a1e22d4e2833721c953cfbab128ef339156b6be 100644 (file)
 #define ZMAGIC 0x010B
 #define QMAGIC 0x00CC
 
+#define AOUT_TYPE_FIELD(x) ((x) & 0x1E)
+#define AOUT_SYM_UNDEFINED 0x00
+#define AOUT_SYM_EXTERN    0x01
+#define AOUT_SYM_ABSOLUTE  0x02
+#define AOUT_SYM_TEXT      0x04
+#define AOUT_SYM_DATA      0x06
+#define AOUT_SYM_BSS       0x08
+
+#pragma pack(push, 1)
+
 typedef struct
 {
     dword_t midmag;
@@ -53,7 +63,23 @@ typedef struct
     dword_t jump_table  : 1;
     dword_t relative    : 1;
     dword_t copy        : 1;
-} aout_reloc;
+} aout_reloc_t;
+
+typedef struct
+{
+    union
+    {
+        dword_t name_offset;
+        char *name;
+    };
+    
+    byte_t type;
+    byte_t other;
+    word_t reserved;
+    dword_t value;
+} aout_symbol_t;
+
+#pragma pack(pop)
 
 dword_t load_aout(handle_t file, process_params_t *parameters, thread_state_t *initial_state);
 
index e6d7c88c658e51b2ceedcb473c2fa99471bbdb24..7fa3b87a9e3e7912d77fa0715dbc8cac238fe56b 100644 (file)
@@ -29,16 +29,18 @@ static resource_t device_list_res = 0;
 
 char_device_t *get_char_device(const char *name)
 {
-    char_device_t *i;
+    list_entry_t *i;
+    char_device_t *device;
 
     acquire_resource_shared(&device_list_res);
-    for (i = (char_device_t*)char_devices.next; i != NULL; i = (char_device_t*)i->list.next)
+    for (i = char_devices.next; i != &char_devices; i = i->next)
     {
-        if (strcmp(i->name, name) == 0) break;
+        device = CONTAINER_OF(i, char_device_t, list);
+        if (strcmp(device->name, name) == 0) break;
     }
     release_resource(&device_list_res);
 
-    return i;
+    return (i != &char_devices) ? device : NULL;
 }
 
 dword_t register_char_dev_driver(char_dev_driver_t *driver)
index 4c76ad3c8ea5572f6bf6722518cd9a9afa4d8c38..ea6aace71395dd83449731e89d24b1a266978d91 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <exec/aout.h>
 #include <memory.h>
+#include <heap.h>
 #include <syscalls.h>
 
 dword_t load_aout(handle_t file, process_params_t *parameters, thread_state_t *initial_state)
@@ -27,6 +28,7 @@ dword_t load_aout(handle_t file, process_params_t *parameters, thread_state_t *i
     size_t bytes_read;
     char filename[MAX_PATH];
     qword_t filesize;
+    uintptr_t i;
 
     dword_t ret = syscall(SYSCALL_QUERY_FILE, file, FILE_INFO_NAME, filename, sizeof(filename));
     if (ret != ERR_SUCCESS) return ret;
@@ -38,6 +40,8 @@ dword_t load_aout(handle_t file, process_params_t *parameters, thread_state_t *i
     if (ret != ERR_SUCCESS) return ret;
 
     void *address = (void*)0x7FE00000;
+    void *data_address;
+    void *bss_address;
 
     ret = syscall(SYSCALL_ALLOC_MEMORY,
                   INVALID_HANDLE,
@@ -56,6 +60,9 @@ dword_t load_aout(handle_t file, process_params_t *parameters, thread_state_t *i
     {
     case OMAGIC:
     {
+        data_address = (void*)((uintptr_t)address + header.text_size + sizeof(aout_header_t));
+        bss_address = (void*)((uintptr_t)address + header.text_size + header.data_size + sizeof(aout_header_t));
+
         ret = syscall(SYSCALL_ALLOC_MEMORY,
                       INVALID_HANDLE,
                       &address,
@@ -81,8 +88,8 @@ dword_t load_aout(handle_t file, process_params_t *parameters, thread_state_t *i
     case ZMAGIC:
     {
         handle_t section;
-        void *data_address = (void*)((uintptr_t)address + PAGE_ALIGN_UP(header.text_size));
-        void *bss_address = (void*)((uintptr_t)address + PAGE_ALIGN_UP(header.text_size) + PAGE_ALIGN_UP(header.data_size));
+        data_address = (void*)((uintptr_t)address + PAGE_ALIGN_UP(header.text_size));
+        bss_address = (void*)((uintptr_t)address + PAGE_ALIGN_UP(header.text_size) + PAGE_ALIGN_UP(header.data_size));
 
         ret = syscall(SYSCALL_CREATE_MEMORY_SECTION, filename, file, (size_t)filesize, MEMORY_SECTION_WRITABLE, &section);
         if (ret != ERR_SUCCESS) return ret;
@@ -93,7 +100,11 @@ dword_t load_aout(handle_t file, process_params_t *parameters, thread_state_t *i
                       &address,
                       0ULL,
                       PAGE_ALIGN_UP(header.text_size + sizeof(aout_header_t)),
-                      MEMORY_BLOCK_ACCESSIBLE | MEMORY_BLOCK_USERMODE | MEMORY_BLOCK_EXECUTABLE | MEMORY_BLOCK_EVICTABLE);
+                      MEMORY_BLOCK_ACCESSIBLE
+                      | MEMORY_BLOCK_WRITABLE
+                      | MEMORY_BLOCK_USERMODE
+                      | MEMORY_BLOCK_EXECUTABLE
+                      | MEMORY_BLOCK_EVICTABLE);
         if (ret != ERR_SUCCESS)
         {
             syscall(SYSCALL_CLOSE_OBJECT, section);
@@ -142,6 +153,166 @@ dword_t load_aout(handle_t file, process_params_t *parameters, thread_state_t *i
         return ERR_INVALID;
     }
 
-    // TODO: relocations
-    return ERR_SUCCESS; // TODO
+    uintptr_t num_text_relocs = header.text_reloc_size / sizeof(aout_reloc_t);
+    uintptr_t num_data_relocs = header.data_reloc_size / sizeof(aout_reloc_t);
+    uintptr_t num_symbols = header.sym_size / sizeof(aout_symbol_t);
+    aout_reloc_t *text_relocs = NULL;
+    aout_reloc_t *data_relocs = NULL;
+    aout_symbol_t *symbols = NULL;
+    uintptr_t string_table_size = 0;
+    char *string_table = NULL;
+
+    if (header.text_reloc_size)
+    {
+        text_relocs = (aout_reloc_t*)malloc(header.text_reloc_size);
+        if (text_relocs == NULL) return ERR_NOMEMORY;
+
+        ret = syscall(SYSCALL_READ_FILE,
+                      file,
+                      text_relocs,
+                      (qword_t)(sizeof(aout_header_t) + header.text_size + header.data_size),
+                      header.text_reloc_size,
+                      &bytes_read);
+        if (ret != ERR_SUCCESS) goto cleanup;
+    }
+
+    if (header.data_reloc_size)
+    {
+        data_relocs = (aout_reloc_t*)malloc(header.data_reloc_size);
+        if (data_relocs == NULL) return ERR_NOMEMORY;
+
+        ret = syscall(SYSCALL_READ_FILE,
+                      file,
+                      data_relocs,
+                      (qword_t)(sizeof(aout_header_t)
+                                + header.text_size
+                                + header.data_size
+                                + header.text_reloc_size),
+                      header.data_reloc_size,
+                      &bytes_read);
+        if (ret != ERR_SUCCESS) goto cleanup;
+    }
+
+    if (header.sym_size)
+    {
+        symbols = (aout_symbol_t*)malloc(header.sym_size);
+        if (symbols == NULL) return ERR_NOMEMORY;
+
+        ret = syscall(SYSCALL_READ_FILE,
+                      file,
+                      symbols,
+                      (qword_t)(sizeof(aout_header_t)
+                                + header.text_size
+                                + header.data_size
+                                + header.text_reloc_size
+                                + header.data_reloc_size),
+                      header.sym_size,
+                      &bytes_read);
+        if (ret != ERR_SUCCESS) goto cleanup;
+    }
+
+    ret = syscall(SYSCALL_READ_FILE,
+                  file,
+                  &string_table_size,
+                  (qword_t)(sizeof(aout_header_t)
+                            + header.text_size
+                            + header.data_size
+                            + header.sym_size
+                            + header.text_reloc_size
+                            + header.data_reloc_size),
+                  sizeof(string_table_size),
+                  &bytes_read);
+    if (ret != ERR_SUCCESS) goto cleanup;
+
+    string_table = malloc(string_table_size);
+    if (string_table == NULL)
+    {
+        ret = ERR_NOMEMORY;
+        goto cleanup;
+    }
+
+    ret = syscall(SYSCALL_READ_FILE,
+                  file,
+                  string_table,
+                  (qword_t)(sizeof(aout_header_t)
+                            + header.text_size
+                            + header.data_size
+                            + header.sym_size
+                            + header.text_reloc_size
+                            + header.data_reloc_size),
+                  string_table_size,
+                  &bytes_read);
+    if (ret != ERR_SUCCESS) goto cleanup;
+
+    for (i = 0; i < num_symbols; i++)
+    {
+        symbols[i].name = (char*)((uintptr_t)string_table + symbols[i].name_offset);
+
+        switch (AOUT_TYPE_FIELD(symbols[i].type))
+        {
+        case AOUT_SYM_UNDEFINED:
+            // TODO: Resolve symbol
+            break;
+
+        case AOUT_SYM_TEXT:
+            symbols[i].value += (uintptr_t)address + sizeof(aout_header_t);
+            break;
+
+        case AOUT_SYM_DATA:
+            symbols[i].value += (uintptr_t)data_address;
+            break;
+
+        case AOUT_SYM_BSS:
+            symbols[i].value += (uintptr_t)bss_address;
+            break;
+        }
+    }
+
+    for (i = 0; i < num_text_relocs + num_data_relocs; i++)
+    {
+        aout_reloc_t *reloc = (i < num_text_relocs) ? &text_relocs[i] : &data_relocs[i];
+        uintptr_t base_address = (i < num_text_relocs) ? ((uintptr_t)address + sizeof(aout_header_t)) : (uintptr_t)data_address;
+        dword_t offset;
+
+        if (!reloc->external)
+        {
+            offset = (uintptr_t)address + sizeof(aout_header_t);
+        }
+        else
+        {
+            if (reloc->symbol_num >= num_symbols)
+            {
+                ret = ERR_INVALID;
+                goto cleanup;
+            }
+
+            offset = symbols[reloc->symbol_num].value;
+        }
+
+        switch (reloc->length)
+        {
+        case 0:
+            *(byte_t*)(base_address + reloc->address) += offset;
+            break;
+        case 1:
+            *(word_t*)(base_address + reloc->address) += offset;
+            break;
+        case 2:
+            *(dword_t*)(base_address + reloc->address) += offset;
+            break;
+        }
+    }
+
+    if ((header.midmag & 0xFFFF) == ZMAGIC)
+    {
+        syscall(SYSCALL_SET_MEMORY_FLAGS,
+                INVALID_HANDLE,
+                address,
+                MEMORY_BLOCK_ACCESSIBLE | MEMORY_BLOCK_USERMODE | MEMORY_BLOCK_EXECUTABLE | MEMORY_BLOCK_EVICTABLE);
+    }
+
+cleanup:
+    if (symbols) free(symbols);
+    if (string_table) free(string_table);
+    return ret;
 }