3 * - By John Hodge (thePowersGang)
\r
6 * - ELF Executable Loader Code
\r
12 // ---- Import linking code from userland
\r
14 #define SysDebug(v...) LOG(v)
\r
16 # define DISABLE_ELF64
\r
18 static int GetSymbol(const char *Name, void **Value, size_t *Size);
\r
19 static int GetSymbol(const char *Name, void **Value, size_t *Size) {
\r
21 if(!Binary_GetSymbol(Name, &val)) {
\r
22 Log_Notice("ELF", "Lookup of '%s' failed", Name);
\r
27 *Value = (void*)val;
\r
30 #define AddLoaded(a,b) do{}while(0)
\r
31 #define LoadLibrary(a,b,c) (Log_Debug("ELF", "Module requested lib '%s'",a),0)
\r
32 static int _SysSetMemFlags(tVAddr addr, int flag, int mask) {
\r
35 // Re-set RO, clear COW
\r
36 MM_SetFlags(addr, MM_PFLAG_RO, MM_PFLAG_RO|MM_PFLAG_COW);
\r
39 MM_SetFlags(addr, MM_PFLAG_RO|MM_PFLAG_COW, MM_PFLAG_RO|MM_PFLAG_COW);
\r
44 #include "../../../Usermode/Libraries/ld-acess.so_src/elf.c"
\r
47 #define DEBUG_WARN 1
\r
49 // === PROTOTYPES ===
\r
50 tBinary *Elf_Load(int fp);
\r
51 tBinary *Elf_Load64(int fp, Elf64_Ehdr *hdr);
\r
52 tBinary *Elf_Load32(int fp, Elf32_Ehdr *hdr);
\r
53 int Elf_Relocate(void *Base);
\r
54 int Elf_GetSymbol(void *Base, const char *Name, Uint *Ret);
\r
55 Uint Elf_Int_HashString(const char *str);
\r
58 tBinaryType gELF_Info = {
\r
60 0x464C457F, 0xFFFFFFFF, // '\x7FELF'
\r
62 Elf_Load, Elf_Relocate, Elf_GetSymbol
\r
66 tBinary *Elf_Load(int fp)
\r
71 VFS_Read(fp, sizeof(hdr), &hdr);
\r
73 // Check the file type
\r
74 if(hdr.e_ident[0] != 0x7F || hdr.e_ident[1] != 'E' || hdr.e_ident[2] != 'L' || hdr.e_ident[3] != 'F') {
\r
75 Log_Warning("ELF", "Non-ELF File was passed to the ELF loader");
\r
79 switch(hdr.e_ident[4]) // EI_CLASS
\r
82 return Elf_Load32(fp, (void*)&hdr);
\r
84 return Elf_Load64(fp, &hdr);
\r
86 Log_Warning("ELF", "Unknown EI_CLASS value %i", hdr.e_ident[4]);
\r
91 tBinary *Elf_Load64(int FD, Elf64_Ehdr *Header)
\r
94 Elf64_Phdr phtab[Header->e_phnum];
\r
99 if( Header->e_phoff == 0 )
\r
101 Log_Warning("ELF", "No program header, panic!");
\r
104 if( Header->e_shentsize != sizeof(Elf64_Shdr) ) {
\r
105 Log_Warning("ELF", "Header gives shentsize as %i, my type is %i",
\r
106 Header->e_shentsize, sizeof(Elf64_Shdr) );
\r
108 if( Header->e_phentsize != sizeof(Elf64_Phdr) ) {
\r
109 Log_Warning("ELF", "Header gives phentsize as %i, my type is %i",
\r
110 Header->e_phentsize, sizeof(Elf64_Phdr) );
\r
114 LOG(" e_ident = %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
\r
115 Header->e_ident[0], Header->e_ident[1], Header->e_ident[2], Header->e_ident[3],
\r
116 Header->e_ident[4], Header->e_ident[5], Header->e_ident[6], Header->e_ident[7],
\r
117 Header->e_ident[8], Header->e_ident[9], Header->e_ident[10], Header->e_ident[11],
\r
118 Header->e_ident[12], Header->e_ident[13], Header->e_ident[14], Header->e_ident[15]
\r
120 LOG(" e_type = %i", Header->e_type);
\r
121 LOG(" e_machine = %i", Header->e_machine);
\r
122 LOG(" e_version = %i", Header->e_version);
\r
123 LOG(" e_entry = 0x%llx", Header->e_entry);
\r
124 LOG(" e_phoff = 0x%llx", Header->e_phoff);
\r
125 LOG(" e_shoff = 0x%llx", Header->e_shoff);
\r
126 LOG(" e_flags = 0x%x", Header->e_flags);
\r
127 LOG(" e_ehsize = %i", Header->e_ehsize);
\r
128 LOG(" e_phentsize = %i", Header->e_phentsize);
\r
129 LOG(" e_phnum = %i", Header->e_phnum);
\r
130 LOG(" e_shentsize = %i", Header->e_shentsize);
\r
131 LOG(" e_shnum = %i", Header->e_shnum);
\r
132 LOG(" e_shstrndx = %i", Header->e_shstrndx);
\r
135 // Load Program Header table
\r
136 VFS_Seek(FD, Header->e_phoff, SEEK_SET);
\r
137 VFS_Read(FD, sizeof(Elf64_Phdr)*Header->e_phnum, phtab);
\r
139 // Count load segments
\r
141 for( i = 0; i < Header->e_phnum; i ++ )
\r
143 if( phtab[i].p_type != PT_LOAD ) continue ;
\r
147 // Allocate Information Structure
\r
148 ret = malloc( sizeof(tBinary) + sizeof(tBinarySection)*nLoadSegments );
\r
149 // Fill Info Struct
\r
150 ret->Entry = Header->e_entry;
\r
151 ret->Base = -1; // Set Base to maximum value
\r
152 ret->NumSections = nLoadSegments;
\r
153 ret->Interpreter = NULL;
\r
155 j = 0; // LoadSections[] index
\r
156 for( i = 0; i < Header->e_phnum; i ++ )
\r
158 LOG("phtab[%i] = {", i);
\r
159 LOG(" .p_type = %i", phtab[i].p_type);
\r
160 LOG(" .p_flags = 0x%x", phtab[i].p_flags);
\r
161 LOG(" .p_offset = 0x%llx", phtab[i].p_offset);
\r
162 LOG(" .p_vaddr = 0x%llx", phtab[i].p_vaddr);
\r
163 LOG(" .p_paddr = 0x%llx", phtab[i].p_paddr);
\r
164 LOG(" .p_filesz = 0x%llx", phtab[i].p_filesz);
\r
165 LOG(" .p_memsz = 0x%llx", phtab[i].p_memsz);
\r
166 LOG(" .p_align = 0x%llx", phtab[i].p_align);
\r
169 // Get Interpreter Name
\r
170 if( phtab[i].p_type == PT_INTERP )
\r
173 if(ret->Interpreter) continue;
\r
174 tmp = malloc(phtab[i].p_filesz);
\r
175 VFS_Seek(FD, phtab[i].p_offset, 1);
\r
176 VFS_Read(FD, phtab[i].p_filesz, tmp);
\r
177 ret->Interpreter = Binary_RegInterp(tmp);
\r
178 LOG("Interpreter '%s'", tmp);
\r
183 if( phtab[i].p_type != PT_LOAD ) continue ;
\r
185 // Find the executable base
\r
186 if( phtab[i].p_vaddr < ret->Base ) ret->Base = phtab[i].p_vaddr;
\r
188 ret->LoadSections[j].Offset = phtab[i].p_offset;
\r
189 ret->LoadSections[j].Virtual = phtab[i].p_vaddr;
\r
190 ret->LoadSections[j].FileSize = phtab[i].p_filesz;
\r
191 ret->LoadSections[j].MemSize = phtab[i].p_memsz;
\r
193 ret->LoadSections[j].Flags = 0;
\r
194 if( !(phtab[i].p_flags & PF_W) )
\r
195 ret->LoadSections[j].Flags |= BIN_SECTFLAG_RO;
\r
196 if( phtab[i].p_flags & PF_X )
\r
197 ret->LoadSections[j].Flags |= BIN_SECTFLAG_EXEC;
\r
204 tBinary *Elf_Load32(int FD, Elf32_Ehdr *Header)
\r
213 // Check architecture with current CPU
\r
214 // - TODO: Support kernel level emulation
\r
216 if( Header->machine != EM_386 )
\r
218 Log_Warning("ELF", "Unknown architecure on ELF-32");
\r
224 // Check for a program header
\r
225 if(Header->phoff == 0) {
\r
227 Log_Warning("ELF", "File does not contain a program header (phoff == 0)");
\r
233 // Read Program Header Table
\r
234 phtab = malloc( sizeof(Elf32_Phdr) * Header->phentcount );
\r
239 LOG("hdr.phoff = 0x%08x", Header->phoff);
\r
240 VFS_Seek(FD, Header->phoff, SEEK_SET);
\r
241 VFS_Read(FD, sizeof(Elf32_Phdr)*Header->phentcount, phtab);
\r
245 LOG("Header->phentcount = %i", Header->phentcount);
\r
246 for( i = 0; i < Header->phentcount; i++ )
\r
248 // Ignore Non-LOAD types
\r
249 if(phtab[i].Type != PT_LOAD)
\r
252 LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}", i, phtab[i].VAddr, phtab[i].MemSize);
\r
255 LOG("iLoadCount = %i", iLoadCount);
\r
257 // Allocate Information Structure
\r
258 ret = malloc( sizeof(tBinary) + sizeof(tBinarySection)*iLoadCount );
\r
259 // Fill Info Struct
\r
260 ret->Entry = Header->entrypoint;
\r
261 ret->Base = -1; // Set Base to maximum value
\r
262 ret->NumSections = iLoadCount;
\r
263 ret->Interpreter = NULL;
\r
267 for( i = 0; i < Header->phentcount; i++ )
\r
269 //LOG("phtab[%i].Type = 0x%x", i, phtab[i].Type);
\r
270 LOG("phtab[%i] = {", i);
\r
271 LOG(" .Type = 0x%08x", phtab[i].Type);
\r
272 LOG(" .Offset = 0x%08x", phtab[i].Offset);
\r
273 LOG(" .VAddr = 0x%08x", phtab[i].VAddr);
\r
274 LOG(" .PAddr = 0x%08x", phtab[i].PAddr);
\r
275 LOG(" .FileSize = 0x%08x", phtab[i].FileSize);
\r
276 LOG(" .MemSize = 0x%08x", phtab[i].MemSize);
\r
277 LOG(" .Flags = 0x%08x", phtab[i].Flags);
\r
278 LOG(" .Align = 0x%08x", phtab[i].Align);
\r
280 // Get Interpreter Name
\r
281 if( phtab[i].Type == PT_INTERP )
\r
284 if(ret->Interpreter) continue;
\r
285 tmp = malloc(phtab[i].FileSize);
\r
286 VFS_Seek(FD, phtab[i].Offset, 1);
\r
287 VFS_Read(FD, phtab[i].FileSize, tmp);
\r
288 ret->Interpreter = Binary_RegInterp(tmp);
\r
289 LOG("Interpreter '%s'", tmp);
\r
293 // Ignore non-LOAD types
\r
294 if(phtab[i].Type != PT_LOAD) continue;
\r
297 if(phtab[i].VAddr < ret->Base) ret->Base = phtab[i].VAddr;
\r
299 LOG("phtab[%i] = {VAddr:0x%x,Offset:0x%x,FileSize:0x%x}",
\r
300 i, phtab[i].VAddr, phtab[i].Offset, phtab[i].FileSize);
\r
302 ret->LoadSections[j].Offset = phtab[i].Offset;
\r
303 ret->LoadSections[j].FileSize = phtab[i].FileSize;
\r
304 ret->LoadSections[j].Virtual = phtab[i].VAddr;
\r
305 ret->LoadSections[j].MemSize = phtab[i].MemSize;
\r
306 ret->LoadSections[j].Flags = 0;
\r
307 if( !(phtab[i].Flags & PF_W) )
\r
308 ret->LoadSections[j].Flags |= BIN_SECTFLAG_RO;
\r
309 if( phtab[i].Flags & PF_X )
\r
310 ret->LoadSections[j].Flags |= BIN_SECTFLAG_EXEC;
\r
321 int Elf_Relocate(void *Base)
\r
323 return ElfRelocate(Base, (char**){NULL}, "") != NULL;
\r
325 int Elf_GetSymbol(void *Base, const char *Name, Uint *ret)
\r
327 return ElfGetSymbol(Base, Name, (void**)ret, NULL);
\r