blob: dfc6df614de3d5ee443fc5c28befa0be2b726842 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
#include <kc/kc.h>
#include <elf/elf64.h>
#include <stddef.h>
#define STARTCODE __attribute__((section(".text.start")))
STARTCODE
static void do_rela(Elf64_Rela *rela, void *base)
{
union
{
Elf_Byte word8;
Elf64_Half word16;
Elf64_Word word32;
Elf64_Xword word64;
}
*fixup;
switch (ELF64_R_TYPE(rela->r_info))
{
case R_AMD64_RELATIVE:
fixup = (void *)(rela->r_offset + (uintptr_t)base);
fixup->word64 = (rela->r_addend + (uintptr_t)base);
break;
default:
break;
}
}
STARTCODE
void kc_reloc(Elf64_Dyn *dyn, void *base)
{
struct
{
Elf64_Rela *entries;
size_t *size;
size_t *entsize;
}
rela = {NULL, NULL, NULL};
// parse the dynamic segment
while (dyn && dyn++->d_tag != DT_NULL)
{
switch (dyn->d_tag)
{
case DT_RELA:
rela.entries = (Elf64_Rela *)(dyn->d_ptr + (uintptr_t)base);
break;
case DT_RELASZ:
rela.size = &dyn->d_val;
break;
case DT_RELAENT:
rela.entsize = &dyn->d_val;
break;
default:
break;
}
}
// perform the actual relocation
for (size_t i = 0; rela.entries && (i < *rela.size / *rela.entsize); i++)
{
do_rela(&rela.entries[i], base);
}
}
|