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
69 // Check for a program header
\r
70 if(hdr->e_phoff == 0) {
\r
72 Warning("ELF File does not contain a program header\n");
\r
78 // Read Program Header Table
\r
79 Elf32_Phdr* phtab = malloc( sizeof(Elf32_Phdr) * hdr->e_phnum );
\r
84 LOG("hdr.e_phoff = 0x%08x\n", hdr->e_phoff);
\r
85 acess__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET);
\r
86 acess__SysRead(FD, phtab, sizeof(Elf32_Phdr) * hdr->e_phnum);
\r
89 unsigned int iPageCount = 0;
\r
90 LOG("hdr.e_phnum = %i\n", hdr->e_phnum);
\r
91 for( unsigned int i = 0; i < hdr->e_phnum; i++ )
\r
93 // Ignore Non-LOAD types
\r
94 if(phtab[i].p_type != PT_LOAD)
\r
96 iPageCount += ((phtab[i].p_vaddr&0xFFF) + phtab[i].p_memsz + 0xFFF) >> 12;
\r
97 LOG("phtab[%i] = {p_vaddr:0x%x, p_memsz:0x%x}\n", i, phtab[i].p_vaddr, phtab[i].MemSize);
\r
100 LOG("iPageCount = %i\n", iPageCount);
\r
102 // Allocate Information Structure
\r
103 //ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount );
\r
104 // Fill Info Struct
\r
105 //ret->Entry = hdr.entrypoint;
\r
106 //ret->Base = -1; // Set Base to maximum value
\r
107 //ret->NumPages = iPageCount;
\r
108 //ret->Interpreter = NULL;
\r
110 // Prescan for base and size
\r
112 uint32_t base = UINT32_MAX;
\r
113 for( unsigned int i = 0; i < hdr->e_phnum; i ++)
\r
115 if( phtab[i].p_type != PT_LOAD )
\r
117 if( phtab[i].p_vaddr < base )
\r
118 base = phtab[i].p_vaddr;
\r
119 if( phtab[i].p_vaddr + phtab[i].p_memsz > max )
\r
120 max = phtab[i].p_vaddr + phtab[i].p_memsz;
\r
123 LOG("base = %08x, max = %08x\n", base, max);
\r
125 uint32_t baseDiff = 0;
\r
127 // Find a nice space (47 address bits allowed)
\r
128 base = FindFreeRange( max, 47 );
\r
129 LOG("new base = %08x\n", base);
\r
130 if( base == 0 ) return NULL;
\r
135 for( unsigned int i = 0; i < hdr->e_phnum; i++ )
\r
137 // Get Interpreter Name
\r
138 if( phtab[i].p_type == PT_INTERP )
\r
141 //if(ret->Interpreter) continue;
\r
142 tmp = malloc(phtab[i].p_filesz);
\r
143 acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);
\r
144 acess__SysRead(FD, tmp, phtab[i].p_filesz);
\r
145 //ret->Interpreter = Binary_RegInterp(tmp);
\r
146 LOG("Interpreter '%s'\n", tmp);
\r
150 // Ignore non-LOAD types
\r
151 if(phtab[i].p_type != PT_LOAD) continue;
\r
153 LOG("phtab[%i] = PT_LOAD {Adj p_vaddr:0x%x, p_offset:0x%x, p_filesz:0x%x, p_memsz:0x%x}\n",
\r
154 i, phtab[i].p_vaddr+baseDiff, phtab[i].p_offset, phtab[i].p_filesz, phtab[i].p_memsz);
\r
156 uint64_t addr = phtab[i].p_vaddr + baseDiff;
\r
158 if( AllocateMemory( addr, phtab[i].p_memsz ) ) {
\r
159 fprintf(stderr, "Elf_Load: Unable to map memory at 0x%"PRIx64" (0x%x bytes)\n",
\r
160 addr, phtab[i].p_memsz);
\r
165 acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);
\r
166 acess__SysRead(FD, PTRMK(void, addr), phtab[i].p_filesz);
\r
167 memset( PTRMK(char, addr) + phtab[i].p_filesz, 0, phtab[i].p_memsz - phtab[i].p_filesz );
\r
174 return PTRMK(void, base);
\r
177 void *Elf64Load(int FD, Elf64_Ehdr *hdr)
\r
181 if( sizeof(void*) == 4) {
\r
182 Warning("ELF64 being loaded in 32-bit env, this may not work");
\r
185 // Check for a program header
\r
186 if(hdr->e_phoff == 0) {
\r
188 Warning("ELF File does not contain a program header\n");
\r
194 // Read Program Header Table
\r
195 Elf64_Phdr* phtab = malloc( sizeof(Elf64_Phdr) * hdr->e_phnum );
\r
200 LOG("hdr.e_phoff = 0x%08llx\n", (long long)hdr->e_phoff);
\r
201 acess__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET);
\r
202 acess__SysRead(FD, phtab, sizeof(Elf64_Phdr) * hdr->e_phnum);
\r
205 unsigned int iPageCount = 0;
\r
206 LOG("hdr.e_phnum = %i\n", hdr->e_phnum);
\r
207 for( unsigned int i = 0; i < hdr->e_phnum; i++ )
\r
209 // Ignore Non-LOAD types
\r
210 if(phtab[i].p_type != PT_LOAD)
\r
212 iPageCount += ((phtab[i].p_vaddr&0xFFF) + phtab[i].p_memsz + 0xFFF) >> 12;
\r
213 LOG("phtab[%i] = {p_vaddr:0x%llx, p_memsz:0x%llx}\n",
\r
214 i, (long long)phtab[i].p_vaddr, (long long)phtab[i].p_memsz);
\r
217 LOG("iPageCount = %i\n", iPageCount);
\r
219 // Allocate Information Structure
\r
220 //ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount );
\r
221 // Fill Info Struct
\r
222 //ret->Entry = hdr.entrypoint;
\r
223 //ret->Base = -1; // Set Base to maximum value
\r
224 //ret->NumPages = iPageCount;
\r
225 //ret->Interpreter = NULL;
\r
227 // Prescan for base and size
\r
229 uint64_t base = UINT64_MAX;
\r
230 for( unsigned int i = 0; i < hdr->e_phnum; i ++)
\r
232 if( phtab[i].p_type != PT_LOAD )
\r
234 if( phtab[i].p_vaddr < base )
\r
235 base = phtab[i].p_vaddr;
\r
236 if( phtab[i].p_vaddr + phtab[i].p_memsz > max )
\r
237 max = phtab[i].p_vaddr + phtab[i].p_memsz;
\r
240 LOG("base = %08lx, max = %08lx\n", base, max);
\r
242 uint64_t baseDiff = 0;
\r
244 // Find a nice space (31 address bits allowed)
\r
245 base = FindFreeRange( max, 31 );
\r
246 LOG("new base = %08lx\n", base);
\r
253 for( unsigned int i = 0; i < hdr->e_phnum; i++ )
\r
255 // Get Interpreter Name
\r
256 if( phtab[i].p_type == PT_INTERP )
\r
259 //if(ret->Interpreter) continue;
\r
260 tmp = malloc(phtab[i].p_filesz+1);
\r
261 tmp[ phtab[i].p_filesz ] = 0;
\r
262 acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);
\r
263 acess__SysRead(FD, tmp, phtab[i].p_filesz);
\r
264 //ret->Interpreter = Binary_RegInterp(tmp);
\r
265 LOG("Interpreter '%s'\n", tmp);
\r
269 // Ignore non-LOAD types
\r
270 if(phtab[i].p_type != PT_LOAD) continue;
\r
272 LOG("phtab[%i] = PT_LOAD {Adj p_vaddr:0x%llx, p_offset:0x%llx, p_filesz:0x%llx, p_memsz:0x%llx}\n",
\r
274 (long long)phtab[i].p_vaddr+baseDiff, (long long)phtab[i].p_offset,
\r
275 (long long)phtab[i].p_filesz, (long long)phtab[i].p_memsz
\r
278 uint64_t addr = phtab[i].p_vaddr + baseDiff;
\r
280 if( AllocateMemory( addr, phtab[i].p_memsz ) ) {
\r
281 fprintf(stderr, "Elf_Load: Unable to map memory at %"PRIx64" (0x%"PRIx64" bytes)\n",
\r
282 (uint64_t)addr, (uint64_t)phtab[i].p_memsz);
\r
286 acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);
\r
287 acess__SysRead(FD, PTRMK(void, addr), phtab[i].p_filesz);
\r
288 memset( PTRMK(char, addr) + phtab[i].p_filesz, 0, phtab[i].p_memsz - phtab[i].p_filesz );
\r
295 return PTRMK(void, base);
\r