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

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