2 Copyright (C) 1995-2019, The AROS Development Team. All rights reserved.
5 Desc: Code to dynamically load ELF executables
11 #include <aros/asmcall.h>
12 #include <aros/debug.h>
13 #include <aros/macros.h>
14 #include <exec/memory.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>
27 #include "internalloadseg.h"
28 #include "dos_intern.h"
29 #include "include/loadseg.h"
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.
57 static int elf_read_block
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
);
79 if (ilsSeek(file
, offset
, OFFSET_BEGINNING
) < 0)
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
;
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
);
96 return read_block(file
, buffer
, size
, funcarray
, DOSBase
);
101 static void *load_block
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
);
118 if (!elf_read_block(file
, offset
, block
, size
, funcarray
, srb
, DOSBase
))
121 ilsFreeMem(block
, size
);
124 SetIoErr(ERROR_NO_FREE_STORE
);
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.
147 if (eh
->shoff
== 0) {
148 D(bug("[ELF Loader] No section header\n"));
149 SetIoErr(ERROR_NOT_EXECUTABLE
);
153 if (elf_read_block(file
, eh
->shoff
, &sh
, sizeof(sh
), funcarray
, srb
, DOSBase
))
156 /* wider section header count is in the size field */
159 /* sanity, if they're still invalid then this isn't elf */
161 D(bug("[ELF Loader] Empty section header\n"));
162 SetIoErr(ERROR_NOT_EXECUTABLE
);
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
))
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
);
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
);
203 static int __attribute__ ((noinline
)) load_hunk
206 BPTR
**next_hunk_ptr
,
211 struct SRBuffer
*srb
,
212 struct DosLibrary
*DOSBase
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
);
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
);
236 CONST_STRPTR nameext
;
238 nameext
= strrchr(strtab
+ sh
->name
, '.');
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));
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. */
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
);
275 sh
->addr
= (char *)AROS_ROUNDUP2((IPTR
)hunk
->data
, sh
->addralign
);
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
);
295 SetIoErr(ERROR_NO_FREE_STORE
);
302 struct elfheader
*eh
,
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
))
323 ULONG numrel
= shrel
->size
/ shrel
->entsize
;
326 for (i
=0; i
<numrel
; i
++, rel
++)
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
)
343 sym
= &symtab
[ELF_R_SYM(rel
->info
)];
344 p
= toreloc
->addr
+ rel
->offset
;
346 if (sym
->shindex
!= SHN_XINDEX
)
347 shindex
= sym
->shindex
;
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
);
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
));
364 D(bug("[ELF Loader] COMMON symbol '%s'\n",
365 (STRPTR
)sh
[shsymtab
->link
].addr
+ sym
->name
));
366 SetIoErr(ERROR_BAD_HUNK
);
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
);
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 */
395 case R_386_PC32
: /* 32bit PC relative */
402 #elif defined(__x86_64__)
403 case R_X86_64_64
: /* 64bit direct/absolute */
404 *(UQUAD
*)p
= s
+ rel
->addend
;
408 case R_X86_64_PC32
: /* PC relative 32 bit signed */
409 *(ULONG
*)p
= s
+ rel
->addend
- (IPTR
) p
;
413 *(ULONG
*)p
= (UQUAD
)s
+ (UQUAD
)rel
->addend
;
417 *(LONG
*)p
= (QUAD
)s
+ (QUAD
)rel
->addend
;
420 case R_X86_64_NONE
: /* No reloc */
423 #elif defined(__mc68000__)
426 *p
= s
+ rel
->addend
;
430 *(UWORD
*)p
= s
+ rel
->addend
;
434 *(UBYTE
*)p
= s
+ rel
->addend
;
438 *p
= s
+ rel
->addend
- (ULONG
)p
;
442 *(UWORD
*)p
= s
+ rel
->addend
- (ULONG
)p
;
446 *(UBYTE
*)p
= s
+ rel
->addend
- (ULONG
)p
;
452 #elif defined(__ppc__) || defined(__powerpc__)
455 *p
= s
+ rel
->addend
;
458 case R_PPC_ADDR16_LO
:
460 unsigned short *c
= (unsigned short *) p
;
461 *c
= (s
+ rel
->addend
) & 0xffff;
465 case R_PPC_ADDR16_HA
:
467 unsigned short *c
= (unsigned short *) p
;
468 ULONG temp
= s
+ rel
->addend
;
470 if ((temp
& 0x8000) != 0)
477 unsigned short *c
= (unsigned short *) p
;
478 *c
= (s
+ rel
->addend
- (ULONG
) p
) & 0xffff;
484 unsigned short *c
= (unsigned short *) p
;
485 ULONG temp
= s
+ rel
->addend
- (ULONG
) p
;
487 if ((temp
& 0x8000) != 0)
494 *p
|= (s
+ rel
->addend
- (ULONG
) p
) & 0x3fffffc;
498 *p
= s
+ rel
->addend
- (ULONG
) p
;
504 #elif defined(__arm__)
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
);
523 offset
+= s
- (ULONG
)p
;
526 *p
&= AROS_LONG2LE(0xff000000);
527 *p
|= AROS_LONG2LE(offset
& 0x00ffffff);
532 case R_ARM_THM_JUMP24
:
534 ULONG upper
,lower
,sign
,j1
,j2
;
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
);
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)));
573 case R_ARM_THM_MOVW_ABS_NC
:
574 case R_ARM_THM_MOVT_ABS
:
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) |
587 offset
= (offset
^ 0x8000) - 0x8000;
591 if (ELF_R_TYPE(rel
->info
) == R_ARM_THM_MOVT_ABS
)
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) |
603 case R_ARM_MOVW_ABS_NC
:
606 signed long offset
= AROS_LE2LONG(*p
);
607 offset
= ((offset
& 0xf0000) >> 4) | (offset
& 0xfff);
608 offset
= (offset
^ 0x8000) - 0x8000;
612 if (ELF_R_TYPE(rel
->info
) == R_ARM_MOVT_ABS
)
615 *p
&= AROS_LONG2LE(0xfff0f000);
616 *p
|= AROS_LONG2LE(((offset
& 0xf000) << 4) | (offset
& 0x0fff));
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
631 # error Your architecture is not supported
635 bug("[ELF Loader] Unknown relocation #%d type %d\n", i
, ELF_R_TYPE(rel
->info
));
636 SetIoErr(ERROR_BAD_HUNK
);
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
656 static inline ULONG
readlong_unaligned(ULONG
*src
)
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
)
674 #define READLONG_UNALIGNED(src) readlong_unaligned(&src);
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
[] =
693 CPUFAMILY_ARM_6
, /* 6KZ */
694 CPUFAMILY_ARM_6
, /* 6T2 */
695 CPUFAMILY_ARM_6
, /* 6K */
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]));
712 attrs
= (void *)data
+ 1;
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
));
740 tag
= *file_subsection
++;
745 DATTR(bug("[ELF.ARM] Mailformed attribute tag %d (no data)\n", tag
));
751 case Tag_CPU_raw_name
:
753 case Tag_compatibility
:
754 case Tag_also_compatible_with
:
755 case Tag_conformance
:
756 /* These two are NULL-terminated strings. Just skip. */
760 if (*file_subsection
++ == 0)
766 /* Read ULEB128 value */
772 byte
= *file_subsection
++;
775 val
|= (byte
& 0x7F) << shift
;
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
));
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
]));
802 DATTR(bug("[ELF.ARM] ARM FPU architecture set to %d\n", val
));
811 if (!IDosBase(DOSBase
)->arm_VFP
)
813 DATTR(bug("[ELF.ARM] VFP required but missing\n"));
819 case ELF_FP_v3_Short
:
820 if (!IDosBase(DOSBase
)->arm_VFP_v3
)
822 DATTR(bug("[ELF.ARM] VFPv3 required but missing\n"));
828 /* This includes VFPv4 for now */
829 DATTR(bug("[ELF.ARM] VFP %d required -- unsupported\n", val
));
837 /* We allow to execute only files which contain attributes section */
840 aeabi_attrs
= (void *)aeabi_attrs
+ aeabi_attrs_size
;
841 aeabi_len
-= aeabi_attrs_size
;
846 attrs
= (void *)attrs
+ attrs_size
;
854 BPTR InternalLoadSeg_ELF
859 LONG
*stack __unused
,
860 struct DosLibrary
*DOSBase
865 struct sheader
*symtab_shndx
= NULL
;
866 struct sheader
*strtab
= NULL
;
868 BPTR
*next_hunk_ptr
= &hunks
;
870 BOOL exec_hunk_seen
= FALSE
;
872 struct SRBuffer srb
= { 0 };
874 /* load and validate ELF header */
875 if (!load_header(file
, &eh
, funcarray
, &srb
, DOSBase
))
878 int_shnum
= read_shnum(file
, &eh
, funcarray
, &srb
, DOSBase
);
882 /* load section headers */
883 if (!(sh
= load_block(file
, eh
.shoff
, int_shnum
* eh
.shentsize
, funcarray
, &srb
, DOSBase
)))
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
);
896 BOOL res
= ARM_ParseAttrs(data
, len
, DOSBase
);
898 ilsFreeMem(data
, len
);
902 D(bug("[ELF Loader] Can't parse ARM attributes\n"));
903 SetIoErr(ERROR_NOT_EXECUTABLE
);
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
);
927 if (sh
[i
].type
== SHT_STRTAB
&& i
== eh
.shstrndx
) {
928 if (strtab
== NULL
) {
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
];
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
)
953 /* Load the section in memory if needed, and make a hunk out of it */
954 if (sh
[i
].flags
& SHF_ALLOC
)
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
))
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
))
982 ilsFreeMem(sh
[i
].addr
, sh
[i
].size
);
987 /* Everything is loaded now. Register the module at kernel.resource */
988 register_elf(file
, hunks
, &eh
, sh
, DOSBase
);
993 /* There were some errors, deallocate The hunks */
995 InternalUnLoadSeg(hunks
, (VOID_FUNC
)funcarray
[2]);
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)
1012 struct hunk
*hunk
= BPTR2HUNK(BADDR(curr
));
1014 CacheClearE(hunk
->data
, hunk
->size
, CACRF_ClearD
| CACRF_ClearI
);
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
);