re-order some parts of the code so that the msg and rect are only allocated once.
[AROS.git] / bootstrap / elfloader.c
blob3a2a381e3cb1138e48f7c32f690ef9946e7de7fb
1 /*
2 Copyright (C) 2006-2019 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 #undef __pure2
21 #undef __deprecated
23 #include <dos/elf.h>
24 #include <libraries/debug.h>
26 #include <elfloader.h>
27 #include <runtime.h>
29 #define D(x)
30 #define DREL(x)
31 #define DSYM(x)
33 /* Use own definitions because we may be compiled as 32-bit code but build structures for 64-bit code */
34 struct ELF_ModuleInfo_t
36 elf_uintptr_t Next;
37 elf_uintptr_t Name;
38 unsigned short Type;
39 unsigned short Pad0; /* On i386 we have different alignment, so do explicit padding */
40 #ifdef ELF_64BIT
41 unsigned int Pad1;
42 #endif
43 elf_uintptr_t eh;
44 elf_uintptr_t sh;
47 /* Our own definition of struct KernelBSS, to avoid excessive castings */
48 struct KernelBSS_t
50 elf_uintptr_t addr;
51 elf_uintptr_t len;
54 static elf_uintptr_t SysBase_ptr = 0;
57 * Test for correct ELF header here
59 static char *check_header(struct elfheader *eh)
61 if (eh->ident[0] != 0x7f || eh->ident[1] != 'E' ||
62 eh->ident[2] != 'L' || eh->ident[3] != 'F')
63 return "Not an ELF file";
65 if (eh->type != ET_REL || eh->machine != AROS_ELF_MACHINE)
66 return "Object of the wrong type or architecture";
68 /* No error */
69 return NULL;
73 * Get the memory for chunk and load it
75 static void *load_hunk(void *file, struct sheader *sh, void *addr, struct KernelBSS_t **bss_tracker)
77 uintptr_t align;
79 /* empty chunk? Who cares :) */
80 if (!sh->size)
81 return addr;
83 D(kprintf("[ELF Loader] Chunk (%ld bytes, align=%ld (%p) @ ", sh->size, sh->addralign, (void *)(uintptr_t)sh->addralign));
84 align = sh->addralign - 1;
85 addr = (char *)(((uintptr_t)addr + align) & ~align);
87 D(kprintf("%p\n", addr));
88 sh->addr = (elf_ptr_t)(uintptr_t)addr;
90 /* copy block of memory from ELF file if it exists */
91 if (sh->type != SHT_NOBITS)
93 if (read_block(file, sh->offset, (void *)(uintptr_t)sh->addr, sh->size))
94 return NULL;
96 else
98 memset(addr, 0, sh->size);
100 (*bss_tracker)->addr = (uintptr_t)addr;
101 (*bss_tracker)->len = sh->size;
102 (*bss_tracker)++;
105 return addr + sh->size;
108 static void *copy_data(void *src, void *addr, uintptr_t len)
110 memcpy(addr, src, len);
111 return addr + len;
114 /* Perform relocations of given section */
115 static int relocate(struct elfheader *eh, struct sheader *sh, long shrel_idx, elf_uintptr_t DefSysBase)
117 struct sheader *shrel = &sh[shrel_idx];
118 struct sheader *shsymtab = &sh[shrel->link];
119 struct sheader *toreloc = &sh[shrel->info];
121 struct symbol *symtab = (struct symbol *)(uintptr_t)shsymtab->addr;
122 struct relo *rel = (struct relo *)(uintptr_t)shrel->addr;
123 /* Early cast to uintptr_t omits __udivdi3 call in x86-64 native bootstrap */
124 unsigned int numrel = (uintptr_t)shrel->size / (uintptr_t)shrel->entsize;
125 unsigned int i;
127 struct symbol *SysBase_sym = NULL;
130 * Ignore relocs if the target section has no allocation. that can happen
131 * eg. with a .debug PROGBITS and a .rel.debug section
133 if (!(toreloc->flags & SHF_ALLOC))
134 return 1;
136 DREL(kprintf("[ELF Loader] performing %d relocations\n", numrel));
138 for (i=0; i<numrel; i++, rel++)
140 struct symbol *sym = &symtab[ELF_R_SYM(rel->info)];
141 uintptr_t *p = (void *)(uintptr_t)toreloc->addr + rel->offset;
142 const char *name = (const char *)(uintptr_t)sh[shsymtab->link].addr + sym->name;
143 elf_uintptr_t s;
145 #ifdef __arm__
147 * R_ARM_V4BX are actually special marks for the linker.
148 * They even never have a target (shindex == SHN_UNDEF),
149 * so we simply ignore them before doing any checks.
151 if (ELF_R_TYPE(rel->info) == R_ARM_V4BX)
152 continue;
153 #endif
155 switch (sym->shindex)
157 case SHN_UNDEF:
158 if (Strcmp(name, "SysBase") == 0) {
159 if (!SysBase_ptr)
161 SysBase_ptr = DefSysBase;
162 D(kprintf("[ELF Loader] SysBase symbol set to default %p\n", (void *)(uintptr_t)SysBase_ptr));
165 s = SysBase_ptr;
166 } else {
167 kprintf("[ELF Loader] Undefined symbol '%s'\n", name);
168 return 0;
170 break;
172 case SHN_COMMON:
173 kprintf("[ELF Loader] COMMON symbol '%s'\n", name);
174 return 0;
176 case SHN_ABS:
177 if (SysBase_sym == NULL)
179 if (Strcmp(name, "SysBase") == 0)
181 DREL(kprintf("[ELF Loader] got SysBase\n"));
182 SysBase_sym = sym;
186 if (SysBase_sym == sym)
188 if (!SysBase_ptr)
190 SysBase_ptr = DefSysBase;
191 D(kprintf("[ELF Loader] SysBase symbol set to default %p\n", (void *)(uintptr_t)SysBase_ptr));
194 s = SysBase_ptr;
196 else
197 s = sym->value;
198 break;
200 default:
201 s = (uintptr_t)sh[sym->shindex].addr + sym->value;
203 if (!SysBase_ptr)
206 * The first global data symbol named SysBase becomes global SysBase.
207 * The idea behind: the first module (kernel.resource) contains global
208 * SysBase variable and all other modules are linked to it.
210 if (sym->info == ELF_S_INFO(STB_GLOBAL, STT_OBJECT))
212 if (Strcmp(name, "SysBase") == 0)
214 SysBase_ptr = s;
215 D(kprintf("[ELF Loader] SysBase symbol set to %p\n", (void *)(uintptr_t)SysBase_ptr));
221 DREL(kprintf("[ELF Loader] Relocating symbol %s, type ", sym->name ? name : "<unknown>"));
222 switch (ELF_R_TYPE(rel->info))
224 #ifdef ELF_64BIT
225 case R_X86_64_64: /* 64bit direct/absolute */
226 *(uint64_t *)p = s + rel->addend;
227 break;
229 case R_X86_64_PLT32:
230 case R_X86_64_PC32: /* PC relative 32 bit signed */
231 *(uint32_t *)p = s + rel->addend - (uintptr_t) p;
232 break;
234 case R_X86_64_32:
235 *(uint32_t *)p = (uint64_t)s + (uint64_t)rel->addend;
236 break;
238 case R_X86_64_32S:
239 *(int32_t *)p = (int64_t)s + (int64_t)rel->addend;
240 break;
242 case R_X86_64_NONE: /* No reloc */
243 break;
244 #else
245 #ifdef __i386__
246 case R_386_32: /* 32bit absolute */
247 DREL(kprintf("R_386_32"));
248 *p += s;
249 break;
251 case R_386_PC32: /* 32bit PC relative */
252 DREL(kprintf("R_386_PC32"));
253 *p += (s - (uintptr_t)p);
254 break;
256 case R_386_NONE:
257 DREL(kprintf("R_386_NONE"));
258 break;
259 #endif
260 #endif
261 #ifdef __mc68000__
262 case R_68K_32:
263 *p = s + rel->addend;
264 break;
266 case R_68K_PC32:
267 *p = s + rel->addend - (uint32_t)p;
268 break;
270 case R_68k_NONE:
271 break;
272 #endif
273 #if defined(__ppc__) || defined(__powerpc__)
274 case R_PPC_ADDR32:
275 *p = s + rel->addend;
276 break;
278 case R_PPC_ADDR16_LO:
280 unsigned short *c = (unsigned short *) p;
281 *c = (s + rel->addend) & 0xffff;
283 break;
285 case R_PPC_ADDR16_HA:
287 unsigned short *c = (unsigned short *) p;
288 uint32_t temp = s + rel->addend;
289 *c = temp >> 16;
290 if ((temp & 0x8000) != 0)
291 (*c)++;
293 break;
295 case R_PPC_REL16_LO:
297 unsigned short *c = (unsigned short *) p;
298 *c = (s + rel->addend - (uint32_t)p) & 0xffff;
300 break;
302 case R_PPC_REL16_HA:
304 unsigned short *c = (unsigned short *) p;
305 uint32_t temp = s + rel->addend - (uint32_t)p;
306 *c = temp >> 16;
307 if ((temp & 0x8000) != 0)
308 (*c)++;
310 break;
312 case R_PPC_REL24:
313 *p &= ~0x3fffffc;
314 *p |= (s + rel->addend - (uint32_t)p) & 0x3fffffc;
315 break;
317 case R_PPC_REL32:
318 *p = s + rel->addend - (uint32_t)p;
319 break;
321 case R_PPC_NONE:
322 break;
323 #endif
324 #ifdef __arm__
325 case R_ARM_CALL:
326 case R_ARM_JUMP24:
327 case R_ARM_PC24:
328 case R_ARM_PREL31:
330 /* On ARM the 24 bit offset is shifted by 2 to the right */
331 signed long offset = (*p & 0x00ffffff) << 2;
332 /* If highest bit set, make offset negative */
333 if (offset & 0x02000000)
334 offset -= 0x04000000;
336 offset += s - (uint32_t)p;
338 offset >>= 2;
339 *p &= 0xff000000;
340 *p |= offset & 0x00ffffff;
342 break;
344 case R_ARM_MOVW_ABS_NC:
345 case R_ARM_MOVT_ABS:
347 signed long offset = *p;
348 offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff);
349 offset = (offset ^ 0x8000) - 0x8000;
351 offset += s;
353 if (ELF_R_TYPE(rel->info) == R_ARM_MOVT_ABS)
354 offset >>= 16;
356 *p &= 0xfff0f000;
357 *p |= ((offset & 0xf000) << 4) | (offset & 0x0fff);
359 break;
361 case R_ARM_ABS32:
362 *p += s;
363 break;
365 case R_ARM_NONE:
366 break;
367 #endif
368 default:
369 kprintf("[ELF Loader] Unknown relocation #%d type %ld\n", i, (long)ELF_R_TYPE(rel->info));
370 return 0;
372 DREL(kprintf(" -> %p\n", *p));
374 return 1;
377 int GetKernelSize(struct ELFNode *FirstELF, unsigned long *ro_size, unsigned long *rw_size, unsigned long *bss_size)
379 struct ELFNode *n;
380 unsigned long ksize = 0;
381 unsigned long rwsize = 0;
382 unsigned long bsize = sizeof(struct KernelBSS_t);
383 unsigned short i;
385 kprintf("[ELF Loader] Calculating kickstart size...\n");
387 for (n = FirstELF; n; n = n->Next)
389 void *file;
390 char *errstr = NULL;
391 unsigned int err;
393 D(kprintf("[ELF Loader] Checking file %s\n", n->Name));
395 file = open_file(n, &err);
396 if (err)
398 DisplayError("Failed to open file %s!\n", n->Name);
399 return 0;
402 /* Check the header of ELF file */
403 n->eh = load_block(file, 0, sizeof(struct elfheader), &err);
404 if (err)
406 errstr = "Failed to read file header";
408 else
410 errstr = check_header(n->eh);
411 if (!errstr)
413 n->sh = load_block(file, n->eh->shoff, n->eh->shnum * n->eh->shentsize, &err);
414 if (err)
416 errstr = "Failed to read section header(s)";
421 close_file(file);
422 if (errstr)
424 DisplayError("%s: %s\n", n->Name, errstr);
425 return 0;
429 * Debug data for the module includes:
430 * - Module descriptor (struct ELF_ModuleInfo_t)
431 * - ELF file header
432 * - ELF section header
433 * - File name
434 * - One empty pointer for alignment
436 ksize += (sizeof(struct ELF_ModuleInfo_t) + sizeof(struct elfheader) + n->eh->shnum * n->eh->shentsize +
437 strlen(n->Name) + sizeof(void *));
439 /* Go through all sections and calculate kernel size */
440 for(i = 0; i < n->eh->shnum; i++)
442 /* Ignore sections with zero lengths */
443 if (!n->sh[i].size)
444 continue;
447 * We will load:
448 * - Actual code and data (allocated sections)
449 * - String tables (for debug data)
450 * - Symbol tables (for debug data)
452 if ((n->sh[i].flags & SHF_ALLOC) || (n->sh[i].type == SHT_STRTAB) || (n->sh[i].type == SHT_SYMTAB))
454 /* Add maximum space for alignment */
455 unsigned long s = n->sh[i].size + n->sh[i].addralign - 1;
457 if (n->sh[i].flags & SHF_WRITE)
458 rwsize += s;
459 else
460 ksize += s;
462 if (n->sh[i].type == SHT_NOBITS)
463 bsize += sizeof(struct KernelBSS_t);
468 *ro_size = ksize;
469 *rw_size = rwsize;
471 if (bss_size)
472 *bss_size = bsize;
474 kprintf("[ELF Loader] Code %lu bytes, data %lu bytes, BSS array %lu bytes\n", ksize, rwsize, bsize);
476 return 1;
480 * This function loads the listed modules.
481 * It expects that ELF and section header pointers in the list are already set up by GetKernelSize().
483 * (elf_ptr_t)(uintptr_t) double-casting is needed because in some cases elf_ptr_t is an UQUAD,
484 * while in most cases it's a pointer (see dos/elf.h).
486 int LoadKernel(struct ELFNode *FirstELF, void *ptr_ro, void *ptr_rw, char *tracker_p, uintptr_t DefSysBase,
487 void **kick_end, kernel_entry_fun_t *kernel_entry, struct ELF_ModuleInfo **kernel_debug)
489 struct ELFNode *n;
490 unsigned int i;
491 unsigned char need_entry = 1;
492 struct ELF_ModuleInfo_t *mod;
493 struct ELF_ModuleInfo_t *prev_mod = NULL;
494 struct KernelBSS_t *tracker = (struct KernelBSS_t *)tracker_p;
496 kprintf("[ELF Loader] Loading kickstart...\n");
498 for (n = FirstELF; n; n = n->Next)
500 void *file;
501 unsigned int err;
503 kprintf("[ELF Loader] Code %p, Data %p, Module %s...\n", ptr_ro, ptr_rw, n->Name);
505 file = open_file(n, &err);
506 if (err)
508 DisplayError("Failed to open file %s!\n", n->Name);
509 return 0;
512 /* Iterate over the section header in order to load some hunks */
513 for (i=0; i < n->eh->shnum; i++)
515 struct sheader *sh = n->sh;
517 D(kprintf("[ELF Loader] Section %u... ", i));
519 if ((sh[i].flags & SHF_ALLOC) || (sh[i].type == SHT_STRTAB) || (sh[i].type == SHT_SYMTAB))
521 /* Does the section require memory allcation? */
522 D(kprintf("Allocated section\n"));
524 if (sh[i].flags & SHF_WRITE)
526 ptr_rw = load_hunk(file, &sh[i], (void *)ptr_rw, &tracker);
527 if (!ptr_rw)
529 DisplayError("%s: Error loading hunk %u!\n", n->Name, i);
530 return 0;
533 else
535 ptr_ro = load_hunk(file, &sh[i], (void *)ptr_ro, &tracker);
536 if (!ptr_ro)
538 DisplayError("%s: Error loading hunk %u!\n", n->Name, i);
539 return 0;
543 /* Remember address of the first code section, this is our entry point */
544 if ((sh[i].flags & SHF_EXECINSTR) && need_entry)
546 *kernel_entry = (void *)(uintptr_t)sh[i].addr;
547 need_entry = 0;
550 D(else kprintf("Ignored\n");)
552 D(kprintf("[ELF Loader] Section address: %p, size: %lu\n", sh[i].addr, sh[i].size));
555 /* For every loaded section perform relocations */
556 D(kprintf("[ELF Loader] Relocating...\n"));
557 for (i=0; i < n->eh->shnum; i++)
559 struct sheader *sh = n->sh;
561 if ((sh[i].type == AROS_ELF_REL) && sh[sh[i].info].addr)
563 sh[i].addr = (elf_ptr_t)(uintptr_t)load_block(file, sh[i].offset, sh[i].size, &err);
564 if (err)
566 DisplayError("%s: Failed to load relocation section %u\n", n->Name, i);
567 return 0;
570 if (!relocate(n->eh, sh, i, (uintptr_t)DefSysBase))
572 DisplayError("%s: Relocation error in section %u!\n", n->Name, i);
573 return 0;
576 free_block((void *)(uintptr_t)sh[i].addr);
577 sh[i].addr = (elf_ptr_t)0;
581 close_file(file);
583 D(kprintf("[ELF Loader] Adding module debug information...\n"));
585 /* Align our pointer */
586 ptr_ro = (void *)(((uintptr_t)ptr_ro + sizeof(void *)) & ~(sizeof(void *) - 1));
588 /* Allocate module descriptor */
589 mod = ptr_ro;
590 ptr_ro += sizeof(struct ELF_ModuleInfo_t);
591 mod->Next = 0;
592 mod->Type = DEBUG_ELF;
594 /* Copy ELF header */
595 mod->eh = (uintptr_t)ptr_ro;
596 ptr_ro = copy_data(n->eh, ptr_ro, sizeof(struct elfheader));
598 /* Copy section header */
599 mod->sh = (uintptr_t)ptr_ro;
600 ptr_ro = copy_data(n->sh, ptr_ro, n->eh->shnum * n->eh->shentsize);
602 /* Copy module name */
603 mod->Name = (uintptr_t)ptr_ro;
604 ptr_ro = copy_data(n->Name, ptr_ro, strlen(n->Name) + 1);
606 /* Link the module descriptor with previous one */
607 if (prev_mod)
608 prev_mod->Next = (uintptr_t)mod;
609 else
610 *kernel_debug = (struct ELF_ModuleInfo *)mod;
611 prev_mod = mod;
613 free_block(n->sh);
614 free_block(n->eh);
617 /* Terminate the array of BSS sections */
618 tracker->addr = 0;
619 tracker->len = 0;
621 /* Return end of kickstart read-only area if requested */
622 if (kick_end)
623 *kick_end = ptr_ro;
625 return 1;