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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#define ET_NONE 0x00
#define ET_REL 0x01
#define ET_EXEC 0x02
#define ET_DYN 0x03
#define ET_CORE 0x04
struct Elf32Header
{
uint8_t ident[16];
uint16_t type;
uint16_t machine;
uint32_t version;
uint32_t entry;
uint32_t phoff;
uint32_t shoff;
uint32_t flags;
uint16_t ehsize;
uint16_t phentsize;
uint16_t phnum;
uint16_t shentsize;
uint16_t shnum;
uint16_t shstrndx;
};
#define PT_NULL 0x00000000
#define PT_LOAD 0x00000001
#define PT_DYNAMIC 0x00000002
#define PT_INTERP 0x00000003
#define PT_NOTE 0x00000004
#define PT_SHLIB 0x00000005
#define PT_PHDR 0x00000006
#define PT_TLS 0x00000007
#define PF_X 0x1
#define PF_W 0x2
#define PF_R 0x4
struct Elf32ProgramHeader
{
uint32_t type;
uint32_t offset;
uint32_t vaddr;
uint32_t paddr;
uint32_t filesz;
uint32_t memsz;
uint32_t flags;
uint32_t align;
};
bool load_elf(const char* file, char* mem, uint32_t mem_size, uint32_t* start_address)
{
FILE* fp = fopen(file, "rb");
if (fp == NULL)
{
printf("Couldn't open input file\n");
return false;
}
struct Elf32Header header;
size_t read = fread(&header, sizeof(struct Elf32Header), 1, fp);
if (read != 1)
{
printf("ELF header too small\n");
return false;
}
static uint8_t kValidIdent[7] = {
0x7f, 0x45, 0x4c, 0x46,
1, 1, 1
};
if (memcmp(kValidIdent, header.ident, 7) != 0)
{
printf("Invalid ELF header\n");
return false;
}
if (header.type != ET_EXEC)
{
printf("Can only link EXEC ELF files\n");
return false;
}
memset(mem, 0, mem_size);
assert(header.phnum == 0 || header.phentsize == sizeof(struct Elf32ProgramHeader));
for (uint32_t i = 0; i < header.phnum; ++i)
{
struct Elf32ProgramHeader pheader;
fseek(fp, header.phoff + i * header.phentsize, SEEK_SET);
read = fread(&pheader, sizeof(struct Elf32ProgramHeader), 1, fp);
if (read != 1)
{
printf("Error reading program header at index %u\n", i);
return false;
}
if (pheader.type == PT_LOAD)
{
if (pheader.paddr + pheader.memsz > mem_size)
{
printf("Memory not large enough for ELF file\n");
return false;
}
fseek(fp, pheader.offset, SEEK_SET);
read = fread(mem + pheader.paddr, pheader.filesz, 1, fp);
if (read != 1)
{
printf("Error when copying ELF segment\n");
return false;
}
}
}
if (header.entry > mem_size)
{
printf("Entry address out of bounds\n");
return false;
}
*start_address = header.entry;
fclose(fp);
return true;
}
|