genmodule: All libraries (including exec) export libreq symbols
[AROS.git] / rom / dos / internalloadseg_elf.c
blob2828fbec4703446ba778cbed5516d715bed79bb2
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Code to dynamically load ELF executables
6 Lang: english
8 1997/12/13: Changed filename to internalloadseg_elf.c
9 Original file was created by digulla.
12 #define DATTR(x)
14 #include <aros/asmcall.h>
15 #include <aros/debug.h>
16 #include <aros/macros.h>
17 #include <exec/memory.h>
18 #include <dos/elf.h>
19 #include <dos/dosasl.h>
20 #include <libraries/debug.h>
21 #include <resources/processor.h>
22 #include <proto/dos.h>
23 #include <proto/arossupport.h>
24 #include <proto/debug.h>
25 #include <proto/exec.h>
27 #include <string.h>
28 #include <stddef.h>
30 #include "internalloadseg.h"
31 #include "dos_intern.h"
32 #include "include/loadseg.h"
34 struct hunk
36 ULONG size;
37 BPTR next;
38 char data[0];
39 } __attribute__((packed));
41 #define BPTR2HUNK(bptr) ((struct hunk *)((void *)bptr - offsetof(struct hunk, next)))
42 #define HUNK2BPTR(hunk) MKBADDR(&hunk->next)
44 static int elf_read_block
46 BPTR file,
47 ULONG offset,
48 APTR buffer,
49 ULONG size,
50 SIPTR *funcarray,
51 struct DosLibrary *DOSBase
54 if (ilsSeek(file, offset, OFFSET_BEGINNING) < 0)
55 return 1;
57 return read_block(file, buffer, size, funcarray, DOSBase);
60 static void *load_block
62 BPTR file,
63 ULONG offset,
64 ULONG size,
65 SIPTR *funcarray,
66 struct DosLibrary *DOSBase
69 D(bug("[ELF Loader] Load Block\n"));
70 D(bug("[ELF Loader] (size=%d)\n",size));
71 D(bug("[ELF Loader] (funcarray=0x%x)\n",funcarray));
72 D(bug("[ELF Loader] (funcarray[1]=0x%x)\n",funcarray[1]));
73 void *block = ilsAllocMem(size, MEMF_ANY);
74 if (block)
76 if (!elf_read_block(file, offset, block, size, funcarray, DOSBase))
77 return block;
79 ilsFreeMem(block, size);
81 else
82 SetIoErr(ERROR_NO_FREE_STORE);
84 return NULL;
87 static ULONG read_shnum(BPTR file, struct elfheader *eh, SIPTR *funcarray, struct DosLibrary *DOSBase)
89 ULONG shnum = eh->shnum;
91 /* the ELF header only uses 16 bits to store the count of section headers,
92 * so it can't handle more than 65535 headers. if the count is 0, and an
93 * offset is defined, then the real count can be found in the first
94 * section header (which always exists).
96 * similarly, if the string table index is SHN_XINDEX, then the actual
97 * index is found in the first section header also.
99 * see the System V ABI 2001-04-24 draft for more details.
101 if (eh->shnum == 0)
103 struct sheader sh;
105 if (eh->shoff == 0) {
106 D(bug("[ELF Loader] No section header\n"));
107 SetIoErr(ERROR_NOT_EXECUTABLE);
108 return 0;
111 if (elf_read_block(file, eh->shoff, &sh, sizeof(sh), funcarray, DOSBase))
112 return 0;
114 /* wider section header count is in the size field */
115 shnum = sh.size;
117 /* sanity, if they're still invalid then this isn't elf */
118 if (shnum == 0) {
119 D(bug("[ELF Loader] Empty section header\n"));
120 SetIoErr(ERROR_NOT_EXECUTABLE);
124 return shnum;
127 static int load_header(BPTR file, struct elfheader *eh, SIPTR *funcarray, struct DosLibrary *DOSBase)
129 if (elf_read_block(file, 0, eh, sizeof(struct elfheader), funcarray, DOSBase))
130 return 0;
132 if (eh->ident[0] != 0x7f || eh->ident[1] != 'E' ||
133 eh->ident[2] != 'L' || eh->ident[3] != 'F') {
134 D(bug("[ELF Loader] Not an ELF object\n"));
135 SetIoErr(ERROR_NOT_EXECUTABLE);
136 return 0;
138 D(bug("[ELF Loader] ELF object\n"));
140 /* WANT_CLASS should be defined for your target */
141 if (eh->ident[EI_CLASS] != AROS_ELF_CLASS ||
142 eh->ident[EI_VERSION] != EV_CURRENT ||
143 eh->type != ET_REL ||
144 eh->ident[EI_DATA] != AROS_ELF_DATA ||
145 eh->machine != AROS_ELF_MACHINE)
147 D(bug("[ELF Loader] Object is of wrong type\n"));
148 D(bug("[ELF Loader] EI_CLASS is %d - should be %d\n", eh->ident[EI_CLASS] , AROS_ELF_CLASS ));
149 D(bug("[ELF Loader] EI_VERSION is %d - should be %d\n", eh->ident[EI_VERSION], EV_CURRENT ));
150 D(bug("[ELF Loader] type is %d - should be %d\n", eh->type , ET_REL ));
151 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA] , AROS_ELF_DATA ));
152 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine , AROS_ELF_MACHINE));
154 SetIoErr(ERROR_NOT_EXECUTABLE);
155 return 0;
158 return 1;
161 static int load_hunk
163 BPTR file,
164 BPTR **next_hunk_ptr,
165 struct sheader *sh,
166 CONST_STRPTR strtab,
167 SIPTR *funcarray,
168 BOOL do_align,
169 struct DosLibrary *DOSBase
172 struct hunk *hunk;
173 ULONG hunk_size;
174 ULONG memflags = 0;
176 if (!sh->size)
177 return 1;
179 /* The size of the hunk is the size of the section, plus
180 the size of the hunk structure, plus the size of the alignment (if necessary)*/
181 hunk_size = sh->size + sizeof(struct hunk);
183 if (do_align)
185 hunk_size += sh->addralign;
187 /* Also create space for a trampoline, if necessary */
188 if (sh->flags & SHF_EXECINSTR)
189 hunk_size += sizeof(struct FullJumpVec);
192 if (strtab) {
193 CONST_STRPTR nameext;
195 nameext = strrchr(strtab + sh->name, '.');
196 if (nameext) {
197 if (strcmp(nameext, ".MEMF_CHIP")==0) {
198 memflags |= MEMF_CHIP;
199 } else if (strcmp(nameext, ".MEMF_LOCAL")==0) {
200 memflags |= MEMF_LOCAL;
201 } else if (strcmp(nameext, ".MEMF_KICK")==0) {
202 memflags |= MEMF_KICK;
203 } else if (strcmp(nameext, ".MEMF_FAST")==0) {
204 memflags |= MEMF_FAST;
205 } else if (strcmp(nameext, ".MEMF_PUBLIC")==0) {
206 memflags |= MEMF_PUBLIC;
211 hunk = ilsAllocMem(hunk_size, memflags | MEMF_PUBLIC | (sh->type == SHT_NOBITS ? MEMF_CLEAR : 0));
212 if (hunk)
214 hunk->next = 0;
215 hunk->size = hunk_size;
217 /* In case we are required to honour alignment, and If this section contains
218 executable code, create a trampoline to its beginning, so that even if the
219 alignment requirements make the actual code go much after the end of the
220 hunk structure, the code can still be reached in the usual way. */
221 if (do_align)
223 if (sh->flags & SHF_EXECINSTR)
225 sh->addr = (char *)AROS_ROUNDUP2
227 (IPTR)hunk->data + sizeof(struct FullJumpVec), sh->addralign
229 __AROS_SET_FULLJMP((struct FullJumpVec *)hunk->data, sh->addr);
231 else
232 sh->addr = (char *)AROS_ROUNDUP2((IPTR)hunk->data, sh->addralign);
234 else
235 sh->addr = hunk->data;
237 /* Link the previous one with the new one */
238 BPTR2HUNK(*next_hunk_ptr)->next = HUNK2BPTR(hunk);
240 D(bug("[dos] hunk @ %p, size=%08x, addr @ %p\n", hunk, hunk->size, sh->addr));
242 /* Update the pointer to the previous one, which is now the current one */
243 *next_hunk_ptr = &hunk->next;
245 if (sh->type != SHT_NOBITS)
246 return !elf_read_block(file, sh->offset, sh->addr, sh->size, funcarray, DOSBase);
248 return 1;
252 SetIoErr(ERROR_NO_FREE_STORE);
254 return 0;
257 static int relocate
259 struct elfheader *eh,
260 struct sheader *sh,
261 ULONG shrel_idx,
262 struct sheader *symtab_shndx,
263 struct DosLibrary *DOSBase
266 struct sheader *shrel = &sh[shrel_idx];
267 struct sheader *shsymtab = &sh[SHINDEX(shrel->link)];
268 struct sheader *toreloc = &sh[SHINDEX(shrel->info)];
270 struct symbol *symtab = (struct symbol *)shsymtab->addr;
271 struct relo *rel = (struct relo *)shrel->addr;
274 * Ignore relocs if the target section has no allocation. that can happen
275 * eg. with a .debug PROGBITS and a .rel.debug section
277 if (!(toreloc->flags & SHF_ALLOC))
278 return 1;
280 ULONG numrel = shrel->size / shrel->entsize;
281 ULONG i;
283 #ifndef NO_SYSBASE_REMAP
284 struct symbol *SysBase_sym = NULL;
285 #endif
287 for (i=0; i<numrel; i++, rel++)
289 struct symbol *sym;
290 ULONG *p;
291 IPTR s;
292 ULONG shindex;
294 #ifdef __arm__
296 * R_ARM_V4BX are actually special marks for the linker.
297 * They even never have a target (shindex == SHN_UNDEF),
298 * so we simply ignore them before doing any checks.
300 if (ELF_R_TYPE(rel->info) == R_ARM_V4BX)
301 continue;
302 #endif
304 sym = &symtab[ELF_R_SYM(rel->info)];
305 p = toreloc->addr + rel->offset;
307 if (sym->shindex != SHN_XINDEX)
308 shindex = sym->shindex;
310 else {
311 if (symtab_shndx == NULL) {
312 D(bug("[ELF Loader] got symbol with shndx 0xfff, but there's no symtab shndx table\n"));
313 SetIoErr(ERROR_BAD_HUNK);
314 return 0;
316 shindex = ((ULONG *)symtab_shndx->addr)[ELF_R_SYM(rel->info)];
319 DB2(bug("[ELF Loader] Processing symbol %s\n", sh[SHINDEX(shsymtab->link)].addr + sym->name));
321 switch (shindex)
324 case SHN_COMMON:
325 D(bug("[ELF Loader] COMMON symbol '%s'\n",
326 (STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name));
327 SetIoErr(ERROR_BAD_HUNK);
329 return 0;
331 case SHN_ABS:
332 #ifdef NO_SYSBASE_REMAP
333 s = sym->value;
334 #else
335 if (SysBase_sym == NULL)
337 if (strncmp((STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name, "SysBase", 8) == 0)
339 SysBase_sym = sym;
340 goto SysBase_yes;
342 else
343 goto SysBase_no;
345 else
346 if (SysBase_sym == sym)
348 SysBase_yes: s = (IPTR)&SysBase;
350 else
351 SysBase_no: s = sym->value;
352 #endif
353 break;
355 case SHN_UNDEF:
356 if (ELF_R_TYPE(rel->info) != 0) {
357 D(bug("[ELF Loader] Undefined symbol '%s'\n",
358 (STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name));
359 SetIoErr(ERROR_BAD_HUNK);
360 return 0;
362 /* fall through */
364 default:
365 s = (IPTR)sh[SHINDEX(shindex)].addr + sym->value;
368 switch (ELF_R_TYPE(rel->info))
370 #if defined(__i386__)
372 case R_386_32: /* 32bit absolute */
373 *p += s;
374 break;
376 case R_386_PC32: /* 32bit PC relative */
377 *p += s - (ULONG)p;
378 break;
380 case R_386_NONE:
381 break;
383 #elif defined(__x86_64__)
384 case R_X86_64_64: /* 64bit direct/absolute */
385 *(UQUAD *)p = s + rel->addend;
386 break;
388 case R_X86_64_PC32: /* PC relative 32 bit signed */
389 *(ULONG *)p = s + rel->addend - (IPTR) p;
390 break;
392 case R_X86_64_32:
393 *(ULONG *)p = (UQUAD)s + (UQUAD)rel->addend;
394 break;
396 case R_X86_64_32S:
397 *(LONG *)p = (QUAD)s + (QUAD)rel->addend;
398 break;
400 case R_X86_64_NONE: /* No reloc */
401 break;
403 #elif defined(__mc68000__)
405 case R_68K_32:
406 *p = s + rel->addend;
407 break;
409 case R_68K_16:
410 *(UWORD *)p = s + rel->addend;
411 break;
413 case R_68K_8:
414 *(UBYTE *)p = s + rel->addend;
415 break;
417 case R_68K_PC32:
418 *p = s + rel->addend - (ULONG)p;
419 break;
421 case R_68K_PC16:
422 *(UWORD *)p = s + rel->addend - (ULONG)p;
423 break;
425 case R_68K_PC8:
426 *(UBYTE *)p = s + rel->addend - (ULONG)p;
427 break;
429 case R_68K_NONE:
430 break;
432 #elif defined(__ppc__) || defined(__powerpc__)
434 case R_PPC_ADDR32:
435 *p = s + rel->addend;
436 break;
438 case R_PPC_ADDR16_LO:
440 unsigned short *c = (unsigned short *) p;
441 *c = (s + rel->addend) & 0xffff;
443 break;
445 case R_PPC_ADDR16_HA:
447 unsigned short *c = (unsigned short *) p;
448 ULONG temp = s + rel->addend;
449 *c = temp >> 16;
450 if ((temp & 0x8000) != 0)
451 (*c)++;
453 break;
455 case R_PPC_REL16_LO:
457 unsigned short *c = (unsigned short *) p;
458 *c = (s + rel->addend - (ULONG) p) & 0xffff;
460 break;
462 case R_PPC_REL16_HA:
464 unsigned short *c = (unsigned short *) p;
465 ULONG temp = s + rel->addend - (ULONG) p;
466 *c = temp >> 16;
467 if ((temp & 0x8000) != 0)
468 (*c)++;
470 break;
472 case R_PPC_REL24:
473 *p &= ~0x3fffffc;
474 *p |= (s + rel->addend - (ULONG) p) & 0x3fffffc;
475 break;
477 case R_PPC_REL32:
478 *p = s + rel->addend - (ULONG) p;
479 break;
481 case R_PPC_NONE:
482 break;
484 #elif defined(__arm__)
485 case R_ARM_CALL:
486 case R_ARM_JUMP24:
487 case R_ARM_PC24:
488 case R_ARM_PREL31:
490 /* On ARM the 24 bit offset is shifted by 2 to the right */
491 signed long offset = (*p & 0x00ffffff) << 2;
492 /* If highest bit set, make offset negative */
493 if (offset & 0x02000000)
494 offset -= 0x04000000;
496 if (offset >= 0x02000000 ||
497 offset <= -0x02000000)
499 bug("[ELF Loader] Relocation type %d %d out of range!\n", i, ELF_R_TYPE(rel->info));
500 SetIoErr(ERROR_BAD_HUNK);
501 return 0;
503 offset += s - (ULONG)p;
505 offset >>= 2;
506 *p &= 0xff000000;
507 *p |= offset & 0x00ffffff;
509 break;
511 case R_ARM_THM_CALL:
512 case R_ARM_THM_JUMP24:
514 ULONG upper,lower,sign,j1,j2;
515 LONG offset;
517 upper = *((UWORD *)p);
518 lower = *((UWORD *)p+1);
520 sign = (upper >> 10) & 1;
521 j1 = (lower >> 13) & 1;
522 j2 = (lower >> 11) & 1;
524 offset = (sign << 24) | ((~(j1 ^ sign) & 1) << 23) |
525 ((~(j2 ^ sign) & 1) << 22) |
526 ((upper & 0x03ff) << 12) |
527 ((lower & 0x07ff) << 1);
529 if (offset & 0x01000000)
530 offset -= 0x02000000;
532 if (offset >= 0x01000000 ||
533 offset <= -0x01000000)
535 bug("[ELF Loader] Relocation type %d %d out of range!\n", i, ELF_R_TYPE(rel->info));
536 SetIoErr(ERROR_BAD_HUNK);
537 return 0;
539 offset += s - (ULONG)p;
541 sign = (offset >> 24) & 1;
542 j1 = sign ^ (~(offset >> 23) & 1);
543 j2 = sign ^ (~(offset >> 22) & 1);
545 *(UWORD *)p = (UWORD)((upper & 0xf800) | (sign << 10) |
546 ((offset >> 12) & 0x03ff));
547 *((UWORD *)p + 1) = (UWORD)((lower & 0xd000) |
548 (j1 << 13) | (j2 << 11) | ((offset >> 1) & 0x07ff));
551 break;
553 case R_ARM_THM_MOVW_ABS_NC:
554 case R_ARM_THM_MOVT_ABS:
556 ULONG upper,lower;
557 LONG offset;
559 upper = *((UWORD *)p);
560 lower = *((UWORD *)p+1);
562 offset = ((upper & 0x000f) << 12) |
563 ((upper & 0x0400) << 1) |
564 ((lower & 0x7000) >> 4) |
565 (lower & 0x00ff);
567 offset = (offset ^ 0x8000) - 0x8000;
569 offset += s;
571 if (ELF_R_TYPE(rel->info) == R_ARM_THM_MOVT_ABS)
572 offset >>= 16;
574 *(UWORD *)p = (UWORD)((upper & 0xfbf0) |
575 ((offset & 0xf000) >> 12) |
576 ((offset & 0x0800) >> 1));
577 *((UWORD *)p + 1) = (UWORD)((lower & 0x8f00) |
578 ((offset & 0x0700)<< 4) |
579 (offset & 0x00ff));
581 break;
583 case R_ARM_MOVW_ABS_NC:
584 case R_ARM_MOVT_ABS:
586 signed long offset = *p;
587 offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff);
588 offset = (offset ^ 0x8000) - 0x8000;
590 offset += s;
592 if (ELF_R_TYPE(rel->info) == R_ARM_MOVT_ABS)
593 offset >>= 16;
595 *p &= 0xfff0f000;
596 *p |= ((offset & 0xf000) << 4) | (offset & 0x0fff);
598 break;
600 case R_ARM_ABS32:
601 *p += s;
602 break;
604 case R_ARM_NONE:
605 break;
607 #else
608 # error Your architecture is not supported
609 #endif
611 default:
612 D(bug("[ELF Loader] Unrecognized relocation type %d %d\n", i, ELF_R_TYPE(rel->info)));
613 SetIoErr(ERROR_BAD_HUNK);
614 return 0;
618 return 1;
621 #ifdef __arm__
624 * On ARM < v6 all LONG accesses must be LONG-aligned
625 * TODO: This is useful and can be moved to some public include file.
627 #if (__ARM_ARCH__ > 5)
629 #define READLONG_UNALIGNED(src) src
631 #else
633 static inline ULONG readlong_unaligned(ULONG *src)
635 ULONG res, tmp;
637 asm volatile(
638 "ldrb %0, [%2, #0]\n\t"
639 "ldrb %1, [%2, #1]\n\t"
640 "orr %0, %0, %1, lsl #8\n\t"
641 "ldrb %1, [%2, #2]\n\t"
642 "orr %0, %0, %1, lsl #16\n\t"
643 "ldrb %1, [%2, #3]\n\t"
644 "orr %0, %0, %1, lsl #24"
645 :"=&r"(res), "=&r"(tmp) : "r"(src)
648 return res;
651 #define READLONG_UNALIGNED(src) readlong_unaligned(&src);
652 #endif
655 * This code parses special .ARM.Attributes section and
656 * extracts system requirements from it. Things like float ABI,
657 * minimum CPU and FPU version are described there.
660 static UBYTE arm_cpus[] =
662 CPUFAMILY_ARM_3,
663 CPUFAMILY_ARM_4,
664 CPUFAMILY_ARM_4T,
665 CPUFAMILY_ARM_5T,
666 CPUFAMILY_ARM_5TE,
667 CPUFAMILY_ARM_5TEJ,
668 CPUFAMILY_ARM_6,
669 CPUFAMILY_ARM_6,
670 CPUFAMILY_ARM_6, /* 6KZ */
671 CPUFAMILY_ARM_6, /* 6T2 */
672 CPUFAMILY_ARM_6, /* 6K */
673 CPUFAMILY_ARM_7,
674 CPUFAMILY_ARM_6, /* 6-M */
675 CPUFAMILY_ARM_6, /* 6S-M */
676 CPUFAMILY_ARM_7 /* 7E-M */
679 static BOOL ARM_ParseAttrs(UBYTE *data, ULONG len, struct DosLibrary *DOSBase)
681 struct attrs_section *attrs;
683 if (data[0] != ATTR_VERSION_CURRENT)
685 DATTR(bug("[ELF.ARM] Unknown attributes version: 0x%02\n", data[0]));
686 return FALSE;
689 attrs = (void *)data + 1;
690 while (len > 0)
692 ULONG attrs_size = READLONG_UNALIGNED(attrs->size);
694 if (!strcmp(attrs->vendor, "aeabi"))
696 struct attrs_subsection *aeabi_attrs = (void *)attrs->vendor + 6;
697 ULONG aeabi_len = attrs_size - 10;
699 DATTR(bug("[ELF.ARM] Found aeabi attributes @ 0x%p (length %u)\n", aeabi_attrs, aeabi_len));
701 while (aeabi_len > 0)
703 ULONG aeabi_attrs_size = READLONG_UNALIGNED(aeabi_attrs->size);
705 if (aeabi_attrs->tag == Tag_File)
707 UBYTE *file_subsection = (void *)aeabi_attrs + sizeof(struct attrs_subsection);
708 UBYTE file_len = aeabi_attrs_size - sizeof(struct attrs_subsection);
710 DATTR(bug("[ELF.ARM] Found file-wide attributes @ 0x%p (length %u)\n", file_subsection, file_len));
712 while (file_len > 0)
714 UBYTE tag, shift;
715 ULONG val = 0;
717 tag = *file_subsection++;
718 file_len--;
720 if (file_len == 0)
722 DATTR(bug("[ELF.ARM] Mailformed attribute tag %d (no data)\n", tag));
723 return FALSE;
726 switch (tag)
728 case Tag_CPU_raw_name:
729 case Tag_CPU_name:
730 case Tag_compatibility:
731 case Tag_also_compatible_with:
732 case Tag_conformance:
733 /* These two are NULL-terminated strings. Just skip. */
734 while (file_len)
736 file_len--;
737 if (*file_subsection++ == 0)
738 break;
740 break;
742 default:
743 /* Read ULEB128 value */
744 shift = 0;
745 while (file_len)
747 UBYTE byte;
749 byte = *file_subsection++;
750 file_len--;
752 val |= (byte & 0x7F) << shift;
753 if (!(byte & 0x80))
754 break;
756 shift += 7;
760 switch (tag)
762 case Tag_CPU_arch:
763 DATTR(bug("[ELF.ARM] ARM CPU architecture set to %d\n", val));
765 if (val > ELF_CPU_ARMv7EM)
767 DATTR(bug("[ELF.ARM] Unknown CPU tag value (%d)\n", val));
768 return FALSE;
771 if (arm_cpus[val] > IDosBase(DOSBase)->arm_Arch)
773 DATTR(bug("[ELF.ARM] CPU Requirements too high (system %d, file %d)\n", IDosBase(DOSBase)->arm_Arch, arm_cpus[val]));
774 return FALSE;
776 break;
778 case Tag_FP_arch:
779 DATTR(bug("[ELF.ARM] ARM FPU architecture set to %d\n", val));
781 switch (val)
783 case ELF_FP_None:
784 break;
786 case ELF_FP_v1:
787 case ELF_FP_v2:
788 if (!IDosBase(DOSBase)->arm_VFP)
790 DATTR(bug("[ELF.ARM] VFP required but missing\n"));
791 return FALSE;
793 break;
795 case ELF_FP_v3:
796 case ELF_FP_v3_Short:
797 if (!IDosBase(DOSBase)->arm_VFP_v3)
799 DATTR(bug("[ELF.ARM] VFPv3 required but missing\n"));
800 return FALSE;
802 break;
804 default:
805 /* This includes VFPv4 for now */
806 DATTR(bug("[ELF.ARM] VFP %d required -- unsupported\n", val));
807 return FALSE;
810 break;
814 /* We allow to execute only files which contain attributes section */
815 return TRUE;
817 aeabi_attrs = (void *)aeabi_attrs + aeabi_attrs_size;
818 aeabi_len -= aeabi_attrs_size;
821 return FALSE;
823 attrs = (void *)attrs + attrs_size;
824 len -= attrs_size;
826 return FALSE;
829 #endif
831 BPTR InternalLoadSeg_ELF
833 BPTR file,
834 BPTR table __unused,
835 SIPTR *funcarray,
836 LONG *stack __unused,
837 struct DosLibrary *DOSBase
840 struct elfheader eh;
841 struct sheader *sh;
842 struct sheader *symtab_shndx = NULL;
843 struct sheader *strtab = NULL;
844 BPTR hunks = 0;
845 BPTR *next_hunk_ptr = &hunks;
846 ULONG i;
847 BOOL exec_hunk_seen = FALSE;
848 ULONG int_shnum;
850 /* load and validate ELF header */
851 if (!load_header(file, &eh, funcarray, DOSBase))
852 return 0;
854 int_shnum = read_shnum(file, &eh, funcarray, DOSBase);
855 if (!int_shnum)
856 return 0;
858 /* load section headers */
859 if (!(sh = load_block(file, eh.shoff, int_shnum * eh.shentsize, funcarray, DOSBase)))
860 return 0;
862 #ifdef __arm__
863 for (i = 0; i < int_shnum; i++)
865 if (sh[i].type == SHT_ARM_ATTRIBUTES)
867 ULONG len = sh[i].size;
868 UBYTE *data = load_block(file, sh[i].offset, len, funcarray, DOSBase);
870 if (data)
872 BOOL res = ARM_ParseAttrs(data, len, DOSBase);
874 ilsFreeMem(data, len);
876 if (!res)
878 D(bug("[ELF Loader] Can't parse ARM attributes\n"));
879 SetIoErr(ERROR_NOT_EXECUTABLE);
880 goto error;
885 #endif
887 /* Iterate over the section headers in order to do some stuff... */
888 for (i = 0; i < int_shnum; i++)
891 Load the symbol and string table(s).
893 NOTICE: the ELF standard, at the moment (Nov 2002) explicitely states
894 that only one symbol table per file is allowed. However, it
895 also states that this may change in future... we already handle it.
897 if (sh[i].type == SHT_SYMTAB || sh[i].type == SHT_STRTAB || sh[i].type == SHT_SYMTAB_SHNDX)
899 sh[i].addr = load_block(file, sh[i].offset, sh[i].size, funcarray, DOSBase);
900 if (!sh[i].addr)
901 goto error;
903 if (sh[i].type == SHT_STRTAB) {
904 if (strtab == NULL) {
905 strtab = &sh[i];
906 } else {
907 D(bug("[ELF Loader] file contains multiple strtab tables. only using the first one\n"));
911 if (sh[i].type == SHT_SYMTAB_SHNDX) {
912 if (symtab_shndx == NULL)
913 symtab_shndx = &sh[i];
914 else
915 D(bug("[ELF Loader] file contains multiple symtab shndx tables. only using the first one\n"));
920 /* Now that we have the string and symbol tables loaded,
921 * load the rest of the hunks.
923 for (i = 0; i < int_shnum; i++)
925 /* Skip the already loaded hunks */
926 if (sh[i].type == SHT_SYMTAB || sh[i].type == SHT_STRTAB || sh[i].type == SHT_SYMTAB_SHNDX)
927 continue;
929 /* Load the section in memory if needed, and make a hunk out of it */
930 if (sh[i].flags & SHF_ALLOC)
932 if (sh[i].size)
934 /* Only allow alignment if this is an executable hunk
935 or if an executable hunk has been loaded already,
936 so to avoid the situation in which a data hunk has its
937 content displaced from the hunk's header in case it's the
938 first hunk (this happens with Keymaps, for instance). */
939 if (sh[i].flags & SHF_EXECINSTR)
940 exec_hunk_seen = TRUE;
942 if (!load_hunk(file, &next_hunk_ptr, &sh[i], strtab ? strtab->addr : NULL, funcarray, exec_hunk_seen, DOSBase))
943 goto error;
948 /* Relocate the sections */
949 for (i = 0; i < int_shnum; i++)
951 /* Does this relocation section refer to a hunk? If so, addr must be != 0 */
952 if ((sh[i].type == AROS_ELF_REL) && sh[SHINDEX(sh[i].info)].addr)
954 sh[i].addr = load_block(file, sh[i].offset, sh[i].size, funcarray, DOSBase);
955 if (!sh[i].addr || !relocate(&eh, sh, i, symtab_shndx, DOSBase))
956 goto error;
958 ilsFreeMem(sh[i].addr, sh[i].size);
959 sh[i].addr = NULL;
963 /* Everything is loaded now. Register the module at kernel.resource */
964 register_elf(file, hunks, &eh, sh, DOSBase);
965 goto end;
967 error:
969 /* There were some errors, deallocate The hunks */
971 InternalUnLoadSeg(hunks, (VOID_FUNC)funcarray[2]);
972 hunks = 0;
974 end:
977 * Clear the caches to let the CPU see the new data and instructions.
978 * We check for SysBase's lib_Version, since this code is also built
979 * as linklib for AmigaOS version of AROS bootstrap, and it can be
980 * running on AOS 1.3 or lower.
982 if (SysBase->LibNode.lib_Version >= 36)
984 BPTR curr = hunks;
986 while (curr)
988 struct hunk *hunk = BPTR2HUNK(BADDR(curr));
990 CacheClearE(hunk->data, hunk->size, CACRF_ClearD | CACRF_ClearI);
992 curr = hunk->next;
996 /* deallocate the symbol tables */
997 for (i = 0; i < int_shnum; i++)
999 if (((sh[i].type == SHT_SYMTAB) || (sh[i].type == SHT_STRTAB)) && (sh[i].addr != NULL))
1000 ilsFreeMem(sh[i].addr, sh[i].size);
1003 /* Free the section headers */
1004 ilsFreeMem(sh, int_shnum * eh.shentsize);
1006 return hunks;