feature (ELF): implemented ELF loading / segment mapping

This commit is contained in:
antifallobst 2023-03-02 17:58:04 +01:00
parent 9cfa6b5d1e
commit adb457de01
11 changed files with 254 additions and 10 deletions

View File

@ -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;

View File

@ -0,0 +1,40 @@
/*
* Copyright 2023 Antifallobst <antifallobst@systemausfall.org>
*
* 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

View File

@ -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

View File

@ -0,0 +1,55 @@
/*
* Copyright 2023 Antifallobst <antifallobst@systemausfall.org>
*
* 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

View File

@ -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);
}

View File

@ -0,0 +1,60 @@
/*
* Copyright 2023 Antifallobst <antifallobst@systemausfall.org>
*
* 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);
}
}

View File

@ -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"
};

View File

@ -0,0 +1,36 @@
/*
* Copyright 2023 Antifallobst <antifallobst@systemausfall.org>
*
* 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"
};

View File

@ -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
}

3
ramdisk/test.c Normal file
View File

@ -0,0 +1,3 @@
int _start() {
return 42;
}

BIN
ramdisk/test.elf Executable file

Binary file not shown.