2 Copyright (C) 2006-2011 The AROS Development Team. All rights reserved.
5 Desc: ELF loader extracted from our internal_load_seg_elf in dos.library.
15 #include <libraries/debug.h>
17 #include <elfloader.h>
24 /* Use own definitions because we may be compiled as 32-bit code but build structures for 64-bit code */
25 struct ELF_ModuleInfo_t
30 unsigned short Pad0
; /* On i386 we have different alignment, so do explicit padding */
38 /* Our own definition of struct KernelBSS, to avoid excessive castings */
45 static elf_uintptr_t SysBase_ptr
= 0;
48 * Test for correct ELF header here
50 static char *check_header(struct elfheader
*eh
)
52 if (eh
->ident
[0] != 0x7f || eh
->ident
[1] != 'E' ||
53 eh
->ident
[2] != 'L' || eh
->ident
[3] != 'F')
54 return "Not a ELF file";
56 if (eh
->type
!= ET_REL
|| eh
->machine
!= AROS_ELF_MACHINE
)
57 return "Wrong object type or wrong architecture";
64 * Get the memory for chunk and load it
66 static void *load_hunk(void *file
, struct sheader
*sh
, void *addr
, struct KernelBSS_t
**bss_tracker
)
70 /* empty chunk? Who cares :) */
74 D(kprintf("[ELF Loader] Chunk (%ld bytes, align=%ld (%p) @ ", sh
->size
, sh
->addralign
, (void *)sh
->addralign
));
75 align
= sh
->addralign
- 1;
76 addr
= (char *)(((uintptr_t)addr
+ align
) & ~align
);
78 D(kprintf("%p\n", addr
));
79 sh
->addr
= (elf_ptr_t
)(uintptr_t)addr
;
81 /* copy block of memory from ELF file if it exists */
82 if (sh
->type
!= SHT_NOBITS
)
84 if (read_block(file
, sh
->offset
, (void *)(uintptr_t)sh
->addr
, sh
->size
))
89 memset(addr
, 0, sh
->size
);
91 (*bss_tracker
)->addr
= (uintptr_t)addr
;
92 (*bss_tracker
)->len
= sh
->size
;
96 return addr
+ sh
->size
;
99 static void *copy_data(void *src
, void *addr
, uintptr_t len
)
101 memcpy(addr
, src
, len
);
105 /* Perform relocations of given section */
106 static int relocate(struct elfheader
*eh
, struct sheader
*sh
, long shrel_idx
, elf_uintptr_t DefSysBase
)
108 struct sheader
*shrel
= &sh
[shrel_idx
];
109 struct sheader
*shsymtab
= &sh
[SHINDEX(shrel
->link
)];
110 struct sheader
*toreloc
= &sh
[SHINDEX(shrel
->info
)];
112 struct symbol
*symtab
= (struct symbol
*)(uintptr_t)shsymtab
->addr
;
113 struct relo
*rel
= (struct relo
*)(uintptr_t)shrel
->addr
;
114 /* Early cast to uintptr_t omits __udivdi3 call in x86-64 native bootstrap */
115 unsigned int numrel
= (uintptr_t)shrel
->size
/ (uintptr_t)shrel
->entsize
;
118 struct symbol
*SysBase_sym
= NULL
;
121 * Ignore relocs if the target section has no allocation. that can happen
122 * eg. with a .debug PROGBITS and a .rel.debug section
124 if (!(toreloc
->flags
& SHF_ALLOC
))
127 DREL(kprintf("[ELF Loader] performing %d relocations\n", numrel
));
129 for (i
=0; i
<numrel
; i
++, rel
++)
131 struct symbol
*sym
= &symtab
[ELF_R_SYM(rel
->info
)];
132 uintptr_t *p
= (void *)(uintptr_t)toreloc
->addr
+ rel
->offset
;
133 const char *name
= (const char *)(uintptr_t)sh
[shsymtab
->link
].addr
+ sym
->name
;
138 * R_ARM_V4BX are actually special marks for the linker.
139 * They even never have a target (shindex == SHN_UNDEF),
140 * so we simply ignore them before doing any checks.
142 if (ELF_R_TYPE(rel
->info
) == R_ARM_V4BX
)
146 switch (sym
->shindex
)
149 DREL(kprintf("[ELF Loader] Undefined symbol '%s'\n", name
));
153 DREL(kprintf("[ELF Loader] COMMON symbol '%s'\n", name
));
157 if (SysBase_sym
== NULL
)
159 if (strncmp(name
, "SysBase", 8) == 0)
161 DREL(kprintf("[ELF Loader] got SysBase\n"));
166 if (SysBase_sym
== sym
)
170 SysBase_ptr
= DefSysBase
;
171 D(kprintf("[ELF Loader] SysBase pointer set to default %p\n", (void *)SysBase_ptr
));
181 s
= (uintptr_t)sh
[sym
->shindex
].addr
+ sym
->value
;
186 * The first global data symbol named SysBase becomes global SysBase.
187 * The idea behind: the first module (kernel.resource) contains global
188 * SysBase variable and all other modules are linked to it.
190 if (sym
->info
== ELF_S_INFO(STB_GLOBAL
, STT_OBJECT
))
192 if (strcmp(name
, "SysBase") == 0)
195 D(kprintf("[ELF Loader] SysBase pointer set to %p\n", (void *)SysBase_ptr
));
201 DREL(kprintf("[ELF Loader] Relocating symbol %s type ", sym
->name
? name
: "<unknown>"));
202 switch (ELF_R_TYPE(rel
->info
))
205 case R_X86_64_64
: /* 64bit direct/absolute */
206 *(uint64_t *)p
= s
+ rel
->addend
;
209 case R_X86_64_PC32
: /* PC relative 32 bit signed */
210 *(uint32_t *)p
= s
+ rel
->addend
- (uintptr_t) p
;
214 *(uint32_t *)p
= (uint64_t)s
+ (uint64_t)rel
->addend
;
218 *(int32_t *)p
= (int64_t)s
+ (int64_t)rel
->addend
;
221 case R_X86_64_NONE
: /* No reloc */
225 case R_386_32
: /* 32bit absolute */
226 DREL(kprintf("R_386_32"));
230 case R_386_PC32
: /* 32bit PC relative */
231 DREL(kprintf("R_386_PC32"));
232 *p
+= (s
- (uintptr_t)p
);
236 DREL(kprintf("R_386_NONE"));
242 *p
= s
+ rel
->addend
;
246 *p
= s
+ rel
->addend
- (uint32_t)p
;
252 #if defined(__ppc__) || defined(__powerpc__)
254 *p
= s
+ rel
->addend
;
257 case R_PPC_ADDR16_LO
:
259 unsigned short *c
= (unsigned short *) p
;
260 *c
= (s
+ rel
->addend
) & 0xffff;
264 case R_PPC_ADDR16_HA
:
266 unsigned short *c
= (unsigned short *) p
;
267 uint32_t temp
= s
+ rel
->addend
;
269 if ((temp
& 0x8000) != 0)
276 unsigned short *c
= (unsigned short *) p
;
277 *c
= (s
+ rel
->addend
- (uint32_t)p
) & 0xffff;
283 unsigned short *c
= (unsigned short *) p
;
284 uint32_t temp
= s
+ rel
->addend
- (uint32_t)p
;
286 if ((temp
& 0x8000) != 0)
293 *p
|= (s
+ rel
->addend
- (uint32_t)p
) & 0x3fffffc;
297 *p
= s
+ rel
->addend
- (uint32_t)p
;
308 /* On ARM the 24 bit offset is shifted by 2 to the right */
309 signed long offset
= (*p
& 0x00ffffff) << 2;
310 /* If highest bit set, make offset negative */
311 if (offset
& 0x02000000)
312 offset
-= 0x04000000;
314 offset
+= s
- (uint32_t)p
;
318 *p
|= offset
& 0x00ffffff;
322 case R_ARM_MOVW_ABS_NC
:
325 signed long offset
= *p
;
326 offset
= ((offset
& 0xf0000) >> 4) | (offset
& 0xfff);
327 offset
= (offset
^ 0x8000) - 0x8000;
331 if (ELF_R_TYPE(rel
->info
) == R_ARM_MOVT_ABS
)
335 *p
|= ((offset
& 0xf000) << 4) | (offset
& 0x0fff);
347 kprintf("[ELF Loader] Unrecognized relocation type %d %ld\n", i
, (long)ELF_R_TYPE(rel
->info
));
350 DREL(kprintf(" -> %p\n", *p
));
355 int GetKernelSize(struct ELFNode
*FirstELF
, unsigned long *ro_size
, unsigned long *rw_size
, unsigned long *bss_size
)
358 unsigned long ksize
= 0;
359 unsigned long rwsize
= 0;
360 unsigned long bsize
= sizeof(struct KernelBSS_t
);
363 kprintf("[ELF Loader] Calculating kickstart size...\n");
365 for (n
= FirstELF
; n
; n
= n
->Next
)
371 D(kprintf("[ELF Loader] Checking file %s\n", n
->Name
));
373 file
= open_file(n
, &err
);
376 DisplayError("Failed to open file %s!\n", n
->Name
);
380 /* Check the header of ELF file */
381 n
->eh
= load_block(file
, 0, sizeof(struct elfheader
), &err
);
384 errstr
= "Failed to read file header";
388 errstr
= check_header(n
->eh
);
391 n
->sh
= load_block(file
, n
->eh
->shoff
, n
->eh
->shnum
* n
->eh
->shentsize
, &err
);
394 errstr
= "Failed to read section headers";
402 DisplayError("%s: %s\n", n
->Name
, errstr
);
407 * Debug data for the module includes:
408 * - Module descriptor (struct ELF_ModuleInfo_t)
410 * - ELF section header
412 * - One empty pointer for alignment
414 ksize
+= (sizeof(struct ELF_ModuleInfo_t
) + sizeof(struct elfheader
) + n
->eh
->shnum
* n
->eh
->shentsize
+
415 strlen(n
->Name
) + sizeof(void *));
417 /* Go through all sections and calculate kernel size */
418 for(i
= 0; i
< n
->eh
->shnum
; i
++)
420 /* Ignore sections with zero lengths */
426 * - Actual code and data (allocated sections)
427 * - String tables (for debug data)
428 * - Symbol tables (for debug data)
430 if ((n
->sh
[i
].flags
& SHF_ALLOC
) || (n
->sh
[i
].type
== SHT_STRTAB
) || (n
->sh
[i
].type
== SHT_SYMTAB
))
432 /* Add maximum space for alignment */
433 unsigned long s
= n
->sh
[i
].size
+ n
->sh
[i
].addralign
- 1;
435 if (n
->sh
[i
].flags
& SHF_WRITE
)
440 if (n
->sh
[i
].type
== SHT_NOBITS
)
441 bsize
+= sizeof(struct KernelBSS_t
);
452 kprintf("[ELF Loader] Code %lu bytes, data %lu bytes, BSS array %lu bytes\n", ksize
, rwsize
, bsize
);
458 * This function loads the listed modules.
459 * It expects that ELF and section header pointers in the list are already set up by GetKernelSize().
461 * (elf_ptr_t)(uintptr_t) double-casting is needed because in some cases elf_ptr_t is an UQUAD,
462 * while in most cases it's a pointer (see dos/elf.h).
464 int LoadKernel(struct ELFNode
*FirstELF
, void *ptr_ro
, void *ptr_rw
, void *tracker
, uintptr_t DefSysBase
,
465 void **kick_end
, kernel_entry_fun_t
*kernel_entry
, struct ELF_ModuleInfo
**kernel_debug
)
469 unsigned char need_entry
= 1;
470 struct ELF_ModuleInfo_t
*mod
;
471 struct ELF_ModuleInfo_t
*prev_mod
= NULL
;
473 kprintf("[ELF Loader] Loading kickstart...\n");
475 for (n
= FirstELF
; n
; n
= n
->Next
)
480 kprintf("[ELF Loader] Code %p, Data %p, Module %s...\n", ptr_ro
, ptr_rw
, n
->Name
);
482 file
= open_file(n
, &err
);
485 DisplayError("Failed to open file %s!\n", n
->Name
);
489 /* Iterate over the section header in order to load some hunks */
490 for (i
=0; i
< n
->eh
->shnum
; i
++)
492 struct sheader
*sh
= n
->sh
;
494 D(kprintf("[ELF Loader] Section %u... ", i
));
496 if ((sh
[i
].flags
& SHF_ALLOC
) || (sh
[i
].type
== SHT_STRTAB
) || (sh
[i
].type
== SHT_SYMTAB
))
498 /* Does the section require memory allcation? */
499 D(kprintf("Allocated section\n"));
501 if (sh
[i
].flags
& SHF_WRITE
)
503 ptr_rw
= load_hunk(file
, &sh
[i
], (void *)ptr_rw
, (struct KernelBSS_t
**)&tracker
);
506 DisplayError("%s: Error loading hunk %u!\n", n
->Name
, i
);
512 ptr_ro
= load_hunk(file
, &sh
[i
], (void *)ptr_ro
, (struct KernelBSS_t
**)&tracker
);
515 DisplayError("%s: Error loading hunk %u!\n", n
->Name
, i
);
520 /* Remember address of the first code section, this is our entry point */
521 if ((sh
[i
].flags
& SHF_EXECINSTR
) && need_entry
)
523 *kernel_entry
= (void *)(uintptr_t)sh
[i
].addr
;
527 D(else kprintf("Ignored\n");)
529 D(kprintf("[ELF Loader] Section address: %p, size: %lu\n", sh
[i
].addr
, sh
[i
].size
));
532 /* For every loaded section perform relocations */
533 D(kprintf("[ELF Loader] Relocating...\n"));
534 for (i
=0; i
< n
->eh
->shnum
; i
++)
536 struct sheader
*sh
= n
->sh
;
538 if ((sh
[i
].type
== AROS_ELF_REL
) && sh
[sh
[i
].info
].addr
)
540 sh
[i
].addr
= (elf_ptr_t
)(uintptr_t)load_block(file
, sh
[i
].offset
, sh
[i
].size
, &err
);
543 DisplayError("%s: Failed to load relocation section %u\n", n
->Name
, i
);
547 if (!relocate(n
->eh
, sh
, i
, (uintptr_t)DefSysBase
))
549 DisplayError("%s: Relocation error in section %u!\n", n
->Name
, i
);
553 free_block((void *)(uintptr_t)sh
[i
].addr
);
554 sh
[i
].addr
= (elf_ptr_t
)0;
560 D(kprintf("[ELF Loader] Adding module debug information...\n"));
562 /* Align our pointer */
563 ptr_ro
= (void *)(((uintptr_t)ptr_ro
+ sizeof(void *)) & ~(sizeof(void *) - 1));
565 /* Allocate module descriptor */
567 ptr_ro
+= sizeof(struct ELF_ModuleInfo_t
);
569 mod
->Type
= DEBUG_ELF
;
571 /* Copy ELF header */
572 mod
->eh
= (uintptr_t)ptr_ro
;
573 ptr_ro
= copy_data(n
->eh
, ptr_ro
, sizeof(struct elfheader
));
575 /* Copy section header */
576 mod
->sh
= (uintptr_t)ptr_ro
;
577 ptr_ro
= copy_data(n
->sh
, ptr_ro
, n
->eh
->shnum
* n
->eh
->shentsize
);
579 /* Copy module name */
580 mod
->Name
= (uintptr_t)ptr_ro
;
581 ptr_ro
= copy_data(n
->Name
, ptr_ro
, strlen(n
->Name
) + 1);
583 /* Link the module descriptor with previous one */
585 prev_mod
->Next
= (uintptr_t)mod
;
587 *kernel_debug
= (struct ELF_ModuleInfo
*)mod
;
594 /* Terminate the array of BSS sections */
595 ((struct KernelBSS_t
*)tracker
)->addr
= 0;
596 ((struct KernelBSS_t
*)tracker
)->len
= 0;
598 /* Return end of kickstart read-only area if requested */