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

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