LF OS
Hobby operating system for amd64 with high ambitions
Loading...
Searching...
No Matches
elf.c
Go to the documentation of this file.
1#include "elf.h"
2#include "log.h"
3#include "string.h"
4#include "mm.h"
5#include "vm.h"
6
7ptr_t load_elf(ptr_t start, struct vm_table* context, ptr_t* data_start, ptr_t* data_end) {
9
10 if(header->ident_magic != ELF_MAGIC) {
11 logf("elf", "not an ELF file, invalid magic (%x != %x)!", header->ident_magic, ELF_MAGIC);
12 return 0;
13 }
14
15 if(header->machine != 0x3E || header->version != 1) {
16 logf("elf", "incompatible ELF file, invalid machine or version");
17 return 0;
18 }
19
20 // check if file is an executable
21 if(header->type != 0x02) {
22 logf("elf", "file not executable (%u != %u)", header->type, 2);
23 return 0;
24 }
25
26 for(int i = 0; i < header->programHeaderCount; ++i) {
27 elf_program_header_t* programHeader = (elf_program_header_t*)(start + header->programHeaderOffset + (i * header->programHeaderEntrySize));
28
29 if(programHeader->type != 1 && programHeader->type != 7) {
30 continue;
31 }
32
33 for(size_t j = 0; j < programHeader->memLength; j += 0x1000) {
34 ptr_t physical = (ptr_t)mm_alloc_pages(1);
35 memset((void*)(physical + ALLOCATOR_REGION_DIRECT_MAPPING.start), 0, 0x1000);
36 vm_context_map(context, (ptr_t)programHeader->vaddr + j, physical, 0);
37
38 if(j < programHeader->fileLength) {
39 size_t offset = (programHeader->vaddr + j) & 0xFFF;
40 size_t toCopy = programHeader->fileLength - j;
41
42 if(toCopy > (0x1000 - offset)) {
43 toCopy = 0x1000 - offset;
44 }
45
46 memcpy((void*)(offset + physical + ALLOCATOR_REGION_DIRECT_MAPPING.start), (void*)(start + programHeader->offset + j), toCopy);
47
48 if(offset) {
49 j -= offset;
50 }
51 }
52
53 }
54
55 ptr_t end = programHeader->vaddr + programHeader->memLength + 1;
56 if(*data_end <= end) {
57 *data_end = end;
58 }
59
60 if(programHeader->vaddr < *data_start) {
61 *data_start = programHeader->vaddr;
62 }
63 }
64
65 *data_end += 4096;
66 *data_end &= ~0xFFF;
67
68 return header->entrypoint;
69}
70
71elf_section_header_t* elf_section_by_name(const char* name, const void* elf) {
73
74 // "Oh deer, who wrote this code" -- littlefox 2024-02-10
76 char* sectionNames = (char*)elf + shSectionNames->offset;
77
78 for(size_t i = 0; i < eh->sectionHeaderCount; ++i) {
80
81 if(strcmp(sectionNames + sh->name, name) == 0) {
82 return sh;
83 }
84 }
85
86 return 0;
87}
88
93
100
102 elf_section_header_t* symtab = elf_section_by_name(".symtab", (void*)elf);
103 elf_section_header_t* strtab = elf_section_by_name(".strtab", (void*)elf);
104
105 if(symtab == 0 && strtab == 0) {
106 logw("elf", "Unable to load symbols as either symtab (0x%x) or strtab (0x%x) are missing", symtab, strtab);
107 return 0;
108 }
109
110 uint64_t numSymbols = symtab->size / symtab->entrySize;
111
112 size_t dataSize = sizeof(struct SymbolData) + ((sizeof(struct Symbol) * numSymbols)) + strtab->size;
113 void* data = alloc->alloc(alloc, dataSize);
114
115 struct SymbolData* header = (struct SymbolData*)data;
116 header->alloc = alloc;
117 header->numSymbols = numSymbols;
118 header->symbolNames = (char*)data + sizeof(struct SymbolData) + (sizeof(struct Symbol) * numSymbols);
119
120 memcpy(header->symbolNames, (char*)elf + strtab->offset, strtab->size);
121
122 for(size_t i = 0; i < numSymbols; ++i) {
123 elf_symbol_t* elfSymbol = (elf_symbol_t*)(elf + symtab->offset + (i * symtab->entrySize));
124 struct Symbol* symbol = (struct Symbol*)((char*)data + sizeof(struct SymbolData) + (sizeof(struct Symbol) * i));
125
126 symbol->address = elfSymbol->addr;
127 symbol->name = elfSymbol->name;
128 }
129
130 return (void*)data;
131}
132
133bool elf_symbolize(void* symbol_data, ptr_t addr, size_t* symbol_size, char* symbol) {
134 if(!symbol_data) {
135 *symbol_size = 0;
136 return false;
137 }
138
139 struct SymbolData* symbols = (struct SymbolData*)symbol_data;
140
141 int64_t best_difference = ~(1ULL<<63);
142 struct Symbol* best = 0;
143
144 for(size_t i = 0; i < symbols->numSymbols; ++i) {
145 struct Symbol* current = &symbols->symbols[i];
146 int64_t diff = addr - current->address;
147
148 if(diff > 0 && diff < best_difference) {
149 best = current;
150 best_difference = diff;
151 }
152 }
153
154 if(!best) {
155 *symbol_size = 0;
156 return false;
157 }
158
159 char* best_name = symbols->symbolNames + best->name;
160 size_t max_size = *symbol_size;
161
162 if(best_difference) {
163 *symbol_size = ksnprintf(symbol, *symbol_size, "%s(+0x%x)", best_name, best_difference);
164 } else {
165 *symbol_size = strlen(best_name) + 1;
166
167 strncpy(symbol, best_name, max_size);
168 }
169
170 return *symbol_size <= max_size;
171}
struct acpi_table_header header
Definition acpi.c:0
uint64_t ptr_t
Definition arch.h:17
unsigned int uint32_t
Definition arch.h:11
unsigned long uint64_t
Definition arch.h:14
signed long int64_t
Definition arch.h:13
bool elf_symbolize(void *symbol_data, ptr_t addr, size_t *symbol_size, char *symbol)
Definition elf.c:133
uint64_t address
Definition elf.c:90
uint32_t name
Definition elf.c:91
ptr_t load_elf(ptr_t start, struct vm_table *context, ptr_t *data_start, ptr_t *data_end)
Definition elf.c:7
char * symbolNames
Definition elf.c:97
allocator_t * alloc
Definition elf.c:95
struct Symbol symbols[0]
Definition elf.c:98
uint64_t numSymbols
Definition elf.c:96
elf_section_header_t * elf_section_by_name(const char *name, const void *elf)
Definition elf.c:71
void * elf_load_symbols(ptr_t elf, allocator_t *alloc)
Definition elf.c:101
Definition elf.c:89
#define ALLOCATOR_REGION_DIRECT_MAPPING
Definition vm.h:29
size_t strlen(const char *str)
Definition string.c:30
int strcmp(const char *s1, const char *s2)
Definition string.c:7
void * memcpy(void *dest, void const *source, size_t size)
Definition string.c:80
void * memset(void *dest, int c, size_t size)
Definition string.c:72
size_t ksnprintf(char *buffer, size_t buffer_size, const char *format,...)
Definition string.c:339
char * strncpy(char *s1, const char *s2, size_t n)
Definition string.c:42
uint16_t sectionHeaderSectionNameIndex
Definition elf.h:39
ptr_t addr
Definition elf.h:3
uint64_t entrySize
Definition elf.h:69
uint32_t name
Definition elf.h:60
uint64_t offset
Definition elf.h:64
uint64_t size
Definition elf.h:65
uint64_t addr
Definition elf.h:79
uint16_t sectionHeaderEntrySize
Definition elf.h:37
uint16_t sectionHeaderCount
Definition elf.h:38
ptr_t sectionHeaderOffset
Definition elf.h:29
uint32_t name
Definition elf.h:75
#define ELF_MAGIC
Definition elf.h:8
uint64_t memLength
Definition elf.h:52
uint64_t vaddr
Definition elf.h:49
uint32_t type
Definition elf.h:45
uint64_t fileLength
Definition elf.h:51
uint64_t fileLength
Definition elf.h:6
uint64_t offset
Definition elf.h:48
Header of ELF images.
Definition elf.h:11
Program headers in ELF images, required for preparing a program for execution.
Definition elf.h:44
Section headers in ELF images, required to read additional information from file.
Definition elf.h:59
Symbols in ELF images, there may be many.
Definition elf.h:74
allocator_t * alloc
char name[256]
Zero terminated string with the name of the file.
Definition loader.h:1
uint64_t offset
Offset where the file contents are located after LoaderStruct.
Definition loader.h:7
#define logw(component, fmt,...)
Definition log.h:44
#define logf(component, fmt,...)
Definition log.h:60
void * mm_alloc_pages(uint64_t count)
Definition mm.c:24
void *(* alloc)(struct allocator *alloc, size_t size)
Definition allocator.h:9
static void ** data_end
Definition syscalls.h:82
void vm_context_map(struct vm_table *pml4, ptr_t virtual, ptr_t physical, uint8_t pat)
Definition vm.c:406
A paging table, when this is a PML4 it may also be called context.
Definition vm.c:42