2 * Acess2 - AcessNative
\r
4 * ELF Executable Loader Code
\r
11 #include <inttypes.h> // PRIx64
\r
16 #define DEBUG_WARN 1
\r
18 #define MKPTR(_type,_val) ((_type*)(uintptr_t)(_val))
\r
19 #define PTRMK(_type,_val) MKPTR(_type,_val)
\r
20 #define PTR(_val) ((void*)(uintptr_t)(_val))
\r
23 # define ENTER(...) printf("%s: ---- ENTER ----\n", __func__);
\r
24 # define LOG(s, ...) printf("%s: " s, __func__, __VA_ARGS__)
\r
25 # define LOGS(s) printf("%s: " s, __func__)
\r
26 # define LEAVE(...) printf("%s: ---- LEAVE ----\n", __func__);
\r
34 // === PROTOTYPES ===
\r
35 void *Elf_Load(int FD);
\r
36 void *Elf32Load(int FD, Elf32_Ehdr *hdr);
\r
37 void *Elf64Load(int FD, Elf64_Ehdr *hdr);
\r
40 void *Elf_Load(int FD)
\r
45 acess__SysRead(FD, &hdr, sizeof(hdr));
\r
47 // Check the file type
\r
48 if(hdr.e_ident[0] != 0x7F || hdr.e_ident[1] != 'E' || hdr.e_ident[2] != 'L' || hdr.e_ident[3] != 'F') {
\r
49 Warning("Non-ELF File was passed to the ELF loader\n");
\r
53 switch(hdr.e_ident[4])
\r
56 return Elf32Load(FD, (void*)&hdr);
\r
58 return Elf64Load(FD, &hdr);
\r
60 Warning("Unknown ELF class (%i)", hdr.e_ident[4]);
\r
65 void *Elf32Load(int FD, Elf32_Ehdr *hdr)
\r
72 uint32_t baseDiff = 0;
\r
76 // Check for a program header
\r
77 if(hdr->e_phoff == 0) {
\r
79 Warning("ELF File does not contain a program header\n");
\r
85 // Read Program Header Table
\r
86 phtab = malloc( sizeof(Elf32_Phdr) * hdr->e_phnum );
\r
91 LOG("hdr.e_phoff = 0x%08x\n", hdr->e_phoff);
\r
92 acess__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET);
\r
93 acess__SysRead(FD, phtab, sizeof(Elf32_Phdr) * hdr->e_phnum);
\r
97 LOG("hdr.e_phnum = %i\n", hdr->e_phnum);
\r
98 for( i = 0; i < hdr->e_phnum; i++ )
\r
100 // Ignore Non-LOAD types
\r
101 if(phtab[i].p_type != PT_LOAD)
\r
103 iPageCount += ((phtab[i].p_vaddr&0xFFF) + phtab[i].p_memsz + 0xFFF) >> 12;
\r
104 LOG("phtab[%i] = {p_vaddr:0x%x, p_memsz:0x%x}\n", i, phtab[i].p_vaddr, phtab[i].MemSize);
\r
107 LOG("iPageCount = %i\n", iPageCount);
\r
109 // Allocate Information Structure
\r
110 //ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount );
\r
111 // Fill Info Struct
\r
112 //ret->Entry = hdr.entrypoint;
\r
113 //ret->Base = -1; // Set Base to maximum value
\r
114 //ret->NumPages = iPageCount;
\r
115 //ret->Interpreter = NULL;
\r
117 // Prescan for base and size
\r
120 for( i = 0; i < hdr->e_phnum; i ++)
\r
122 if( phtab[i].p_type != PT_LOAD )
\r
124 if( phtab[i].p_vaddr < base )
\r
125 base = phtab[i].p_vaddr;
\r
126 if( phtab[i].p_vaddr + phtab[i].p_memsz > max )
\r
127 max = phtab[i].p_vaddr + phtab[i].p_memsz;
\r
130 LOG("base = %08x, max = %08x\n", base, max);
\r
133 // Find a nice space (47 address bits allowed)
\r
134 base = FindFreeRange( max, 47 );
\r
135 LOG("new base = %08x\n", base);
\r
136 if( base == 0 ) return NULL;
\r
141 for( i = 0; i < hdr->e_phnum; i++ )
\r
143 // Get Interpreter Name
\r
144 if( phtab[i].p_type == PT_INTERP )
\r
147 //if(ret->Interpreter) continue;
\r
148 tmp = malloc(phtab[i].p_filesz);
\r
149 acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);
\r
150 acess__SysRead(FD, tmp, phtab[i].p_filesz);
\r
151 //ret->Interpreter = Binary_RegInterp(tmp);
\r
152 LOG("Interpreter '%s'\n", tmp);
\r
156 // Ignore non-LOAD types
\r
157 if(phtab[i].p_type != PT_LOAD) continue;
\r
159 LOG("phtab[%i] = PT_LOAD {Adj p_vaddr:0x%x, p_offset:0x%x, p_filesz:0x%x, p_memsz:0x%x}\n",
\r
160 i, phtab[i].p_vaddr+baseDiff, phtab[i].p_offset, phtab[i].p_filesz, phtab[i].p_memsz);
\r
162 addr = phtab[i].p_vaddr + baseDiff;
\r
164 if( AllocateMemory( addr, phtab[i].p_memsz ) ) {
\r
165 fprintf(stderr, "Elf_Load: Unable to map memory at %x (0x%x bytes)\n",
\r
166 addr, phtab[i].p_memsz);
\r
171 acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);
\r
172 acess__SysRead(FD, PTRMK(void, addr), phtab[i].p_filesz);
\r
173 memset( PTRMK(char, addr) + phtab[i].p_filesz, 0, phtab[i].p_memsz - phtab[i].p_filesz );
\r
180 return PTRMK(void, base);
\r
183 void *Elf64Load(int FD, Elf64_Ehdr *hdr)
\r
188 uint64_t max, base;
\r
190 uint64_t baseDiff = 0;
\r
194 if( sizeof(void*) == 4) {
\r
195 Warning("ELF64 being loaded in 32-bit env, this may not work");
\r
198 // Check for a program header
\r
199 if(hdr->e_phoff == 0) {
\r
201 Warning("ELF File does not contain a program header\n");
\r
207 // Read Program Header Table
\r
208 phtab = malloc( sizeof(Elf64_Phdr) * hdr->e_phnum );
\r
213 LOG("hdr.e_phoff = 0x%08llx\n", (long long)hdr->e_phoff);
\r
214 acess__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET);
\r
215 acess__SysRead(FD, phtab, sizeof(Elf64_Phdr) * hdr->e_phnum);
\r
219 LOG("hdr.e_phnum = %i\n", hdr->e_phnum);
\r
220 for( i = 0; i < hdr->e_phnum; i++ )
\r
222 // Ignore Non-LOAD types
\r
223 if(phtab[i].p_type != PT_LOAD)
\r
225 iPageCount += ((phtab[i].p_vaddr&0xFFF) + phtab[i].p_memsz + 0xFFF) >> 12;
\r
226 LOG("phtab[%i] = {p_vaddr:0x%llx, p_memsz:0x%llx}\n",
\r
227 i, (long long)phtab[i].p_vaddr, (long long)phtab[i].p_memsz);
\r
230 LOG("iPageCount = %i\n", iPageCount);
\r
232 // Allocate Information Structure
\r
233 //ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount );
\r
234 // Fill Info Struct
\r
235 //ret->Entry = hdr.entrypoint;
\r
236 //ret->Base = -1; // Set Base to maximum value
\r
237 //ret->NumPages = iPageCount;
\r
238 //ret->Interpreter = NULL;
\r
240 // Prescan for base and size
\r
243 for( i = 0; i < hdr->e_phnum; i ++)
\r
245 if( phtab[i].p_type != PT_LOAD )
\r
247 if( phtab[i].p_vaddr < base )
\r
248 base = phtab[i].p_vaddr;
\r
249 if( phtab[i].p_vaddr + phtab[i].p_memsz > max )
\r
250 max = phtab[i].p_vaddr + phtab[i].p_memsz;
\r
253 LOG("base = %08lx, max = %08lx\n", base, max);
\r
256 // Find a nice space (31 address bits allowed)
\r
257 base = FindFreeRange( max, 31 );
\r
258 LOG("new base = %08lx\n", base);
\r
259 if( base == 0 ) return NULL;
\r
264 for( i = 0; i < hdr->e_phnum; i++ )
\r
266 // Get Interpreter Name
\r
267 if( phtab[i].p_type == PT_INTERP )
\r
270 //if(ret->Interpreter) continue;
\r
271 tmp = malloc(phtab[i].p_filesz+1);
\r
272 tmp[ phtab[i].p_filesz ] = 0;
\r
273 acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);
\r
274 acess__SysRead(FD, tmp, phtab[i].p_filesz);
\r
275 //ret->Interpreter = Binary_RegInterp(tmp);
\r
276 LOG("Interpreter '%s'\n", tmp);
\r
280 // Ignore non-LOAD types
\r
281 if(phtab[i].p_type != PT_LOAD) continue;
\r
283 LOG("phtab[%i] = PT_LOAD {Adj p_vaddr:0x%llx, p_offset:0x%llx, p_filesz:0x%llx, p_memsz:0x%llx}\n",
\r
285 (long long)phtab[i].p_vaddr+baseDiff, (long long)phtab[i].p_offset,
\r
286 (long long)phtab[i].p_filesz, (long long)phtab[i].p_memsz
\r
289 addr = phtab[i].p_vaddr + baseDiff;
\r
291 if( AllocateMemory( addr, phtab[i].p_memsz ) ) {
\r
292 fprintf(stderr, "Elf_Load: Unable to map memory at %"PRIx64" (0x%"PRIx64" bytes)\n",
\r
293 (uint64_t)addr, (uint64_t)phtab[i].p_memsz);
\r
298 acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);
\r
299 acess__SysRead(FD, PTRMK(void, addr), phtab[i].p_filesz);
\r
300 memset( PTRMK(char, addr) + phtab[i].p_filesz, 0, phtab[i].p_memsz - phtab[i].p_filesz );
\r
307 return PTRMK(void, base);
\r