AcessNative - TCP client implimented, buggy
[tpg/acess2.git] / KernelLand / Kernel / bin / elf.c
1 /*\r
2  * Acess v0.1\r
3  * ELF Executable Loader Code\r
4  */\r
5 #define DEBUG   0\r
6 #include <acess.h>\r
7 #include <binary.h>\r
8 \r
9 #define _COMMON_H\r
10 #define SysDebug(v...)  LOG(v)\r
11 #if BITS <= 32\r
12 # define DISABLE_ELF64\r
13 #endif\r
14 void    *GetSymbol(const char *Name, size_t *Size);\r
15 void    *GetSymbol(const char *Name, size_t *Size) { Uint val; Binary_GetSymbol(Name, &val); if(Size)*Size=0; return (void*)val; };\r
16 #define AddLoaded(a,b)  do{}while(0)\r
17 #define LoadLibrary(a,b,c)      (Log_Debug("ELF", "Module requested lib '%s'",a),0)\r
18 #include "../../../Usermode/Libraries/ld-acess.so_src/elf.c"\r
19 \r
20 #define DEBUG_WARN      1\r
21 \r
22 // === PROTOTYPES ===\r
23 tBinary *Elf_Load(int fp);\r
24 tBinary *Elf_Load64(int fp, Elf64_Ehdr *hdr);\r
25 tBinary *Elf_Load32(int fp, Elf32_Ehdr *hdr);\r
26  int    Elf_Relocate(void *Base);\r
27  int    Elf_GetSymbol(void *Base, const char *Name, Uint *Ret);\r
28 Uint    Elf_Int_HashString(const char *str);\r
29 \r
30 // === GLOBALS ===\r
31 tBinaryType     gELF_Info = {\r
32         NULL,\r
33         0x464C457F, 0xFFFFFFFF, // '\x7FELF'\r
34         "ELF",\r
35         Elf_Load, Elf_Relocate, Elf_GetSymbol\r
36         };\r
37 \r
38 // === CODE ===\r
39 tBinary *Elf_Load(int fp)\r
40 {\r
41         Elf64_Ehdr      hdr;\r
42         \r
43         // Read ELF Header\r
44         VFS_Read(fp, sizeof(hdr), &hdr);\r
45         \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                 Log_Warning("ELF", "Non-ELF File was passed to the ELF loader");\r
49                 return NULL;\r
50         }\r
51 \r
52         switch(hdr.e_ident[4])  // EI_CLASS\r
53         {\r
54         case ELFCLASS32:\r
55                 return Elf_Load32(fp, (void*)&hdr);\r
56         case ELFCLASS64:\r
57                 return Elf_Load64(fp, &hdr);\r
58         default:\r
59                 Log_Warning("ELF", "Unknown EI_CLASS value %i", hdr.e_ident[4]);\r
60                 return NULL;\r
61         }\r
62 }\r
63 \r
64 tBinary *Elf_Load64(int FD, Elf64_Ehdr *Header)\r
65 {\r
66         tBinary *ret;\r
67         Elf64_Phdr      phtab[Header->e_phnum];\r
68          int    nLoadSegments;\r
69          int    i, j;\r
70         \r
71         // Sanity check\r
72         if( Header->e_phoff == 0 )\r
73         {\r
74                 Log_Warning("ELF", "No program header, panic!");\r
75                 return NULL;\r
76         }\r
77         if( Header->e_shentsize != sizeof(Elf64_Shdr) ) {\r
78                 Log_Warning("ELF", "Header gives shentsize as %i, my type is %i",\r
79                         Header->e_shentsize, sizeof(Elf64_Shdr) );\r
80         }\r
81         if( Header->e_phentsize != sizeof(Elf64_Phdr) ) {\r
82                 Log_Warning("ELF", "Header gives phentsize as %i, my type is %i",\r
83                         Header->e_phentsize, sizeof(Elf64_Phdr) );\r
84         }\r
85 \r
86         LOG("Header = {");\r
87         LOG("  e_ident = %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",\r
88                 Header->e_ident[0], Header->e_ident[1], Header->e_ident[2], Header->e_ident[3],\r
89                 Header->e_ident[4], Header->e_ident[5], Header->e_ident[6], Header->e_ident[7],\r
90                 Header->e_ident[8], Header->e_ident[9], Header->e_ident[10], Header->e_ident[11],\r
91                 Header->e_ident[12], Header->e_ident[13], Header->e_ident[14], Header->e_ident[15]\r
92                 );\r
93         LOG("  e_type = %i", Header->e_type);\r
94         LOG("  e_machine = %i", Header->e_machine);\r
95         LOG("  e_version = %i", Header->e_version);\r
96         LOG("  e_entry   = 0x%llx", Header->e_entry);\r
97         LOG("  e_phoff   = 0x%llx", Header->e_phoff);\r
98         LOG("  e_shoff   = 0x%llx", Header->e_shoff);\r
99         LOG("  e_flags   = 0x%x", Header->e_flags);\r
100         LOG("  e_ehsize  = %i", Header->e_ehsize);\r
101         LOG("  e_phentsize = %i", Header->e_phentsize);\r
102         LOG("  e_phnum   = %i", Header->e_phnum);\r
103         LOG("  e_shentsize = %i", Header->e_shentsize);\r
104         LOG("  e_shnum   = %i", Header->e_shnum);\r
105         LOG("  e_shstrndx = %i", Header->e_shstrndx);\r
106         LOG("}");\r
107 \r
108         // Load Program Header table\r
109         VFS_Seek(FD, Header->e_phoff, SEEK_SET);\r
110         VFS_Read(FD, sizeof(Elf64_Phdr)*Header->e_phnum, phtab);\r
111 \r
112         // Count load segments\r
113         nLoadSegments = 0;\r
114         for( i = 0; i < Header->e_phnum; i ++ )\r
115         {\r
116                 if( phtab[i].p_type != PT_LOAD )        continue ;\r
117                 nLoadSegments ++;\r
118         }\r
119         \r
120         // Allocate Information Structure\r
121         ret = malloc( sizeof(tBinary) + sizeof(tBinarySection)*nLoadSegments );\r
122         // Fill Info Struct\r
123         ret->Entry = Header->e_entry;\r
124         ret->Base = -1;         // Set Base to maximum value\r
125         ret->NumSections = nLoadSegments;\r
126         ret->Interpreter = NULL;\r
127 \r
128         j = 0;  // LoadSections[] index\r
129         for( i = 0; i < Header->e_phnum; i ++ )\r
130         {\r
131                 LOG("phtab[%i] = {", i);\r
132                 LOG("  .p_type   = %i", phtab[i].p_type);\r
133                 LOG("  .p_flags  = 0x%x", phtab[i].p_flags);\r
134                 LOG("  .p_offset = 0x%llx", phtab[i].p_offset);\r
135                 LOG("  .p_vaddr  = 0x%llx", phtab[i].p_vaddr);\r
136                 LOG("  .p_paddr  = 0x%llx", phtab[i].p_paddr);\r
137                 LOG("  .p_filesz = 0x%llx", phtab[i].p_filesz);\r
138                 LOG("  .p_memsz  = 0x%llx", phtab[i].p_memsz);\r
139                 LOG("  .p_align  = 0x%llx", phtab[i].p_align);\r
140                 LOG("}");\r
141 \r
142                 // Get Interpreter Name\r
143                 if( phtab[i].p_type == PT_INTERP )\r
144                 {\r
145                         char *tmp;\r
146                         if(ret->Interpreter)    continue;\r
147                         tmp = malloc(phtab[i].p_filesz);\r
148                         VFS_Seek(FD, phtab[i].p_offset, 1);\r
149                         VFS_Read(FD, phtab[i].p_filesz, tmp);\r
150                         ret->Interpreter = Binary_RegInterp(tmp);\r
151                         LOG("Interpreter '%s'", tmp);\r
152                         free(tmp);\r
153                         continue;\r
154                 }\r
155                 \r
156                 if( phtab[i].p_type != PT_LOAD )        continue ;\r
157                 \r
158                 // Find the executable base\r
159                 if( phtab[i].p_vaddr < ret->Base )      ret->Base = phtab[i].p_vaddr;\r
160 \r
161                 ret->LoadSections[j].Offset = phtab[i].p_offset;\r
162                 ret->LoadSections[j].Virtual = phtab[i].p_vaddr;\r
163                 ret->LoadSections[j].FileSize = phtab[i].p_filesz;\r
164                 ret->LoadSections[j].MemSize = phtab[i].p_memsz;\r
165                 \r
166                 ret->LoadSections[j].Flags = 0;\r
167                 if( !(phtab[i].p_flags & PF_W) )\r
168                         ret->LoadSections[j].Flags |= BIN_SECTFLAG_RO;\r
169                 if( phtab[i].p_flags & PF_X )\r
170                         ret->LoadSections[j].Flags |= BIN_SECTFLAG_EXEC;\r
171                 j ++;\r
172         }\r
173 \r
174         return ret;\r
175 }\r
176 \r
177 tBinary *Elf_Load32(int FD, Elf32_Ehdr *Header)\r
178 {\r
179         tBinary *ret;\r
180         Elf32_Phdr      *phtab;\r
181          int    i, j;\r
182          int    iLoadCount;\r
183 \r
184         ENTER("xFD", FD);\r
185 \r
186         // Check architecture with current CPU\r
187         // - TODO: Support kernel level emulation\r
188         #if ARCH_IS_x86\r
189         if( Header->machine != EM_386 )\r
190         {\r
191                 Log_Warning("ELF", "Unknown architecure on ELF-32");\r
192                 LEAVE_RET('n');\r
193                 return NULL;\r
194         }\r
195         #endif\r
196 \r
197         // Check for a program header\r
198         if(Header->phoff == 0) {\r
199                 #if DEBUG_WARN\r
200                 Log_Warning("ELF", "File does not contain a program header (phoff == 0)");\r
201                 #endif\r
202                 LEAVE('n');\r
203                 return NULL;\r
204         }\r
205         \r
206         // Read Program Header Table\r
207         phtab = malloc( sizeof(Elf32_Phdr) * Header->phentcount );\r
208         if( !phtab ) {\r
209                 LEAVE('n');\r
210                 return NULL;\r
211         }\r
212         LOG("hdr.phoff = 0x%08x", Header->phoff);\r
213         VFS_Seek(FD, Header->phoff, SEEK_SET);\r
214         VFS_Read(FD, sizeof(Elf32_Phdr)*Header->phentcount, phtab);\r
215         \r
216         // Count Pages\r
217         iLoadCount = 0;\r
218         LOG("Header->phentcount = %i", Header->phentcount);\r
219         for( i = 0; i < Header->phentcount; i++ )\r
220         {\r
221                 // Ignore Non-LOAD types\r
222                 if(phtab[i].Type != PT_LOAD)\r
223                         continue;\r
224                 iLoadCount ++;\r
225                 LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}", i, phtab[i].VAddr, phtab[i].MemSize);\r
226         }\r
227         \r
228         LOG("iLoadCount = %i", iLoadCount);\r
229         \r
230         // Allocate Information Structure\r
231         ret = malloc( sizeof(tBinary) + sizeof(tBinarySection)*iLoadCount );\r
232         // Fill Info Struct\r
233         ret->Entry = Header->entrypoint;\r
234         ret->Base = -1;         // Set Base to maximum value\r
235         ret->NumSections = iLoadCount;\r
236         ret->Interpreter = NULL;\r
237         \r
238         // Load Pages\r
239         j = 0;\r
240         for( i = 0; i < Header->phentcount; i++ )\r
241         {\r
242                 //LOG("phtab[%i].Type = 0x%x", i, phtab[i].Type);\r
243                 LOG("phtab[%i] = {", i);\r
244                 LOG(" .Type = 0x%08x", phtab[i].Type);\r
245                 LOG(" .Offset = 0x%08x", phtab[i].Offset);\r
246                 LOG(" .VAddr = 0x%08x", phtab[i].VAddr);\r
247                 LOG(" .PAddr = 0x%08x", phtab[i].PAddr);\r
248                 LOG(" .FileSize = 0x%08x", phtab[i].FileSize);\r
249                 LOG(" .MemSize = 0x%08x", phtab[i].MemSize);\r
250                 LOG(" .Flags = 0x%08x", phtab[i].Flags);\r
251                 LOG(" .Align = 0x%08x", phtab[i].Align);\r
252                 LOG(" }");\r
253                 // Get Interpreter Name\r
254                 if( phtab[i].Type == PT_INTERP )\r
255                 {\r
256                         char *tmp;\r
257                         if(ret->Interpreter)    continue;\r
258                         tmp = malloc(phtab[i].FileSize);\r
259                         VFS_Seek(FD, phtab[i].Offset, 1);\r
260                         VFS_Read(FD, phtab[i].FileSize, tmp);\r
261                         ret->Interpreter = Binary_RegInterp(tmp);\r
262                         LOG("Interpreter '%s'", tmp);\r
263                         free(tmp);\r
264                         continue;\r
265                 }\r
266                 // Ignore non-LOAD types\r
267                 if(phtab[i].Type != PT_LOAD)    continue;\r
268                 \r
269                 // Find Base\r
270                 if(phtab[i].VAddr < ret->Base)  ret->Base = phtab[i].VAddr;\r
271                 \r
272                 LOG("phtab[%i] = {VAddr:0x%x,Offset:0x%x,FileSize:0x%x}",\r
273                         i, phtab[i].VAddr, phtab[i].Offset, phtab[i].FileSize);\r
274                 \r
275                 ret->LoadSections[j].Offset = phtab[i].Offset;\r
276                 ret->LoadSections[j].FileSize = phtab[i].FileSize;\r
277                 ret->LoadSections[j].Virtual = phtab[i].VAddr;\r
278                 ret->LoadSections[j].MemSize = phtab[i].MemSize;\r
279                 ret->LoadSections[j].Flags = 0;\r
280                 if( !(phtab[i].Flags & PF_W) )\r
281                         ret->LoadSections[j].Flags |= BIN_SECTFLAG_RO;\r
282                 if( phtab[i].Flags & PF_X )\r
283                         ret->LoadSections[j].Flags |= BIN_SECTFLAG_EXEC;\r
284                 j ++;\r
285         }\r
286         \r
287         // Clean Up\r
288         free(phtab);\r
289         // Return\r
290         LEAVE('p', ret);\r
291         return ret;\r
292 }\r
293 \r
294 int Elf_Relocate(void *Base)\r
295 {\r
296         return ElfRelocate(Base, (char**){NULL}, "") != NULL;\r
297 }\r
298 int Elf_GetSymbol(void *Base, const char *Name, Uint *ret)\r
299 {\r
300         return ElfGetSymbol(Base, Name, (void**)ret, NULL);\r
301 }\r
302 \r

UCC git Repository :: git.ucc.asn.au