From adb457de019cf3a7bb02f2b28c048f7b21a635d7 Mon Sep 17 00:00:00 2001 From: antifallobst Date: Thu, 2 Mar 2023 17:58:04 +0100 Subject: [PATCH] feature (ELF): implemented ELF loading / segment mapping --- kernel/inc/drivers/elf/elf.h | 3 ++ kernel/inc/drivers/elf/mapping.h | 40 +++++++++++++++++++++ kernel/inc/drivers/elf/section.h | 6 ++-- kernel/inc/drivers/elf/segment.h | 55 ++++++++++++++++++++++++++++ kernel/src/drivers/elf/elf.c | 40 ++++++++++++++++++++- kernel/src/drivers/elf/mapping.c | 60 +++++++++++++++++++++++++++++++ kernel/src/drivers/elf/section.c | 6 ++-- kernel/src/drivers/elf/segment.c | 36 +++++++++++++++++++ kernel/src/kmain.c | 15 +++++--- ramdisk/test.c | 3 ++ ramdisk/test.elf | Bin 0 -> 13704 bytes 11 files changed, 254 insertions(+), 10 deletions(-) create mode 100644 kernel/inc/drivers/elf/mapping.h create mode 100644 kernel/inc/drivers/elf/segment.h create mode 100644 kernel/src/drivers/elf/mapping.c create mode 100644 kernel/src/drivers/elf/segment.c create mode 100644 ramdisk/test.c create mode 100755 ramdisk/test.elf diff --git a/kernel/inc/drivers/elf/elf.h b/kernel/inc/drivers/elf/elf.h index fe0e332..d82f161 100644 --- a/kernel/inc/drivers/elf/elf.h +++ b/kernel/inc/drivers/elf/elf.h @@ -26,12 +26,15 @@ #include "drivers/elf/header.h" #include "drivers/elf/section.h" +#include "drivers/elf/mapping.h" #include "utils/symbol.h" typedef struct { elf_header_T header; uint64_t num_symbols; symbol_T* symbols; + uint64_t num_mappings; + elf_mapping_T* mappings; void* string_table; } elf_executable_T; diff --git a/kernel/inc/drivers/elf/mapping.h b/kernel/inc/drivers/elf/mapping.h new file mode 100644 index 0000000..a86cc26 --- /dev/null +++ b/kernel/inc/drivers/elf/mapping.h @@ -0,0 +1,40 @@ +/* + * Copyright 2023 Antifallobst + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the “Software”), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef NOX_MAPPING_H +#define NOX_MAPPING_H + +#include "utils/stdtypes.h" +#include "mm/page_map.h" + +typedef struct { + uint64_t offset_file; + uint64_t offset_virtual; + uint64_t length_file; + uint64_t length_virtual; + uint64_t alignment; +} elf_mapping_T; + +void elf_mappings_apply(elf_mapping_T* mappings, uint64_t num_mappings, uint8_t* buffer, void* base, page_map_T* page_map); + +#endif //NOX_MAPPING_H diff --git a/kernel/inc/drivers/elf/section.h b/kernel/inc/drivers/elf/section.h index 3a40535..4c0fcae 100644 --- a/kernel/inc/drivers/elf/section.h +++ b/kernel/inc/drivers/elf/section.h @@ -36,7 +36,9 @@ typedef enum { ELF_SECTION_HASH, ELF_SECTION_DYNAMIC_LINK, ELF_SECTION_NOTE, - ELF_SECTION_NOBITS + ELF_SECTION_NOBITS, + + ELF_SECTION_ENUM_END } elf_section_type_E; typedef struct { @@ -52,6 +54,6 @@ typedef struct { uint64_t entry_size; } elf_section_T; -extern string_t g_elf_section_type_strings[9]; +extern string_t g_elf_section_type_strings[ELF_SECTION_ENUM_END+1]; #endif //NOX_SECTION_H diff --git a/kernel/inc/drivers/elf/segment.h b/kernel/inc/drivers/elf/segment.h new file mode 100644 index 0000000..e005fa7 --- /dev/null +++ b/kernel/inc/drivers/elf/segment.h @@ -0,0 +1,55 @@ +/* + * Copyright 2023 Antifallobst + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the “Software”), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef NOX_SEGMENT_H +#define NOX_SEGMENT_H + +#include "utils/stdtypes.h" +#include "utils/string.h" + +typedef enum { + ELF_SEGMENT_NULL, + ELF_SEGMENT_LOAD, + ELF_SEGMENT_DYNAMIC, + ELF_SEGMENT_INTERPRETER, + ELF_SEGMENT_NOTE, + ELF_SEGMENT_PROGRAM_HEADER_TABLE, + ELF_SEGMENT_TLS, + + ELF_SEGMENT_ENUM_END +} elf_segment_type_E; + +typedef struct { + uint32_t type; + uint32_t flags; + uint64_t offset; + uint64_t address_virtual; + uint64_t address_physical; + uint64_t length_file; + uint64_t length_memory; + uint64_t align; +} elf_segment_T; + +extern string_t g_elf_segment_type_strings[ELF_SEGMENT_ENUM_END+1]; + +#endif //NOX_SEGMENT_H diff --git a/kernel/src/drivers/elf/elf.c b/kernel/src/drivers/elf/elf.c index 5951bbb..c539355 100644 --- a/kernel/src/drivers/elf/elf.c +++ b/kernel/src/drivers/elf/elf.c @@ -23,8 +23,10 @@ #include "drivers/elf/elf.h" #include "drivers/elf/symbol.h" +#include "drivers/elf/segment.h" #include "utils/memory.h" #include "utils/logger.h" +#include "utils/math.h" // TEMPORARY BLOCK BEGIN @@ -123,7 +125,7 @@ elf_executable_T* elf_executable_create(uint8_t* buffer) { for (int i = 0; i < executable_temp.executable->header.num_section_header_entries; i++) { string_t name = (string_t)&(&buffer[executable_temp.section_header_string_table->offset])[sections[i].name_offset]; - log(LOG_INFO, " [%s] '%s'", g_elf_section_type_strings[sections[i].type], name); + log(LOG_INFO, " [%s] '%s'", g_elf_section_type_strings[MIN(sections[i].type, ELF_SECTION_ENUM_END)], name); switch (sections[i].type) { case ELF_SECTION_SYMBOL_TABLE: { @@ -141,6 +143,41 @@ elf_executable_T* elf_executable_create(uint8_t* buffer) { } } + log(LOG_INFO, "Program Headers:"); + executable_temp.executable->num_mappings = 0; + + elf_segment_T* segments = (elf_segment_T*)&buffer[executable_temp.executable->header.offset_program_header]; + for (int i = 0; i < executable_temp.executable->header.num_program_header_entries; i++) { + log(LOG_INFO, " %s", g_elf_segment_type_strings[MIN(segments[i].type, ELF_SEGMENT_ENUM_END)]); + + switch (segments[i].type) { + case ELF_SEGMENT_LOAD: { + executable_temp.executable->num_mappings++; + break; + } + } + } + + executable_temp.executable->mappings = memory_allocate(executable_temp.executable->num_mappings * sizeof(elf_mapping_T)); + + uint64_t mappings_index = 0; + segments = (elf_segment_T*)&buffer[executable_temp.executable->header.offset_program_header]; + for (int i = 0; i < executable_temp.executable->header.num_program_header_entries; i++) { + switch (segments[i].type) { + case ELF_SEGMENT_LOAD: { + executable_temp.executable->mappings[mappings_index] = (elf_mapping_T){ + .offset_file = segments[i].offset, + .offset_virtual = segments[i].address_virtual, + .length_file = segments[i].length_file, + .length_virtual = segments[i].length_memory, + .alignment = segments[i].align + }; + mappings_index++; + break; + } + } + } + elf_executable_extract_symbols(&executable_temp); return executable_temp.executable; @@ -149,5 +186,6 @@ elf_executable_T* elf_executable_create(uint8_t* buffer) { void elf_executable_destruct(elf_executable_T* executable) { memory_free(executable->string_table); memory_free(executable->symbols); + memory_free(executable->mappings); memory_free(executable); } \ No newline at end of file diff --git a/kernel/src/drivers/elf/mapping.c b/kernel/src/drivers/elf/mapping.c new file mode 100644 index 0000000..386d8e0 --- /dev/null +++ b/kernel/src/drivers/elf/mapping.c @@ -0,0 +1,60 @@ +/* + * Copyright 2023 Antifallobst + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the “Software”), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "drivers/elf/mapping.h" +#include "mm/page_frame.h" +#include "utils/math.h" +#include "utils/logger.h" +#include "utils/memory.h" + +void elf_mapping_apply(elf_mapping_T* mapping, uint8_t* buffer, void* base, page_map_T* page_map) { + uint64_t num_pages = CEIL_TO(mapping->length_virtual, PFRAME_SIZE) / PFRAME_SIZE; + log(LOG_INFO, "Mapping: 0x%x -> 0x%x PAGES[%d]", mapping->offset_file, base + mapping->offset_virtual, num_pages); + + void* virtual_address = base + mapping->offset_virtual; + + for (uint64_t i = 0; i < num_pages; i++) { + void* physical_address = pframe_request(); + page_map_map_memory(page_map, virtual_address + (PFRAME_SIZE * i), physical_address, PM_FLAG_READ_WRITE); + page_map_map_memory(g_kernel_page_map, virtual_address + (PFRAME_SIZE * i), physical_address, PM_FLAG_READ_WRITE); + log(LOG_INFO, " mapped 0x%x", virtual_address + (PFRAME_SIZE * i)); + } + + if (mapping->length_virtual > mapping->length_file) { + memory_set(virtual_address + mapping->length_file, 0, mapping->length_virtual - mapping->length_file); + } + + log(LOG_INFO, "Copying data 0x%x --[%d]-> 0x%x", &buffer[mapping->offset_file], mapping->length_file, virtual_address); + + memory_copy(&buffer[mapping->offset_file], virtual_address, mapping->length_file); + +// for (uint64_t i = 0; i < num_pages; i++) { +// page_map_unmap_memory(g_kernel_page_map, virtual_address + (PFRAME_SIZE * i)); +// } +} + +void elf_mappings_apply(elf_mapping_T* mappings, uint64_t num_mappings, uint8_t* buffer, void* base, page_map_T* page_map) { + for (uint64_t i = 0; i < num_mappings; i++) { + elf_mapping_apply(&mappings[i], buffer, base, page_map); + } +} \ No newline at end of file diff --git a/kernel/src/drivers/elf/section.c b/kernel/src/drivers/elf/section.c index b2b2426..547f47c 100644 --- a/kernel/src/drivers/elf/section.c +++ b/kernel/src/drivers/elf/section.c @@ -23,7 +23,7 @@ #include "drivers/elf/section.h" -string_t g_elf_section_type_strings[9] = { +string_t g_elf_section_type_strings[ELF_SECTION_ENUM_END+1] = { "Null", "Program Data", "Symbol Table", @@ -32,5 +32,7 @@ string_t g_elf_section_type_strings[9] = { "Hash", "Dynamic Linker Info", "Note", - "No Bits" + "No Bits", + + "Unknown" }; \ No newline at end of file diff --git a/kernel/src/drivers/elf/segment.c b/kernel/src/drivers/elf/segment.c new file mode 100644 index 0000000..9e1c31b --- /dev/null +++ b/kernel/src/drivers/elf/segment.c @@ -0,0 +1,36 @@ +/* + * Copyright 2023 Antifallobst + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the “Software”), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "drivers/elf/segment.h" + +string_t g_elf_segment_type_strings[ELF_SEGMENT_ENUM_END+1] = { + "Null", + "Loadable", + "Dynamic Linker Info", + "Interpreter Info", + "Note", + "Program Header Table", + "Thread Local Storage", + + "Unknown" +}; \ No newline at end of file diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index ef25116..d768a8a 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -78,10 +78,6 @@ void kernel_init(boot_info_T* boot_info) { limine_terminal_print(boot_info, " ok\n"); } -void test() { - int test = 1 / 0; -} - void kmain(boot_info_T boot_info) { limine_terminal_print(&boot_info, "Booting NoxOS...\n"); @@ -94,7 +90,16 @@ void kmain(boot_info_T boot_info) { elf_init_kernel_exec(&boot_info); - test(); + vfs_node_T* node = vfs_resolve_path(&g_root_fs, "/initrd/test.elf"); + + elf_executable_T* exec = elf_executable_create(node->cache->buffer); + + page_map_T* page_map = pframe_request(); + elf_mappings_apply(exec->mappings, exec->num_mappings, node->cache->buffer, 0xFFFFFFFFFF000000, page_map); + + int (*entry)() = (0xFFFFFFFFFF000000 + symbol_resolve_from_name(exec->symbols, exec->num_symbols, "_start")->address); + + log(LOG_DEBUG, "ELF returned: %d", entry()); CORE_HALT_FOREVER } diff --git a/ramdisk/test.c b/ramdisk/test.c new file mode 100644 index 0000000..6bc3483 --- /dev/null +++ b/ramdisk/test.c @@ -0,0 +1,3 @@ +int _start() { + return 42; +} \ No newline at end of file diff --git a/ramdisk/test.elf b/ramdisk/test.elf new file mode 100755 index 0000000000000000000000000000000000000000..9dbc48d62cbf21e4f8413e3b0737d42e3bb5ffbd GIT binary patch literal 13704 zcmeHO&r4KM7`>yGWm!`g2)1}siwt~@lbHRW6n{gCDJ~-8HO{=631>!To}_J}jZiD0 zf1qu<+O-T?WCS5CqD5QR)uIrBrtf?2JHzXxP$uExyYM{sp8K8q`YyJyIRT4>dsraF4{*60)wDGaKO1 zfHpvkkdbwprPtCP(8xSkw~Iwmj^aLP5QzF}f0hJ9a9n6$SjXNZ+Jk_^rC)JXbU^6X zuD{X2PxgebZkc}+6Ve|rs>_NliYG(|x^!KOtf$uk`_SxJ_S7-ZdrfoJ?m|tjH=a@#6JL%W+xGcK(nHn0KqBRqH z!5s88QYOkzT*q@_n>qf~`rGOEkC$#AdvoL2bnTO-(;v^i<3QHq;<6@nKpjvA)B$xs z9Z(0<0d+tfPzSclfvMpKYtK(nYu8_HSCiU~I-m}y1L}Y}pbn@5>VP_+4yXg_fI6TK z>@WvnEw$(QyQKf!@^htv@5A{18oN7TVhizD%l`U3%M`@lyqB6G^hyC{k;@f4w=`$$LeX>WTZMUhu2h_JOWtCLnwihhzVckg_yO5eIcx09 zVu2bB&?_0+a~C{gyIJREDV2AfY=$_L{HRnumo|2~n9sWfPfYj+Xdx}%Q#r2j+qn#! z!$22!o>4wd8M<3l{buJ65FdTGyCV9{&LKe0`{~1JgbLqi?O^;^pFoTs>owZ{BK1VEb=-*g=San_D z_dH>LJ417aD#H3^(F4076vX^N-=_?ZU0!?Db&hivs}hL$L637952>E}$M264UM2YX z3@47|6vpb@gDU^8B@KQMu91+R0rZdix0g7KT|#|W7yX4WNqO`On%`p^={w~;`Uru7 GQTY0 literal 0 HcmV?d00001