revert between 56095 -> 55830 in arch
[AROS.git] / rom / dos / internalloadseg_elf.c
blobf471cdede48451037df7f068092d02d1f35fcc79
1 /*
2 Copyright (C) 1995-2019, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Code to dynamically load ELF executables
6 Lang: english
7 */
9 #define DATTR(x)
11 #include <aros/asmcall.h>
12 #include <aros/debug.h>
13 #include <aros/macros.h>
14 #include <exec/memory.h>
15 #include <dos/elf.h>
16 #include <dos/dosasl.h>
17 #include <libraries/debug.h>
18 #include <resources/processor.h>
19 #include <proto/dos.h>
20 #include <proto/arossupport.h>
21 #include <proto/debug.h>
22 #include <proto/exec.h>
24 #include <string.h>
25 #include <stddef.h>
27 #include "internalloadseg.h"
28 #include "dos_intern.h"
29 #include "include/loadseg.h"
31 struct hunk
33 ULONG size;
34 BPTR next;
35 char data[0];
36 } __attribute__((packed));
38 #define BPTR2HUNK(bptr) ((struct hunk *)((void *)bptr - offsetof(struct hunk, next)))
39 #define HUNK2BPTR(hunk) MKBADDR(&hunk->next)
41 #define LOADSEG_SMALL_READ 2048 /* Size adjusted by profiling in Callgrind */
43 /* [S]mall [R]eads [Buffer]
45 * Due to a fact that Seek flushes buffers, FRead that is used to do small reads
46 * cannot use the buffer. The problem is visible with C++ executables that
47 * have a big number of small sections and thus do many (in tens of thousands
48 * for Odyssey) very small reads.
50 * */
51 struct SRBuffer
53 ULONG srb_FileOffset;
54 APTR srb_Buffer;
57 static int elf_read_block
59 BPTR file,
60 ULONG offset,
61 APTR buffer,
62 ULONG size,
63 SIPTR *funcarray,
64 struct SRBuffer *srb,
65 struct DosLibrary *DOSBase
68 D(bug("[ELF Loader] elf_read_block (offset=%d, size=%d)\n", offset, size));
70 if (size <= LOADSEG_SMALL_READ && (offset >= srb->srb_FileOffset) &&
71 ((offset + size) <= (srb->srb_FileOffset + LOADSEG_SMALL_READ)) &&
72 srb->srb_Buffer != NULL)
74 CopyMem(srb->srb_Buffer + (offset - srb->srb_FileOffset), buffer, size);
75 return 0;
77 else
79 if (ilsSeek(file, offset, OFFSET_BEGINNING) < 0)
80 return 1;
82 if (size <= LOADSEG_SMALL_READ)
84 if (srb->srb_Buffer == NULL)
85 srb->srb_Buffer = AllocMem(LOADSEG_SMALL_READ, MEMF_ANY);
87 srb->srb_FileOffset = offset;
89 /* Fill the buffer */
90 read_block(file, srb->srb_Buffer, LOADSEG_SMALL_READ, funcarray, DOSBase);
91 /* Re-read, now srb will be used */
92 return elf_read_block(file, offset, buffer, size, funcarray, srb, DOSBase);
94 else
96 return read_block(file, buffer, size, funcarray, DOSBase);
101 static void *load_block
103 BPTR file,
104 ULONG offset,
105 ULONG size,
106 SIPTR *funcarray,
107 struct SRBuffer *srb,
108 struct DosLibrary *DOSBase
111 D(bug("[ELF Loader] Load Block\n"));
112 D(bug("[ELF Loader] (size=%d)\n",size));
113 D(bug("[ELF Loader] (funcarray=0x%x)\n",funcarray));
114 D(bug("[ELF Loader] (funcarray[1]=0x%x)\n",funcarray[1]));
115 void *block = ilsAllocMem(size, MEMF_ANY);
116 if (block)
118 if (!elf_read_block(file, offset, block, size, funcarray, srb, DOSBase))
119 return block;
121 ilsFreeMem(block, size);
123 else
124 SetIoErr(ERROR_NO_FREE_STORE);
126 return NULL;
129 static ULONG read_shnum(BPTR file, struct elfheader *eh, SIPTR *funcarray, struct SRBuffer *srb, struct DosLibrary *DOSBase)
131 ULONG shnum = eh->shnum;
133 /* the ELF header only uses 16 bits to store the count of section headers,
134 * so it can't handle more than 65535 headers. if the count is 0, and an
135 * offset is defined, then the real count can be found in the first
136 * section header (which always exists).
138 * similarly, if the string table index is SHN_XINDEX, then the actual
139 * index is found in the first section header also.
141 * see the System V ABI 2001-04-24 draft for more details.
143 if (eh->shnum == 0)
145 struct sheader sh;
147 if (eh->shoff == 0) {
148 D(bug("[ELF Loader] No section header\n"));
149 SetIoErr(ERROR_NOT_EXECUTABLE);
150 return 0;
153 if (elf_read_block(file, eh->shoff, &sh, sizeof(sh), funcarray, srb, DOSBase))
154 return 0;
156 /* wider section header count is in the size field */
157 shnum = sh.size;
159 /* sanity, if they're still invalid then this isn't elf */
160 if (shnum == 0) {
161 D(bug("[ELF Loader] Empty section header\n"));
162 SetIoErr(ERROR_NOT_EXECUTABLE);
166 return shnum;
169 static int load_header(BPTR file, struct elfheader *eh, SIPTR *funcarray, struct SRBuffer *srb, struct DosLibrary *DOSBase)
171 if (elf_read_block(file, 0, eh, sizeof(struct elfheader), funcarray, srb, DOSBase))
172 return 0;
174 if (eh->ident[0] != 0x7f || eh->ident[1] != 'E' ||
175 eh->ident[2] != 'L' || eh->ident[3] != 'F') {
176 D(bug("[ELF Loader] Not an ELF object\n"));
177 SetIoErr(ERROR_NOT_EXECUTABLE);
178 return 0;
180 D(bug("[ELF Loader] ELF object\n"));
182 /* WANT_CLASS should be defined for your target */
183 if (eh->ident[EI_CLASS] != AROS_ELF_CLASS ||
184 eh->ident[EI_VERSION] != EV_CURRENT ||
185 eh->type != ET_REL ||
186 eh->ident[EI_DATA] != AROS_ELF_DATA ||
187 eh->machine != AROS_ELF_MACHINE)
189 D(bug("[ELF Loader] Object is of wrong type\n"));
190 D(bug("[ELF Loader] EI_CLASS is %d - should be %d\n", eh->ident[EI_CLASS] , AROS_ELF_CLASS ));
191 D(bug("[ELF Loader] EI_VERSION is %d - should be %d\n", eh->ident[EI_VERSION], EV_CURRENT ));
192 D(bug("[ELF Loader] type is %d - should be %d\n", eh->type , ET_REL ));
193 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA] , AROS_ELF_DATA ));
194 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine , AROS_ELF_MACHINE));
196 SetIoErr(ERROR_NOT_EXECUTABLE);
197 return 0;
200 return 1;
203 static int __attribute__ ((noinline)) load_hunk
205 BPTR file,
206 BPTR **next_hunk_ptr,
207 struct sheader *sh,
208 CONST_STRPTR strtab,
209 SIPTR *funcarray,
210 BOOL do_align,
211 struct SRBuffer *srb,
212 struct DosLibrary *DOSBase
215 struct hunk *hunk;
216 ULONG hunk_size;
217 ULONG memflags = 0;
219 if (!sh->size)
220 return 1;
222 /* The size of the hunk is the size of the section, plus
223 the size of the hunk structure, plus the size of the alignment (if necessary)*/
224 hunk_size = sh->size + sizeof(struct hunk);
226 if (do_align)
228 hunk_size += sh->addralign;
230 /* Also create space for a trampoline, if necessary */
231 if (sh->flags & SHF_EXECINSTR)
232 hunk_size += sizeof(struct FullJumpVec);
235 if (strtab) {
236 CONST_STRPTR nameext;
238 nameext = strrchr(strtab + sh->name, '.');
239 if (nameext) {
240 if (strcmp(nameext, ".MEMF_CHIP")==0) {
241 memflags |= MEMF_CHIP;
242 } else if (strcmp(nameext, ".MEMF_LOCAL")==0) {
243 memflags |= MEMF_LOCAL;
244 } else if (strcmp(nameext, ".MEMF_KICK")==0) {
245 memflags |= MEMF_KICK;
246 } else if (strcmp(nameext, ".MEMF_FAST")==0) {
247 memflags |= MEMF_FAST;
248 } else if (strcmp(nameext, ".MEMF_PUBLIC")==0) {
249 memflags |= MEMF_PUBLIC;
254 hunk = ilsAllocMem(hunk_size, memflags | MEMF_PUBLIC | (sh->type == SHT_NOBITS ? MEMF_CLEAR : 0));
255 if (hunk)
257 hunk->next = 0;
258 hunk->size = hunk_size;
260 /* In case we are required to honour alignment, and If this section contains
261 executable code, create a trampoline to its beginning, so that even if the
262 alignment requirements make the actual code go much after the end of the
263 hunk structure, the code can still be reached in the usual way. */
264 if (do_align)
266 if (sh->flags & SHF_EXECINSTR)
268 sh->addr = (char *)AROS_ROUNDUP2
270 (IPTR)hunk->data + sizeof(struct FullJumpVec), sh->addralign
272 __AROS_SET_FULLJMP((struct FullJumpVec *)hunk->data, sh->addr);
274 else
275 sh->addr = (char *)AROS_ROUNDUP2((IPTR)hunk->data, sh->addralign);
277 else
278 sh->addr = hunk->data;
280 /* Link the previous one with the new one */
281 BPTR2HUNK(*next_hunk_ptr)->next = HUNK2BPTR(hunk);
283 D(bug("[dos] hunk @ %p, size=%08x, addr @ %p\n", hunk, hunk->size, sh->addr));
285 /* Update the pointer to the previous one, which is now the current one */
286 *next_hunk_ptr = &hunk->next;
288 if (sh->type != SHT_NOBITS)
289 return !elf_read_block(file, sh->offset, sh->addr, sh->size, funcarray, srb, DOSBase);
291 return 1;
295 SetIoErr(ERROR_NO_FREE_STORE);
297 return 0;
300 static int relocate
302 struct elfheader *eh,
303 struct sheader *sh,
304 ULONG shrel_idx,
305 struct sheader *symtab_shndx,
306 struct DosLibrary *DOSBase
309 struct sheader *shrel = &sh[shrel_idx];
310 struct sheader *shsymtab = &sh[shrel->link];
311 struct sheader *toreloc = &sh[shrel->info];
313 struct symbol *symtab = (struct symbol *)shsymtab->addr;
314 struct relo *rel = (struct relo *)shrel->addr;
317 * Ignore relocs if the target section has no allocation. that can happen
318 * eg. with a .debug PROGBITS and a .rel.debug section
320 if (!(toreloc->flags & SHF_ALLOC))
321 return 1;
323 ULONG numrel = shrel->size / shrel->entsize;
324 ULONG i;
326 for (i=0; i<numrel; i++, rel++)
328 struct symbol *sym;
329 ULONG *p;
330 IPTR s;
331 ULONG shindex;
333 #ifdef __arm__
335 * R_ARM_V4BX are actually special marks for the linker.
336 * They even never have a target (shindex == SHN_UNDEF),
337 * so we simply ignore them before doing any checks.
339 if (ELF_R_TYPE(rel->info) == R_ARM_V4BX)
340 continue;
341 #endif
343 sym = &symtab[ELF_R_SYM(rel->info)];
344 p = toreloc->addr + rel->offset;
346 if (sym->shindex != SHN_XINDEX)
347 shindex = sym->shindex;
349 else {
350 if (symtab_shndx == NULL) {
351 D(bug("[ELF Loader] got symbol with shndx 0xfff, but there's no symtab shndx table\n"));
352 SetIoErr(ERROR_BAD_HUNK);
353 return 0;
355 shindex = ((ULONG *)symtab_shndx->addr)[ELF_R_SYM(rel->info)];
358 DB2(bug("[ELF Loader] Processing symbol %s\n", sh[shsymtab->link].addr + sym->name));
360 switch (shindex)
363 case SHN_COMMON:
364 D(bug("[ELF Loader] COMMON symbol '%s'\n",
365 (STRPTR)sh[shsymtab->link].addr + sym->name));
366 SetIoErr(ERROR_BAD_HUNK);
368 return 0;
370 case SHN_ABS:
371 s = sym->value;
372 break;
374 case SHN_UNDEF:
375 if (ELF_R_TYPE(rel->info) != 0) {
376 D(bug("[ELF Loader] Undefined symbol '%s'\n",
377 (STRPTR)sh[shsymtab->link].addr + sym->name));
378 SetIoErr(ERROR_BAD_HUNK);
379 return 0;
381 /* fall through */
383 default:
384 s = (IPTR)sh[shindex].addr + sym->value;
387 switch (ELF_R_TYPE(rel->info))
389 #if defined(__i386__)
391 case R_386_32: /* 32bit absolute */
392 *p += s;
393 break;
395 case R_386_PC32: /* 32bit PC relative */
396 *p += s - (ULONG)p;
397 break;
399 case R_386_NONE:
400 break;
402 #elif defined(__x86_64__)
403 case R_X86_64_64: /* 64bit direct/absolute */
404 *(UQUAD *)p = s + rel->addend;
405 break;
407 case R_X86_64_PLT32:
408 case R_X86_64_PC32: /* PC relative 32 bit signed */
409 *(ULONG *)p = s + rel->addend - (IPTR) p;
410 break;
412 case R_X86_64_32:
413 *(ULONG *)p = (UQUAD)s + (UQUAD)rel->addend;
414 break;
416 case R_X86_64_32S:
417 *(LONG *)p = (QUAD)s + (QUAD)rel->addend;
418 break;
420 case R_X86_64_NONE: /* No reloc */
421 break;
423 #elif defined(__mc68000__)
425 case R_68K_32:
426 *p = s + rel->addend;
427 break;
429 case R_68K_16:
430 *(UWORD *)p = s + rel->addend;
431 break;
433 case R_68K_8:
434 *(UBYTE *)p = s + rel->addend;
435 break;
437 case R_68K_PC32:
438 *p = s + rel->addend - (ULONG)p;
439 break;
441 case R_68K_PC16:
442 *(UWORD *)p = s + rel->addend - (ULONG)p;
443 break;
445 case R_68K_PC8:
446 *(UBYTE *)p = s + rel->addend - (ULONG)p;
447 break;
449 case R_68K_NONE:
450 break;
452 #elif defined(__ppc__) || defined(__powerpc__)
454 case R_PPC_ADDR32:
455 *p = s + rel->addend;
456 break;
458 case R_PPC_ADDR16_LO:
460 unsigned short *c = (unsigned short *) p;
461 *c = (s + rel->addend) & 0xffff;
463 break;
465 case R_PPC_ADDR16_HA:
467 unsigned short *c = (unsigned short *) p;
468 ULONG temp = s + rel->addend;
469 *c = temp >> 16;
470 if ((temp & 0x8000) != 0)
471 (*c)++;
473 break;
475 case R_PPC_REL16_LO:
477 unsigned short *c = (unsigned short *) p;
478 *c = (s + rel->addend - (ULONG) p) & 0xffff;
480 break;
482 case R_PPC_REL16_HA:
484 unsigned short *c = (unsigned short *) p;
485 ULONG temp = s + rel->addend - (ULONG) p;
486 *c = temp >> 16;
487 if ((temp & 0x8000) != 0)
488 (*c)++;
490 break;
492 case R_PPC_REL24:
493 *p &= ~0x3fffffc;
494 *p |= (s + rel->addend - (ULONG) p) & 0x3fffffc;
495 break;
497 case R_PPC_REL32:
498 *p = s + rel->addend - (ULONG) p;
499 break;
501 case R_PPC_NONE:
502 break;
504 #elif defined(__arm__)
505 case R_ARM_CALL:
506 case R_ARM_JUMP24:
507 case R_ARM_PC24:
508 case R_ARM_PREL31:
510 /* On ARM the 24 bit offset is shifted by 2 to the right */
511 signed long offset = (AROS_LE2LONG(*p) & 0x00ffffff) << 2;
512 /* If highest bit set, make offset negative */
513 if (offset & 0x02000000)
514 offset -= 0x04000000;
516 if (offset >= 0x02000000 ||
517 offset <= -0x02000000)
519 bug("[ELF Loader] Relocation type %d %d out of range!\n", i, ELF_R_TYPE(rel->info));
520 SetIoErr(ERROR_BAD_HUNK);
521 return 0;
523 offset += s - (ULONG)p;
525 offset >>= 2;
526 *p &= AROS_LONG2LE(0xff000000);
527 *p |= AROS_LONG2LE(offset & 0x00ffffff);
529 break;
531 case R_ARM_THM_CALL:
532 case R_ARM_THM_JUMP24:
534 ULONG upper,lower,sign,j1,j2;
535 LONG offset;
537 upper = AROS_WORD2LE(*((UWORD *)p));
538 lower = AROS_WORD2LE(*((UWORD *)p+1));
540 sign = (upper >> 10) & 1;
541 j1 = (lower >> 13) & 1;
542 j2 = (lower >> 11) & 1;
544 offset = (sign << 24) | ((~(j1 ^ sign) & 1) << 23) |
545 ((~(j2 ^ sign) & 1) << 22) |
546 ((upper & 0x03ff) << 12) |
547 ((lower & 0x07ff) << 1);
549 if (offset & 0x01000000)
550 offset -= 0x02000000;
552 if (offset >= 0x01000000 ||
553 offset <= -0x01000000)
555 bug("[ELF Loader] Relocation type %d %d out of range!\n", i, ELF_R_TYPE(rel->info));
556 SetIoErr(ERROR_BAD_HUNK);
557 return 0;
559 offset += s - (ULONG)p;
561 sign = (offset >> 24) & 1;
562 j1 = sign ^ (~(offset >> 23) & 1);
563 j2 = sign ^ (~(offset >> 22) & 1);
565 *(UWORD *)p = AROS_WORD2LE((UWORD)((upper & 0xf800) | (sign << 10) |
566 ((offset >> 12) & 0x03ff)));
567 *((UWORD *)p + 1) = AROS_WORD2LE((UWORD)((lower & 0xd000) |
568 (j1 << 13) | (j2 << 11) | ((offset >> 1) & 0x07ff)));
571 break;
573 case R_ARM_THM_MOVW_ABS_NC:
574 case R_ARM_THM_MOVT_ABS:
576 ULONG upper,lower;
577 LONG offset;
579 upper = AROS_LE2WORD(*((UWORD *)p));
580 lower = AROS_LE2WORD(*((UWORD *)p+1));
582 offset = ((upper & 0x000f) << 12) |
583 ((upper & 0x0400) << 1) |
584 ((lower & 0x7000) >> 4) |
585 (lower & 0x00ff);
587 offset = (offset ^ 0x8000) - 0x8000;
589 offset += s;
591 if (ELF_R_TYPE(rel->info) == R_ARM_THM_MOVT_ABS)
592 offset >>= 16;
594 *(UWORD *)p = AROS_WORD2LE((UWORD)((upper & 0xfbf0) |
595 ((offset & 0xf000) >> 12) |
596 ((offset & 0x0800) >> 1)));
597 *((UWORD *)p + 1) = AROS_WORD2LE((UWORD)((lower & 0x8f00) |
598 ((offset & 0x0700)<< 4) |
599 (offset & 0x00ff)));
601 break;
603 case R_ARM_MOVW_ABS_NC:
604 case R_ARM_MOVT_ABS:
606 signed long offset = AROS_LE2LONG(*p);
607 offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff);
608 offset = (offset ^ 0x8000) - 0x8000;
610 offset += s;
612 if (ELF_R_TYPE(rel->info) == R_ARM_MOVT_ABS)
613 offset >>= 16;
615 *p &= AROS_LONG2LE(0xfff0f000);
616 *p |= AROS_LONG2LE(((offset & 0xf000) << 4) | (offset & 0x0fff));
618 break;
620 case R_ARM_TARGET2: /* maps to R_ARM_ABS32 under EABI for AROS*/
621 case R_ARM_TARGET1: /* use for constructors/destructors; maps to
622 R_ARM_ABS32 */
623 case R_ARM_ABS32:
624 *p += s;
625 break;
627 case R_ARM_NONE:
628 break;
630 #else
631 # error Your architecture is not supported
632 #endif
634 default:
635 bug("[ELF Loader] Unknown relocation #%d type %d\n", i, ELF_R_TYPE(rel->info));
636 SetIoErr(ERROR_BAD_HUNK);
637 return 0;
641 return 1;
644 #ifdef __arm__
647 * On ARM < v6 all LONG accesses must be LONG-aligned
648 * TODO: This is useful and can be moved to some public include file.
650 #if (__ARM_ARCH__ > 5)
652 #define READLONG_UNALIGNED(src) src
654 #else
656 static inline ULONG readlong_unaligned(ULONG *src)
658 ULONG res, tmp;
660 asm volatile(
661 "ldrb %0, [%2, #0]\n\t"
662 "ldrb %1, [%2, #1]\n\t"
663 "orr %0, %0, %1, lsl #8\n\t"
664 "ldrb %1, [%2, #2]\n\t"
665 "orr %0, %0, %1, lsl #16\n\t"
666 "ldrb %1, [%2, #3]\n\t"
667 "orr %0, %0, %1, lsl #24"
668 :"=&r"(res), "=&r"(tmp) : "r"(src)
671 return res;
674 #define READLONG_UNALIGNED(src) readlong_unaligned(&src);
675 #endif
678 * This code parses special .ARM.Attributes section and
679 * extracts system requirements from it. Things like float ABI,
680 * minimum CPU and FPU version are described there.
683 static UBYTE arm_cpus[] =
685 CPUFAMILY_ARM_3,
686 CPUFAMILY_ARM_4,
687 CPUFAMILY_ARM_4T,
688 CPUFAMILY_ARM_5T,
689 CPUFAMILY_ARM_5TE,
690 CPUFAMILY_ARM_5TEJ,
691 CPUFAMILY_ARM_6,
692 CPUFAMILY_ARM_6,
693 CPUFAMILY_ARM_6, /* 6KZ */
694 CPUFAMILY_ARM_6, /* 6T2 */
695 CPUFAMILY_ARM_6, /* 6K */
696 CPUFAMILY_ARM_7,
697 CPUFAMILY_ARM_6, /* 6-M */
698 CPUFAMILY_ARM_6, /* 6S-M */
699 CPUFAMILY_ARM_7 /* 7E-M */
702 static BOOL ARM_ParseAttrs(UBYTE *data, ULONG len, struct DosLibrary *DOSBase)
704 struct attrs_section *attrs;
706 if (data[0] != ATTR_VERSION_CURRENT)
708 DATTR(bug("[ELF.ARM] Unknown attributes version: 0x%02\n", data[0]));
709 return FALSE;
712 attrs = (void *)data + 1;
713 while (len > 0)
715 ULONG attrs_size = READLONG_UNALIGNED(attrs->size);
717 if (!strcmp(attrs->vendor, "aeabi"))
719 struct attrs_subsection *aeabi_attrs = (void *)attrs->vendor + 6;
720 ULONG aeabi_len = attrs_size - 10;
722 DATTR(bug("[ELF.ARM] Found aeabi attributes @ 0x%p (length %u)\n", aeabi_attrs, aeabi_len));
724 while (aeabi_len > 0)
726 ULONG aeabi_attrs_size = READLONG_UNALIGNED(aeabi_attrs->size);
728 if (aeabi_attrs->tag == Tag_File)
730 UBYTE *file_subsection = (void *)aeabi_attrs + sizeof(struct attrs_subsection);
731 UBYTE file_len = aeabi_attrs_size - sizeof(struct attrs_subsection);
733 DATTR(bug("[ELF.ARM] Found file-wide attributes @ 0x%p (length %u)\n", file_subsection, file_len));
735 while (file_len > 0)
737 UBYTE tag, shift;
738 ULONG val = 0;
740 tag = *file_subsection++;
741 file_len--;
743 if (file_len == 0)
745 DATTR(bug("[ELF.ARM] Mailformed attribute tag %d (no data)\n", tag));
746 return FALSE;
749 switch (tag)
751 case Tag_CPU_raw_name:
752 case Tag_CPU_name:
753 case Tag_compatibility:
754 case Tag_also_compatible_with:
755 case Tag_conformance:
756 /* These two are NULL-terminated strings. Just skip. */
757 while (file_len)
759 file_len--;
760 if (*file_subsection++ == 0)
761 break;
763 break;
765 default:
766 /* Read ULEB128 value */
767 shift = 0;
768 while (file_len)
770 UBYTE byte;
772 byte = *file_subsection++;
773 file_len--;
775 val |= (byte & 0x7F) << shift;
776 if (!(byte & 0x80))
777 break;
779 shift += 7;
783 switch (tag)
785 case Tag_CPU_arch:
786 DATTR(bug("[ELF.ARM] ARM CPU architecture set to %d\n", val));
788 if (val > ELF_CPU_ARMv7EM)
790 DATTR(bug("[ELF.ARM] Unknown CPU tag value (%d)\n", val));
791 return FALSE;
794 if (arm_cpus[val] > IDosBase(DOSBase)->arm_Arch)
796 DATTR(bug("[ELF.ARM] CPU Requirements too high (system %d, file %d)\n", IDosBase(DOSBase)->arm_Arch, arm_cpus[val]));
797 return FALSE;
799 break;
801 case Tag_FP_arch:
802 DATTR(bug("[ELF.ARM] ARM FPU architecture set to %d\n", val));
804 switch (val)
806 case ELF_FP_None:
807 break;
809 case ELF_FP_v1:
810 case ELF_FP_v2:
811 if (!IDosBase(DOSBase)->arm_VFP)
813 DATTR(bug("[ELF.ARM] VFP required but missing\n"));
814 return FALSE;
816 break;
818 case ELF_FP_v3:
819 case ELF_FP_v3_Short:
820 if (!IDosBase(DOSBase)->arm_VFP_v3)
822 DATTR(bug("[ELF.ARM] VFPv3 required but missing\n"));
823 return FALSE;
825 break;
827 default:
828 /* This includes VFPv4 for now */
829 DATTR(bug("[ELF.ARM] VFP %d required -- unsupported\n", val));
830 return FALSE;
833 break;
837 /* We allow to execute only files which contain attributes section */
838 return TRUE;
840 aeabi_attrs = (void *)aeabi_attrs + aeabi_attrs_size;
841 aeabi_len -= aeabi_attrs_size;
844 return FALSE;
846 attrs = (void *)attrs + attrs_size;
847 len -= attrs_size;
849 return FALSE;
852 #endif
854 BPTR InternalLoadSeg_ELF
856 BPTR file,
857 BPTR table __unused,
858 SIPTR *funcarray,
859 LONG *stack __unused,
860 struct DosLibrary *DOSBase
863 struct elfheader eh;
864 struct sheader *sh;
865 struct sheader *symtab_shndx = NULL;
866 struct sheader *strtab = NULL;
867 BPTR hunks = 0;
868 BPTR *next_hunk_ptr = &hunks;
869 ULONG i;
870 BOOL exec_hunk_seen = FALSE;
871 ULONG int_shnum;
872 struct SRBuffer srb = { 0 };
874 /* load and validate ELF header */
875 if (!load_header(file, &eh, funcarray, &srb, DOSBase))
876 return 0;
878 int_shnum = read_shnum(file, &eh, funcarray, &srb, DOSBase);
879 if (!int_shnum)
880 return 0;
882 /* load section headers */
883 if (!(sh = load_block(file, eh.shoff, int_shnum * eh.shentsize, funcarray, &srb, DOSBase)))
884 return 0;
886 #ifdef __arm__
887 for (i = 0; i < int_shnum; i++)
889 if (sh[i].type == SHT_ARM_ATTRIBUTES)
891 ULONG len = sh[i].size;
892 UBYTE *data = load_block(file, sh[i].offset, len, funcarray, &srb, DOSBase);
894 if (data)
896 BOOL res = ARM_ParseAttrs(data, len, DOSBase);
898 ilsFreeMem(data, len);
900 if (!res)
902 D(bug("[ELF Loader] Can't parse ARM attributes\n"));
903 SetIoErr(ERROR_NOT_EXECUTABLE);
904 goto error;
909 #endif
911 /* Iterate over the section headers in order to do some stuff... */
912 for (i = 0; i < int_shnum; i++)
915 Load the symbol and string table(s).
917 NOTICE: the ELF standard, at the moment (Nov 2002) explicitely states
918 that only one symbol table per file is allowed. However, it
919 also states that this may change in future... we already handle it.
921 if (sh[i].type == SHT_SYMTAB || sh[i].type == SHT_STRTAB || sh[i].type == SHT_SYMTAB_SHNDX)
923 sh[i].addr = load_block(file, sh[i].offset, sh[i].size, funcarray, &srb, DOSBase);
924 if (!sh[i].addr)
925 goto error;
927 if (sh[i].type == SHT_STRTAB && i == eh.shstrndx) {
928 if (strtab == NULL) {
929 strtab = &sh[i];
930 } else {
931 D(bug("[ELF Loader] file contains multiple strtab tables. only using the first one\n"));
935 if (sh[i].type == SHT_SYMTAB_SHNDX) {
936 if (symtab_shndx == NULL)
937 symtab_shndx = &sh[i];
938 else
939 D(bug("[ELF Loader] file contains multiple symtab shndx tables. only using the first one\n"));
944 /* Now that we have the string and symbol tables loaded,
945 * load the rest of the hunks.
947 for (i = 0; i < int_shnum; i++)
949 /* Skip the already loaded hunks */
950 if (sh[i].type == SHT_SYMTAB || sh[i].type == SHT_STRTAB || sh[i].type == SHT_SYMTAB_SHNDX)
951 continue;
953 /* Load the section in memory if needed, and make a hunk out of it */
954 if (sh[i].flags & SHF_ALLOC)
956 if (sh[i].size)
958 /* Only allow alignment if this is an executable hunk
959 or if an executable hunk has been loaded already,
960 so to avoid the situation in which a data hunk has its
961 content displaced from the hunk's header in case it's the
962 first hunk (this happens with Keymaps, for instance). */
963 if (sh[i].flags & SHF_EXECINSTR)
964 exec_hunk_seen = TRUE;
966 if (!load_hunk(file, &next_hunk_ptr, &sh[i], strtab ? strtab->addr : NULL, funcarray, exec_hunk_seen, &srb, DOSBase))
967 goto error;
972 /* Relocate the sections */
973 for (i = 0; i < int_shnum; i++)
975 /* Does this relocation section refer to a hunk? If so, addr must be != 0 */
976 if ((sh[i].type == AROS_ELF_REL) && sh[sh[i].info].addr)
978 sh[i].addr = load_block(file, sh[i].offset, sh[i].size, funcarray, &srb, DOSBase);
979 if (!sh[i].addr || !relocate(&eh, sh, i, symtab_shndx, DOSBase))
980 goto error;
982 ilsFreeMem(sh[i].addr, sh[i].size);
983 sh[i].addr = NULL;
987 /* Everything is loaded now. Register the module at kernel.resource */
988 register_elf(file, hunks, &eh, sh, DOSBase);
989 goto end;
991 error:
993 /* There were some errors, deallocate The hunks */
995 InternalUnLoadSeg(hunks, (VOID_FUNC)funcarray[2]);
996 hunks = 0;
998 end:
1001 * Clear the caches to let the CPU see the new data and instructions.
1002 * We check for SysBase's lib_Version, since this code is also built
1003 * as linklib for AmigaOS version of AROS bootstrap, and it can be
1004 * running on AOS 1.3 or lower.
1006 if (SysBase->LibNode.lib_Version >= 36)
1008 BPTR curr = hunks;
1010 while (curr)
1012 struct hunk *hunk = BPTR2HUNK(BADDR(curr));
1014 CacheClearE(hunk->data, hunk->size, CACRF_ClearD | CACRF_ClearI);
1016 curr = hunk->next;
1020 /* deallocate the symbol tables */
1021 for (i = 0; i < int_shnum; i++)
1023 if (((sh[i].type == SHT_SYMTAB) || (sh[i].type == SHT_STRTAB)) && (sh[i].addr != NULL))
1024 ilsFreeMem(sh[i].addr, sh[i].size);
1027 /* Free the section headers */
1028 ilsFreeMem(sh, int_shnum * eh.shentsize);
1030 if (srb.srb_Buffer) FreeMem(srb.srb_Buffer, LOADSEG_SMALL_READ);
1032 return hunks;