2 * Acess2 - AcessNative
\r
4 * ELF Executable Loader Code
\r
15 #define DEBUG_WARN 1
\r
17 #define MKPTR(_type,_val) ((_type*)(uintptr_t)(_val))
\r
18 #define PTRMK(_type,_val) MKPTR(_type,_val)
\r
19 #define PTR(_val) ((void*)(uintptr_t)(_val))
\r
22 # define ENTER(...) printf("%s: ---- ENTER ----\n", __func__);
\r
23 # define LOG(s, ...) printf("%s: " s, __func__, __VA_ARGS__)
\r
24 # define LOGS(s) printf("%s: " s, __func__)
\r
25 # define LEAVE(...) printf("%s: ---- LEAVE ----\n", __func__);
\r
33 // === PROTOTYPES ===
\r
34 void *Elf_Load(int FD);
\r
35 void *Elf32Load(int FD, Elf32_Ehdr *hdr);
\r
36 void *Elf64Load(int FD, Elf64_Ehdr *hdr);
\r
39 void *Elf_Load(int FD)
\r
44 acess_read(FD, &hdr, sizeof(hdr));
\r
46 // Check the file type
\r
47 if(hdr.e_ident[0] != 0x7F || hdr.e_ident[1] != 'E' || hdr.e_ident[2] != 'L' || hdr.e_ident[3] != 'F') {
\r
48 Warning("Non-ELF File was passed to the ELF loader\n");
\r
52 switch(hdr.e_ident[4])
\r
55 return Elf32Load(FD, (void*)&hdr);
\r
57 return Elf64Load(FD, &hdr);
\r
59 Warning("Unknown ELF class (%i)", hdr.e_ident[4]);
\r
64 void *Elf32Load(int FD, Elf32_Ehdr *hdr)
\r
71 uint32_t baseDiff = 0;
\r
75 // Check for a program header
\r
76 if(hdr->phoff == 0) {
\r
78 Warning("ELF File does not contain a program header\n");
\r
84 // Read Program Header Table
\r
85 phtab = malloc( sizeof(Elf32_Phdr) * hdr->phentcount );
\r
90 LOG("hdr.phoff = 0x%08x\n", hdr->phoff);
\r
91 acess_seek(FD, hdr->phoff, ACESS_SEEK_SET);
\r
92 acess_read(FD, phtab, sizeof(Elf32_Phdr) * hdr->phentcount);
\r
96 LOG("hdr.phentcount = %i\n", hdr->phentcount);
\r
97 for( i = 0; i < hdr->phentcount; i++ )
\r
99 // Ignore Non-LOAD types
\r
100 if(phtab[i].Type != PT_LOAD)
\r
102 iPageCount += ((phtab[i].VAddr&0xFFF) + phtab[i].MemSize + 0xFFF) >> 12;
\r
103 LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}\n", i, phtab[i].VAddr, phtab[i].MemSize);
\r
106 LOG("iPageCount = %i\n", iPageCount);
\r
108 // Allocate Information Structure
\r
109 //ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount );
\r
110 // Fill Info Struct
\r
111 //ret->Entry = hdr.entrypoint;
\r
112 //ret->Base = -1; // Set Base to maximum value
\r
113 //ret->NumPages = iPageCount;
\r
114 //ret->Interpreter = NULL;
\r
116 // Prescan for base and size
\r
119 for( i = 0; i < hdr->phentcount; i ++)
\r
121 if( phtab[i].Type != PT_LOAD )
\r
123 if( phtab[i].VAddr < base )
\r
124 base = phtab[i].VAddr;
\r
125 if( phtab[i].VAddr + phtab[i].MemSize > max )
\r
126 max = phtab[i].VAddr + phtab[i].MemSize;
\r
129 LOG("base = %08x, max = %08x\n", base, max);
\r
132 // Find a nice space (47 address bits allowed)
\r
133 base = FindFreeRange( max, 47 );
\r
134 LOG("new base = %08x\n", base);
\r
135 if( base == 0 ) return NULL;
\r
140 for( i = 0; i < hdr->phentcount; i++ )
\r
142 // Get Interpreter Name
\r
143 if( phtab[i].Type == PT_INTERP )
\r
146 //if(ret->Interpreter) continue;
\r
147 tmp = malloc(phtab[i].FileSize);
\r
148 acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);
\r
149 acess_read(FD, tmp, phtab[i].FileSize);
\r
150 //ret->Interpreter = Binary_RegInterp(tmp);
\r
151 LOG("Interpreter '%s'\n", tmp);
\r
155 // Ignore non-LOAD types
\r
156 if(phtab[i].Type != PT_LOAD) continue;
\r
158 LOG("phtab[%i] = PT_LOAD {Adj VAddr:0x%x, Offset:0x%x, FileSize:0x%x, MemSize:0x%x}\n",
\r
159 i, phtab[i].VAddr+baseDiff, phtab[i].Offset, phtab[i].FileSize, phtab[i].MemSize);
\r
161 addr = phtab[i].VAddr + baseDiff;
\r
163 if( AllocateMemory( addr, phtab[i].MemSize ) ) {
\r
164 fprintf(stderr, "Elf_Load: Unable to map memory at %x (0x%x bytes)\n",
\r
165 addr, phtab[i].MemSize);
\r
170 acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);
\r
171 acess_read(FD, PTRMK(void, addr), phtab[i].FileSize);
\r
172 memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize );
\r
179 return PTRMK(void, base);
\r
182 void *Elf64Load(int FD, Elf64_Ehdr *hdr)
\r
187 uint64_t max, base;
\r
189 uint64_t baseDiff = 0;
\r
193 if( sizeof(void*) == 4) {
\r
194 Warning("ELF64 being loaded in 32-bit env, this may not work");
\r
197 // Check for a program header
\r
198 if(hdr->e_phoff == 0) {
\r
200 Warning("ELF File does not contain a program header\n");
\r
206 // Read Program Header Table
\r
207 phtab = malloc( sizeof(Elf64_Phdr) * hdr->e_phnum );
\r
212 LOG("hdr.phoff = 0x%08llx\n", (long long)hdr->e_phoff);
\r
213 acess_seek(FD, hdr->e_phoff, ACESS_SEEK_SET);
\r
214 acess_read(FD, phtab, sizeof(Elf64_Phdr) * hdr->e_phnum);
\r
218 LOG("hdr.phentcount = %i\n", hdr->e_phnum);
\r
219 for( i = 0; i < hdr->e_phnum; i++ )
\r
221 // Ignore Non-LOAD types
\r
222 if(phtab[i].p_type != PT_LOAD)
\r
224 iPageCount += ((phtab[i].p_vaddr&0xFFF) + phtab[i].p_memsz + 0xFFF) >> 12;
\r
225 LOG("phtab[%i] = {VAddr:0x%llx, MemSize:0x%llx}\n",
\r
226 i, (long long)phtab[i].p_vaddr, (long long)phtab[i].p_memsz);
\r
229 LOG("iPageCount = %i\n", iPageCount);
\r
231 // Allocate Information Structure
\r
232 //ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount );
\r
233 // Fill Info Struct
\r
234 //ret->Entry = hdr.entrypoint;
\r
235 //ret->Base = -1; // Set Base to maximum value
\r
236 //ret->NumPages = iPageCount;
\r
237 //ret->Interpreter = NULL;
\r
239 // Prescan for base and size
\r
242 for( i = 0; i < hdr->e_phnum; i ++)
\r
244 if( phtab[i].p_type != PT_LOAD )
\r
246 if( phtab[i].p_vaddr < base )
\r
247 base = phtab[i].p_vaddr;
\r
248 if( phtab[i].p_vaddr + phtab[i].p_memsz > max )
\r
249 max = phtab[i].p_vaddr + phtab[i].p_memsz;
\r
252 LOG("base = %08lx, max = %08lx\n", base, max);
\r
255 // Find a nice space (31 address bits allowed)
\r
256 base = FindFreeRange( max, 31 );
\r
257 LOG("new base = %08lx\n", base);
\r
258 if( base == 0 ) return NULL;
\r
263 for( i = 0; i < hdr->e_phnum; i++ )
\r
265 // Get Interpreter Name
\r
266 if( phtab[i].p_type == PT_INTERP )
\r
269 //if(ret->Interpreter) continue;
\r
270 tmp = malloc(phtab[i].p_filesz+1);
\r
271 tmp[ phtab[i].p_filesz ] = 0;
\r
272 acess_seek(FD, phtab[i].p_offset, ACESS_SEEK_SET);
\r
273 acess_read(FD, tmp, phtab[i].p_filesz);
\r
274 //ret->Interpreter = Binary_RegInterp(tmp);
\r
275 LOG("Interpreter '%s'\n", tmp);
\r
279 // Ignore non-LOAD types
\r
280 if(phtab[i].p_type != PT_LOAD) continue;
\r
282 LOG("phtab[%i] = PT_LOAD {Adj VAddr:0x%llx, Offset:0x%llx, FileSize:0x%llx, MemSize:0x%llx}\n",
\r
284 (long long)phtab[i].p_vaddr+baseDiff, (long long)phtab[i].p_offset,
\r
285 (long long)phtab[i].p_filesz, (long long)phtab[i].p_memsz
\r
288 addr = phtab[i].p_vaddr + baseDiff;
\r
290 if( AllocateMemory( addr, phtab[i].p_memsz ) ) {
\r
291 fprintf(stderr, "Elf_Load: Unable to map memory at %llx (0x%llx bytes)\n",
\r
292 (long long)addr, (long long)phtab[i].p_memsz);
\r
297 acess_seek(FD, phtab[i].p_offset, ACESS_SEEK_SET);
\r
298 acess_read(FD, PTRMK(void, addr), phtab[i].p_filesz);
\r
299 memset( PTRMK(char, addr) + phtab[i].p_filesz, 0, phtab[i].p_memsz - phtab[i].p_filesz );
\r
306 return PTRMK(void, base);
\r