Skip to content

Commit 836d1a5

Browse files
Mod elf.c/.h
1 parent e566298 commit 836d1a5

2 files changed

Lines changed: 135 additions & 0 deletions

File tree

  • source
    • includes/executables
    • kernel/C/executables

source/includes/executables/elf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ typedef int64_t Elf64_Sxword;
9292
#define R_X86_64_JUMP_SLOT 7
9393
#define R_X86_64_RELATIVE 8
9494
#define R_X86_64_GOTPCREL 9
95+
#define R_X86_64_IRELATIVE 37
9596

9697
// Extract symbol and type from r_info
9798
#define ELF64_R_SYM(info) ((info) >> 32)

source/kernel/C/executables/elf.c

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,132 @@ static int elf_load_tls_template_from_vfs(const char* path, elf_image_info_t* in
130130
return 0;
131131
}
132132

133+
typedef uint64_t (*elf_ifunc_resolver_t)(void);
134+
135+
static int elf_apply_relocation_entries(const Elf64_Rela* relocs, uint64_t reloc_count)
136+
{
137+
if (!relocs || reloc_count == 0)
138+
return 0;
139+
140+
for (uint64_t i = 0; i < reloc_count; ++i) {
141+
const Elf64_Rela* reloc = &relocs[i];
142+
uint32_t reloc_type = ELF64_R_TYPE(reloc->r_info);
143+
uint64_t* target = (uint64_t*)reloc->r_offset;
144+
145+
if (!target) {
146+
eprintf("elf: invalid relocation target");
147+
return -1;
148+
}
149+
150+
switch (reloc_type) {
151+
case R_X86_64_RELATIVE:
152+
*target = (uint64_t)reloc->r_addend;
153+
break;
154+
155+
case R_X86_64_IRELATIVE: {
156+
elf_ifunc_resolver_t resolver = (elf_ifunc_resolver_t)(uint64_t)reloc->r_addend;
157+
*target = resolver ? resolver() : 0;
158+
break;
159+
}
160+
161+
default:
162+
break;
163+
}
164+
}
165+
166+
return 0;
167+
}
168+
169+
static int elf_apply_relocations_from_memory(void* file_base_address, uint64_t file_size, const Elf64_Ehdr* header)
170+
{
171+
if (!file_base_address || !header || header->e_shoff == 0 || header->e_shnum == 0)
172+
return 0;
173+
174+
uint64_t shdr_bytes = (uint64_t)header->e_shnum * header->e_shentsize;
175+
if (header->e_shentsize != sizeof(Elf64_Shdr) || header->e_shoff + shdr_bytes > file_size) {
176+
eprintf("elf: invalid section header table");
177+
return -1;
178+
}
179+
180+
Elf64_Shdr* shdrs = (Elf64_Shdr*)((uint8_t*)file_base_address + header->e_shoff);
181+
for (uint16_t i = 0; i < header->e_shnum; ++i) {
182+
Elf64_Shdr* sh = &shdrs[i];
183+
if (sh->sh_type != SHT_RELA || sh->sh_size == 0)
184+
continue;
185+
186+
if (sh->sh_offset + sh->sh_size > file_size || (sh->sh_size % sizeof(Elf64_Rela)) != 0) {
187+
eprintf("elf: invalid SHT_RELA bounds");
188+
return -1;
189+
}
190+
191+
if (elf_apply_relocation_entries((Elf64_Rela*)((uint8_t*)file_base_address + sh->sh_offset),
192+
sh->sh_size / sizeof(Elf64_Rela)) != 0)
193+
return -1;
194+
}
195+
196+
return 0;
197+
}
198+
199+
static int elf_apply_relocations_from_vfs(const char* path, uint32_t file_size, const Elf64_Ehdr* header)
200+
{
201+
if (!path || !header || header->e_shoff == 0 || header->e_shnum == 0)
202+
return 0;
203+
204+
uint64_t shdr_bytes = (uint64_t)header->e_shnum * header->e_shentsize;
205+
if (header->e_shentsize != sizeof(Elf64_Shdr) || header->e_shoff + shdr_bytes > file_size) {
206+
eprintf("elf: invalid section header table");
207+
return -1;
208+
}
209+
210+
Elf64_Shdr* shdrs = kmalloc(shdr_bytes);
211+
if (!shdrs) {
212+
eprintf("elf: failed to allocate section headers");
213+
return -1;
214+
}
215+
216+
if (elf_vfs_read_exact_path(path, (uint32_t)header->e_shoff, shdrs, (uint32_t)shdr_bytes) != 0) {
217+
eprintf("elf: failed to read section headers");
218+
kfree(shdrs);
219+
return -1;
220+
}
221+
222+
for (uint16_t i = 0; i < header->e_shnum; ++i) {
223+
Elf64_Shdr* sh = &shdrs[i];
224+
if (sh->sh_type != SHT_RELA || sh->sh_size == 0)
225+
continue;
226+
227+
if (sh->sh_offset + sh->sh_size > file_size || (sh->sh_size % sizeof(Elf64_Rela)) != 0) {
228+
eprintf("elf: invalid SHT_RELA bounds");
229+
kfree(shdrs);
230+
return -1;
231+
}
232+
233+
Elf64_Rela* relocs = kmalloc(sh->sh_size);
234+
if (!relocs) {
235+
eprintf("elf: failed to allocate relocations");
236+
kfree(shdrs);
237+
return -1;
238+
}
239+
240+
if (elf_vfs_read_exact_path(path, (uint32_t)sh->sh_offset, relocs, (uint32_t)sh->sh_size) != 0) {
241+
eprintf("elf: failed to read relocations");
242+
kfree(relocs);
243+
kfree(shdrs);
244+
return -1;
245+
}
246+
247+
int rc = elf_apply_relocation_entries(relocs, sh->sh_size / sizeof(Elf64_Rela));
248+
kfree(relocs);
249+
if (rc != 0) {
250+
kfree(shdrs);
251+
return -1;
252+
}
253+
}
254+
255+
kfree(shdrs);
256+
return 0;
257+
}
258+
133259
static uint64_t elf_runtime_addr_for_offset(Elf64_Phdr* headers, uint16_t phnum, uint64_t file_offset)
134260
{
135261
for (uint16_t i = 0; i < phnum; ++i) {
@@ -341,6 +467,9 @@ void* elf_load_from_memory_ex(void* file_base_address, uint64_t file_size, elf_i
341467
return NULL;
342468
}
343469

470+
if (elf_apply_relocations_from_memory(file_base_address, file_size, &header) != 0)
471+
return NULL;
472+
344473
return (void*)header.e_entry;
345474
}
346475

@@ -442,6 +571,11 @@ void* elf_load_from_vfs_ex(const char* path, elf_image_info_t* info)
442571
}
443572
}
444573

574+
if (elf_apply_relocations_from_vfs(path, size, &header) != 0) {
575+
kfree(program_headers);
576+
return NULL;
577+
}
578+
445579
kfree(program_headers);
446580
void* entry = (void*)header.e_entry;
447581
return entry;

0 commit comments

Comments
 (0)