sm502.hidd: Depend on pci.hidd's includes
[AROS.git] / bootstrap / elfloader.c
blob93ca32fb3ad67560573b1dc38459db70885723aa
1 /*
2 Copyright (C) 2006-2011 The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: ELF loader extracted from our internal_load_seg_elf in dos.library.
6 Lang: English
7 */
9 #include <inttypes.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
14 /* Define this wrapper here, before loading AROS headers,
15 * so that the defines in <aros/system.h> do not
16 * confuse GCC's built-in substitutions for strcmp().
18 static inline int Strcmp(const char *a, const char *b) { return strcmp(a, b); }
20 #include <dos/elf.h>
21 #include <libraries/debug.h>
23 #include <elfloader.h>
24 #include <runtime.h>
26 #define D(x)
27 #define DREL(x)
28 #define DSYM(x)
30 /* Use own definitions because we may be compiled as 32-bit code but build structures for 64-bit code */
31 struct ELF_ModuleInfo_t
33 elf_uintptr_t Next;
34 elf_uintptr_t Name;
35 unsigned short Type;
36 unsigned short Pad0; /* On i386 we have different alignment, so do explicit padding */
37 #ifdef ELF_64BIT
38 unsigned int Pad1;
39 #endif
40 elf_uintptr_t eh;
41 elf_uintptr_t sh;
44 /* Our own definition of struct KernelBSS, to avoid excessive castings */
45 struct KernelBSS_t
47 elf_uintptr_t addr;
48 elf_uintptr_t len;
51 static elf_uintptr_t SysBase_ptr = 0;
54 * Test for correct ELF header here
56 static char *check_header(struct elfheader *eh)
58 if (eh->ident[0] != 0x7f || eh->ident[1] != 'E' ||
59 eh->ident[2] != 'L' || eh->ident[3] != 'F')
60 return "Not a ELF file";
62 if (eh->type != ET_REL || eh->machine != AROS_ELF_MACHINE)
63 return "Wrong object type or wrong architecture";
65 /* No error */
66 return NULL;
70 * Get the memory for chunk and load it
72 static void *load_hunk(void *file, struct sheader *sh, void *addr, struct KernelBSS_t **bss_tracker)
74 uintptr_t align;
76 /* empty chunk? Who cares :) */
77 if (!sh->size)
78 return addr;
80 D(kprintf("[ELF Loader] Chunk (%ld bytes, align=%ld (%p) @ ", sh->size, sh->addralign, (void *)sh->addralign));
81 align = sh->addralign - 1;
82 addr = (char *)(((uintptr_t)addr + align) & ~align);
84 D(kprintf("%p\n", addr));
85 sh->addr = (elf_ptr_t)(uintptr_t)addr;
87 /* copy block of memory from ELF file if it exists */
88 if (sh->type != SHT_NOBITS)
90 if (read_block(file, sh->offset, (void *)(uintptr_t)sh->addr, sh->size))
91 return NULL;
93 else
95 memset(addr, 0, sh->size);
97 (*bss_tracker)->addr = (uintptr_t)addr;
98 (*bss_tracker)->len = sh->size;
99 (*bss_tracker)++;
102 return addr + sh->size;
105 static void *copy_data(void *src, void *addr, uintptr_t len)
107 memcpy(addr, src, len);
108 return addr + len;
111 /* Perform relocations of given section */
112 static int relocate(struct elfheader *eh, struct sheader *sh, long shrel_idx, elf_uintptr_t DefSysBase)
114 struct sheader *shrel = &sh[shrel_idx];
115 struct sheader *shsymtab = &sh[SHINDEX(shrel->link)];
116 struct sheader *toreloc = &sh[SHINDEX(shrel->info)];
118 struct symbol *symtab = (struct symbol *)(uintptr_t)shsymtab->addr;
119 struct relo *rel = (struct relo *)(uintptr_t)shrel->addr;
120 /* Early cast to uintptr_t omits __udivdi3 call in x86-64 native bootstrap */
121 unsigned int numrel = (uintptr_t)shrel->size / (uintptr_t)shrel->entsize;
122 unsigned int i;
124 struct symbol *SysBase_sym = NULL;
127 * Ignore relocs if the target section has no allocation. that can happen
128 * eg. with a .debug PROGBITS and a .rel.debug section
130 if (!(toreloc->flags & SHF_ALLOC))
131 return 1;
133 DREL(kprintf("[ELF Loader] performing %d relocations\n", numrel));
135 for (i=0; i<numrel; i++, rel++)
137 struct symbol *sym = &symtab[ELF_R_SYM(rel->info)];
138 uintptr_t *p = (void *)(uintptr_t)toreloc->addr + rel->offset;
139 const char *name = (const char *)(uintptr_t)sh[shsymtab->link].addr + sym->name;
140 elf_uintptr_t s;
142 #ifdef __arm__
144 * R_ARM_V4BX are actually special marks for the linker.
145 * They even never have a target (shindex == SHN_UNDEF),
146 * so we simply ignore them before doing any checks.
148 if (ELF_R_TYPE(rel->info) == R_ARM_V4BX)
149 continue;
150 #endif
152 switch (sym->shindex)
154 case SHN_UNDEF:
155 DREL(kprintf("[ELF Loader] Undefined symbol '%s'\n", name));
156 return 0;
158 case SHN_COMMON:
159 DREL(kprintf("[ELF Loader] COMMON symbol '%s'\n", name));
160 return 0;
162 case SHN_ABS:
163 if (SysBase_sym == NULL)
165 if (Strcmp(name, "SysBase") == 0)
167 DREL(kprintf("[ELF Loader] got SysBase\n"));
168 SysBase_sym = sym;
172 if (SysBase_sym == sym)
174 if (!SysBase_ptr)
176 SysBase_ptr = DefSysBase;
177 D(kprintf("[ELF Loader] SysBase pointer set to default %p\n", (void *)SysBase_ptr));
180 s = SysBase_ptr;
182 else
183 s = sym->value;
184 break;
186 default:
187 s = (uintptr_t)sh[sym->shindex].addr + sym->value;
189 if (!SysBase_ptr)
192 * The first global data symbol named SysBase becomes global SysBase.
193 * The idea behind: the first module (kernel.resource) contains global
194 * SysBase variable and all other modules are linked to it.
196 if (sym->info == ELF_S_INFO(STB_GLOBAL, STT_OBJECT))
198 if (Strcmp(name, "SysBase") == 0)
200 SysBase_ptr = s;
201 D(kprintf("[ELF Loader] SysBase pointer set to %p\n", (void *)SysBase_ptr));
207 DREL(kprintf("[ELF Loader] Relocating symbol %s type ", sym->name ? name : "<unknown>"));
208 switch (ELF_R_TYPE(rel->info))
210 #ifdef ELF_64BIT
211 case R_X86_64_64: /* 64bit direct/absolute */
212 *(uint64_t *)p = s + rel->addend;
213 break;
215 case R_X86_64_PC32: /* PC relative 32 bit signed */
216 *(uint32_t *)p = s + rel->addend - (uintptr_t) p;
217 break;
219 case R_X86_64_32:
220 *(uint32_t *)p = (uint64_t)s + (uint64_t)rel->addend;
221 break;
223 case R_X86_64_32S:
224 *(int32_t *)p = (int64_t)s + (int64_t)rel->addend;
225 break;
227 case R_X86_64_NONE: /* No reloc */
228 break;
229 #else
230 #ifdef __i386__
231 case R_386_32: /* 32bit absolute */
232 DREL(kprintf("R_386_32"));
233 *p += s;
234 break;
236 case R_386_PC32: /* 32bit PC relative */
237 DREL(kprintf("R_386_PC32"));
238 *p += (s - (uintptr_t)p);
239 break;
241 case R_386_NONE:
242 DREL(kprintf("R_386_NONE"));
243 break;
244 #endif
245 #endif
246 #ifdef __mc68000__
247 case R_68K_32:
248 *p = s + rel->addend;
249 break;
251 case R_68K_PC32:
252 *p = s + rel->addend - (uint32_t)p;
253 break;
255 case R_68k_NONE:
256 break;
257 #endif
258 #if defined(__ppc__) || defined(__powerpc__)
259 case R_PPC_ADDR32:
260 *p = s + rel->addend;
261 break;
263 case R_PPC_ADDR16_LO:
265 unsigned short *c = (unsigned short *) p;
266 *c = (s + rel->addend) & 0xffff;
268 break;
270 case R_PPC_ADDR16_HA:
272 unsigned short *c = (unsigned short *) p;
273 uint32_t temp = s + rel->addend;
274 *c = temp >> 16;
275 if ((temp & 0x8000) != 0)
276 (*c)++;
278 break;
280 case R_PPC_REL16_LO:
282 unsigned short *c = (unsigned short *) p;
283 *c = (s + rel->addend - (uint32_t)p) & 0xffff;
285 break;
287 case R_PPC_REL16_HA:
289 unsigned short *c = (unsigned short *) p;
290 uint32_t temp = s + rel->addend - (uint32_t)p;
291 *c = temp >> 16;
292 if ((temp & 0x8000) != 0)
293 (*c)++;
295 break;
297 case R_PPC_REL24:
298 *p &= ~0x3fffffc;
299 *p |= (s + rel->addend - (uint32_t)p) & 0x3fffffc;
300 break;
302 case R_PPC_REL32:
303 *p = s + rel->addend - (uint32_t)p;
304 break;
306 case R_PPC_NONE:
307 break;
308 #endif
309 #ifdef __arm__
310 case R_ARM_CALL:
311 case R_ARM_JUMP24:
312 case R_ARM_PC24:
313 case R_ARM_PREL31:
315 /* On ARM the 24 bit offset is shifted by 2 to the right */
316 signed long offset = (*p & 0x00ffffff) << 2;
317 /* If highest bit set, make offset negative */
318 if (offset & 0x02000000)
319 offset -= 0x04000000;
321 offset += s - (uint32_t)p;
323 offset >>= 2;
324 *p &= 0xff000000;
325 *p |= offset & 0x00ffffff;
327 break;
329 case R_ARM_MOVW_ABS_NC:
330 case R_ARM_MOVT_ABS:
332 signed long offset = *p;
333 offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff);
334 offset = (offset ^ 0x8000) - 0x8000;
336 offset += s;
338 if (ELF_R_TYPE(rel->info) == R_ARM_MOVT_ABS)
339 offset >>= 16;
341 *p &= 0xfff0f000;
342 *p |= ((offset & 0xf000) << 4) | (offset & 0x0fff);
344 break;
346 case R_ARM_ABS32:
347 *p += s;
348 break;
350 case R_ARM_NONE:
351 break;
352 #endif
353 default:
354 kprintf("[ELF Loader] Unrecognized relocation type %d %ld\n", i, (long)ELF_R_TYPE(rel->info));
355 return 0;
357 DREL(kprintf(" -> %p\n", *p));
359 return 1;
362 int GetKernelSize(struct ELFNode *FirstELF, unsigned long *ro_size, unsigned long *rw_size, unsigned long *bss_size)
364 struct ELFNode *n;
365 unsigned long ksize = 0;
366 unsigned long rwsize = 0;
367 unsigned long bsize = sizeof(struct KernelBSS_t);
368 unsigned short i;
370 kprintf("[ELF Loader] Calculating kickstart size...\n");
372 for (n = FirstELF; n; n = n->Next)
374 void *file;
375 char *errstr = NULL;
376 unsigned int err;
378 D(kprintf("[ELF Loader] Checking file %s\n", n->Name));
380 file = open_file(n, &err);
381 if (err)
383 DisplayError("Failed to open file %s!\n", n->Name);
384 return 0;
387 /* Check the header of ELF file */
388 n->eh = load_block(file, 0, sizeof(struct elfheader), &err);
389 if (err)
391 errstr = "Failed to read file header";
393 else
395 errstr = check_header(n->eh);
396 if (!errstr)
398 n->sh = load_block(file, n->eh->shoff, n->eh->shnum * n->eh->shentsize, &err);
399 if (err)
401 errstr = "Failed to read section headers";
406 close_file(file);
407 if (errstr)
409 DisplayError("%s: %s\n", n->Name, errstr);
410 return 0;
414 * Debug data for the module includes:
415 * - Module descriptor (struct ELF_ModuleInfo_t)
416 * - ELF file header
417 * - ELF section header
418 * - File name
419 * - One empty pointer for alignment
421 ksize += (sizeof(struct ELF_ModuleInfo_t) + sizeof(struct elfheader) + n->eh->shnum * n->eh->shentsize +
422 strlen(n->Name) + sizeof(void *));
424 /* Go through all sections and calculate kernel size */
425 for(i = 0; i < n->eh->shnum; i++)
427 /* Ignore sections with zero lengths */
428 if (!n->sh[i].size)
429 continue;
432 * We will load:
433 * - Actual code and data (allocated sections)
434 * - String tables (for debug data)
435 * - Symbol tables (for debug data)
437 if ((n->sh[i].flags & SHF_ALLOC) || (n->sh[i].type == SHT_STRTAB) || (n->sh[i].type == SHT_SYMTAB))
439 /* Add maximum space for alignment */
440 unsigned long s = n->sh[i].size + n->sh[i].addralign - 1;
442 if (n->sh[i].flags & SHF_WRITE)
443 rwsize += s;
444 else
445 ksize += s;
447 if (n->sh[i].type == SHT_NOBITS)
448 bsize += sizeof(struct KernelBSS_t);
453 *ro_size = ksize;
454 *rw_size = rwsize;
456 if (bss_size)
457 *bss_size = bsize;
459 kprintf("[ELF Loader] Code %lu bytes, data %lu bytes, BSS array %lu bytes\n", ksize, rwsize, bsize);
461 return 1;
465 * This function loads the listed modules.
466 * It expects that ELF and section header pointers in the list are already set up by GetKernelSize().
468 * (elf_ptr_t)(uintptr_t) double-casting is needed because in some cases elf_ptr_t is an UQUAD,
469 * while in most cases it's a pointer (see dos/elf.h).
471 int LoadKernel(struct ELFNode *FirstELF, void *ptr_ro, void *ptr_rw, void *tracker, uintptr_t DefSysBase,
472 void **kick_end, kernel_entry_fun_t *kernel_entry, struct ELF_ModuleInfo **kernel_debug)
474 struct ELFNode *n;
475 unsigned int i;
476 unsigned char need_entry = 1;
477 struct ELF_ModuleInfo_t *mod;
478 struct ELF_ModuleInfo_t *prev_mod = NULL;
480 kprintf("[ELF Loader] Loading kickstart...\n");
482 for (n = FirstELF; n; n = n->Next)
484 void *file;
485 unsigned int err;
487 kprintf("[ELF Loader] Code %p, Data %p, Module %s...\n", ptr_ro, ptr_rw, n->Name);
489 file = open_file(n, &err);
490 if (err)
492 DisplayError("Failed to open file %s!\n", n->Name);
493 return 0;
496 /* Iterate over the section header in order to load some hunks */
497 for (i=0; i < n->eh->shnum; i++)
499 struct sheader *sh = n->sh;
501 D(kprintf("[ELF Loader] Section %u... ", i));
503 if ((sh[i].flags & SHF_ALLOC) || (sh[i].type == SHT_STRTAB) || (sh[i].type == SHT_SYMTAB))
505 /* Does the section require memory allcation? */
506 D(kprintf("Allocated section\n"));
508 if (sh[i].flags & SHF_WRITE)
510 ptr_rw = load_hunk(file, &sh[i], (void *)ptr_rw, (struct KernelBSS_t **)&tracker);
511 if (!ptr_rw)
513 DisplayError("%s: Error loading hunk %u!\n", n->Name, i);
514 return 0;
517 else
519 ptr_ro = load_hunk(file, &sh[i], (void *)ptr_ro, (struct KernelBSS_t **)&tracker);
520 if (!ptr_ro)
522 DisplayError("%s: Error loading hunk %u!\n", n->Name, i);
523 return 0;
527 /* Remember address of the first code section, this is our entry point */
528 if ((sh[i].flags & SHF_EXECINSTR) && need_entry)
530 *kernel_entry = (void *)(uintptr_t)sh[i].addr;
531 need_entry = 0;
534 D(else kprintf("Ignored\n");)
536 D(kprintf("[ELF Loader] Section address: %p, size: %lu\n", sh[i].addr, sh[i].size));
539 /* For every loaded section perform relocations */
540 D(kprintf("[ELF Loader] Relocating...\n"));
541 for (i=0; i < n->eh->shnum; i++)
543 struct sheader *sh = n->sh;
545 if ((sh[i].type == AROS_ELF_REL) && sh[sh[i].info].addr)
547 sh[i].addr = (elf_ptr_t)(uintptr_t)load_block(file, sh[i].offset, sh[i].size, &err);
548 if (err)
550 DisplayError("%s: Failed to load relocation section %u\n", n->Name, i);
551 return 0;
554 if (!relocate(n->eh, sh, i, (uintptr_t)DefSysBase))
556 DisplayError("%s: Relocation error in section %u!\n", n->Name, i);
557 return 0;
560 free_block((void *)(uintptr_t)sh[i].addr);
561 sh[i].addr = (elf_ptr_t)0;
565 close_file(file);
567 D(kprintf("[ELF Loader] Adding module debug information...\n"));
569 /* Align our pointer */
570 ptr_ro = (void *)(((uintptr_t)ptr_ro + sizeof(void *)) & ~(sizeof(void *) - 1));
572 /* Allocate module descriptor */
573 mod = ptr_ro;
574 ptr_ro += sizeof(struct ELF_ModuleInfo_t);
575 mod->Next = 0;
576 mod->Type = DEBUG_ELF;
578 /* Copy ELF header */
579 mod->eh = (uintptr_t)ptr_ro;
580 ptr_ro = copy_data(n->eh, ptr_ro, sizeof(struct elfheader));
582 /* Copy section header */
583 mod->sh = (uintptr_t)ptr_ro;
584 ptr_ro = copy_data(n->sh, ptr_ro, n->eh->shnum * n->eh->shentsize);
586 /* Copy module name */
587 mod->Name = (uintptr_t)ptr_ro;
588 ptr_ro = copy_data(n->Name, ptr_ro, strlen(n->Name) + 1);
590 /* Link the module descriptor with previous one */
591 if (prev_mod)
592 prev_mod->Next = (uintptr_t)mod;
593 else
594 *kernel_debug = (struct ELF_ModuleInfo *)mod;
595 prev_mod = mod;
597 free_block(n->sh);
598 free_block(n->eh);
601 /* Terminate the array of BSS sections */
602 ((struct KernelBSS_t *)tracker)->addr = 0;
603 ((struct KernelBSS_t *)tracker)->len = 0;
605 /* Return end of kickstart read-only area if requested */
606 if (kick_end)
607 *kick_end = ptr_ro;
609 return 1;