2 Copyright © 1995-2016, 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
;
407 case R_X86_64_PC32
: /* PC relative 32 bit signed */
408 *(ULONG
*)p
= s
+ rel
->addend
- (IPTR
) p
;
412 *(ULONG
*)p
= (UQUAD
)s
+ (UQUAD
)rel
->addend
;
416 *(LONG
*)p
= (QUAD
)s
+ (QUAD
)rel
->addend
;
419 case R_X86_64_NONE
: /* No reloc */
422 #elif defined(__mc68000__)
425 *p
= s
+ rel
->addend
;
429 *(UWORD
*)p
= s
+ rel
->addend
;
433 *(UBYTE
*)p
= s
+ rel
->addend
;
437 *p
= s
+ rel
->addend
- (ULONG
)p
;
441 *(UWORD
*)p
= s
+ rel
->addend
- (ULONG
)p
;
445 *(UBYTE
*)p
= s
+ rel
->addend
- (ULONG
)p
;
451 #elif defined(__ppc__) || defined(__powerpc__)
454 *p
= s
+ rel
->addend
;
457 case R_PPC_ADDR16_LO
:
459 unsigned short *c
= (unsigned short *) p
;
460 *c
= (s
+ rel
->addend
) & 0xffff;
464 case R_PPC_ADDR16_HA
:
466 unsigned short *c
= (unsigned short *) p
;
467 ULONG temp
= s
+ rel
->addend
;
469 if ((temp
& 0x8000) != 0)
476 unsigned short *c
= (unsigned short *) p
;
477 *c
= (s
+ rel
->addend
- (ULONG
) p
) & 0xffff;
483 unsigned short *c
= (unsigned short *) p
;
484 ULONG temp
= s
+ rel
->addend
- (ULONG
) p
;
486 if ((temp
& 0x8000) != 0)
493 *p
|= (s
+ rel
->addend
- (ULONG
) p
) & 0x3fffffc;
497 *p
= s
+ rel
->addend
- (ULONG
) p
;
503 #elif defined(__arm__)
509 /* On ARM the 24 bit offset is shifted by 2 to the right */
510 signed long offset
= (*p
& 0x00ffffff) << 2;
511 /* If highest bit set, make offset negative */
512 if (offset
& 0x02000000)
513 offset
-= 0x04000000;
515 if (offset
>= 0x02000000 ||
516 offset
<= -0x02000000)
518 bug("[ELF Loader] Relocation type %d %d out of range!\n", i
, ELF_R_TYPE(rel
->info
));
519 SetIoErr(ERROR_BAD_HUNK
);
522 offset
+= s
- (ULONG
)p
;
526 *p
|= offset
& 0x00ffffff;
531 case R_ARM_THM_JUMP24
:
533 ULONG upper
,lower
,sign
,j1
,j2
;
536 upper
= *((UWORD
*)p
);
537 lower
= *((UWORD
*)p
+1);
539 sign
= (upper
>> 10) & 1;
540 j1
= (lower
>> 13) & 1;
541 j2
= (lower
>> 11) & 1;
543 offset
= (sign
<< 24) | ((~(j1
^ sign
) & 1) << 23) |
544 ((~(j2
^ sign
) & 1) << 22) |
545 ((upper
& 0x03ff) << 12) |
546 ((lower
& 0x07ff) << 1);
548 if (offset
& 0x01000000)
549 offset
-= 0x02000000;
551 if (offset
>= 0x01000000 ||
552 offset
<= -0x01000000)
554 bug("[ELF Loader] Relocation type %d %d out of range!\n", i
, ELF_R_TYPE(rel
->info
));
555 SetIoErr(ERROR_BAD_HUNK
);
558 offset
+= s
- (ULONG
)p
;
560 sign
= (offset
>> 24) & 1;
561 j1
= sign
^ (~(offset
>> 23) & 1);
562 j2
= sign
^ (~(offset
>> 22) & 1);
564 *(UWORD
*)p
= (UWORD
)((upper
& 0xf800) | (sign
<< 10) |
565 ((offset
>> 12) & 0x03ff));
566 *((UWORD
*)p
+ 1) = (UWORD
)((lower
& 0xd000) |
567 (j1
<< 13) | (j2
<< 11) | ((offset
>> 1) & 0x07ff));
572 case R_ARM_THM_MOVW_ABS_NC
:
573 case R_ARM_THM_MOVT_ABS
:
578 upper
= *((UWORD
*)p
);
579 lower
= *((UWORD
*)p
+1);
581 offset
= ((upper
& 0x000f) << 12) |
582 ((upper
& 0x0400) << 1) |
583 ((lower
& 0x7000) >> 4) |
586 offset
= (offset
^ 0x8000) - 0x8000;
590 if (ELF_R_TYPE(rel
->info
) == R_ARM_THM_MOVT_ABS
)
593 *(UWORD
*)p
= (UWORD
)((upper
& 0xfbf0) |
594 ((offset
& 0xf000) >> 12) |
595 ((offset
& 0x0800) >> 1));
596 *((UWORD
*)p
+ 1) = (UWORD
)((lower
& 0x8f00) |
597 ((offset
& 0x0700)<< 4) |
602 case R_ARM_MOVW_ABS_NC
:
605 signed long offset
= *p
;
606 offset
= ((offset
& 0xf0000) >> 4) | (offset
& 0xfff);
607 offset
= (offset
^ 0x8000) - 0x8000;
611 if (ELF_R_TYPE(rel
->info
) == R_ARM_MOVT_ABS
)
615 *p
|= ((offset
& 0xf000) << 4) | (offset
& 0x0fff);
619 case R_ARM_TARGET2
: /* maps to R_ARM_ABS32 under EABI for AROS*/
620 case R_ARM_TARGET1
: /* use for constructors/destructors; maps to
630 # error Your architecture is not supported
634 D(bug("[ELF Loader] Unrecognized relocation type %d %d\n", i
, ELF_R_TYPE(rel
->info
)));
635 SetIoErr(ERROR_BAD_HUNK
);
646 * On ARM < v6 all LONG accesses must be LONG-aligned
647 * TODO: This is useful and can be moved to some public include file.
649 #if (__ARM_ARCH__ > 5)
651 #define READLONG_UNALIGNED(src) src
655 static inline ULONG
readlong_unaligned(ULONG
*src
)
660 "ldrb %0, [%2, #0]\n\t"
661 "ldrb %1, [%2, #1]\n\t"
662 "orr %0, %0, %1, lsl #8\n\t"
663 "ldrb %1, [%2, #2]\n\t"
664 "orr %0, %0, %1, lsl #16\n\t"
665 "ldrb %1, [%2, #3]\n\t"
666 "orr %0, %0, %1, lsl #24"
667 :"=&r"(res
), "=&r"(tmp
) : "r"(src
)
673 #define READLONG_UNALIGNED(src) readlong_unaligned(&src);
677 * This code parses special .ARM.Attributes section and
678 * extracts system requirements from it. Things like float ABI,
679 * minimum CPU and FPU version are described there.
682 static UBYTE arm_cpus
[] =
692 CPUFAMILY_ARM_6
, /* 6KZ */
693 CPUFAMILY_ARM_6
, /* 6T2 */
694 CPUFAMILY_ARM_6
, /* 6K */
696 CPUFAMILY_ARM_6
, /* 6-M */
697 CPUFAMILY_ARM_6
, /* 6S-M */
698 CPUFAMILY_ARM_7
/* 7E-M */
701 static BOOL
ARM_ParseAttrs(UBYTE
*data
, ULONG len
, struct DosLibrary
*DOSBase
)
703 struct attrs_section
*attrs
;
705 if (data
[0] != ATTR_VERSION_CURRENT
)
707 DATTR(bug("[ELF.ARM] Unknown attributes version: 0x%02\n", data
[0]));
711 attrs
= (void *)data
+ 1;
714 ULONG attrs_size
= READLONG_UNALIGNED(attrs
->size
);
716 if (!strcmp(attrs
->vendor
, "aeabi"))
718 struct attrs_subsection
*aeabi_attrs
= (void *)attrs
->vendor
+ 6;
719 ULONG aeabi_len
= attrs_size
- 10;
721 DATTR(bug("[ELF.ARM] Found aeabi attributes @ 0x%p (length %u)\n", aeabi_attrs
, aeabi_len
));
723 while (aeabi_len
> 0)
725 ULONG aeabi_attrs_size
= READLONG_UNALIGNED(aeabi_attrs
->size
);
727 if (aeabi_attrs
->tag
== Tag_File
)
729 UBYTE
*file_subsection
= (void *)aeabi_attrs
+ sizeof(struct attrs_subsection
);
730 UBYTE file_len
= aeabi_attrs_size
- sizeof(struct attrs_subsection
);
732 DATTR(bug("[ELF.ARM] Found file-wide attributes @ 0x%p (length %u)\n", file_subsection
, file_len
));
739 tag
= *file_subsection
++;
744 DATTR(bug("[ELF.ARM] Mailformed attribute tag %d (no data)\n", tag
));
750 case Tag_CPU_raw_name
:
752 case Tag_compatibility
:
753 case Tag_also_compatible_with
:
754 case Tag_conformance
:
755 /* These two are NULL-terminated strings. Just skip. */
759 if (*file_subsection
++ == 0)
765 /* Read ULEB128 value */
771 byte
= *file_subsection
++;
774 val
|= (byte
& 0x7F) << shift
;
785 DATTR(bug("[ELF.ARM] ARM CPU architecture set to %d\n", val
));
787 if (val
> ELF_CPU_ARMv7EM
)
789 DATTR(bug("[ELF.ARM] Unknown CPU tag value (%d)\n", val
));
793 if (arm_cpus
[val
] > IDosBase(DOSBase
)->arm_Arch
)
795 DATTR(bug("[ELF.ARM] CPU Requirements too high (system %d, file %d)\n", IDosBase(DOSBase
)->arm_Arch
, arm_cpus
[val
]));
801 DATTR(bug("[ELF.ARM] ARM FPU architecture set to %d\n", val
));
810 if (!IDosBase(DOSBase
)->arm_VFP
)
812 DATTR(bug("[ELF.ARM] VFP required but missing\n"));
818 case ELF_FP_v3_Short
:
819 if (!IDosBase(DOSBase
)->arm_VFP_v3
)
821 DATTR(bug("[ELF.ARM] VFPv3 required but missing\n"));
827 /* This includes VFPv4 for now */
828 DATTR(bug("[ELF.ARM] VFP %d required -- unsupported\n", val
));
836 /* We allow to execute only files which contain attributes section */
839 aeabi_attrs
= (void *)aeabi_attrs
+ aeabi_attrs_size
;
840 aeabi_len
-= aeabi_attrs_size
;
845 attrs
= (void *)attrs
+ attrs_size
;
853 BPTR InternalLoadSeg_ELF
858 LONG
*stack __unused
,
859 struct DosLibrary
*DOSBase
864 struct sheader
*symtab_shndx
= NULL
;
865 struct sheader
*strtab
= NULL
;
867 BPTR
*next_hunk_ptr
= &hunks
;
869 BOOL exec_hunk_seen
= FALSE
;
871 struct SRBuffer srb
= { 0 };
873 /* load and validate ELF header */
874 if (!load_header(file
, &eh
, funcarray
, &srb
, DOSBase
))
877 int_shnum
= read_shnum(file
, &eh
, funcarray
, &srb
, DOSBase
);
881 /* load section headers */
882 if (!(sh
= load_block(file
, eh
.shoff
, int_shnum
* eh
.shentsize
, funcarray
, &srb
, DOSBase
)))
886 for (i
= 0; i
< int_shnum
; i
++)
888 if (sh
[i
].type
== SHT_ARM_ATTRIBUTES
)
890 ULONG len
= sh
[i
].size
;
891 UBYTE
*data
= load_block(file
, sh
[i
].offset
, len
, funcarray
, &srb
, DOSBase
);
895 BOOL res
= ARM_ParseAttrs(data
, len
, DOSBase
);
897 ilsFreeMem(data
, len
);
901 D(bug("[ELF Loader] Can't parse ARM attributes\n"));
902 SetIoErr(ERROR_NOT_EXECUTABLE
);
910 /* Iterate over the section headers in order to do some stuff... */
911 for (i
= 0; i
< int_shnum
; i
++)
914 Load the symbol and string table(s).
916 NOTICE: the ELF standard, at the moment (Nov 2002) explicitely states
917 that only one symbol table per file is allowed. However, it
918 also states that this may change in future... we already handle it.
920 if (sh
[i
].type
== SHT_SYMTAB
|| sh
[i
].type
== SHT_STRTAB
|| sh
[i
].type
== SHT_SYMTAB_SHNDX
)
922 sh
[i
].addr
= load_block(file
, sh
[i
].offset
, sh
[i
].size
, funcarray
, &srb
, DOSBase
);
926 if (sh
[i
].type
== SHT_STRTAB
) {
927 if (strtab
== NULL
) {
930 D(bug("[ELF Loader] file contains multiple strtab tables. only using the first one\n"));
934 if (sh
[i
].type
== SHT_SYMTAB_SHNDX
) {
935 if (symtab_shndx
== NULL
)
936 symtab_shndx
= &sh
[i
];
938 D(bug("[ELF Loader] file contains multiple symtab shndx tables. only using the first one\n"));
943 /* Now that we have the string and symbol tables loaded,
944 * load the rest of the hunks.
946 for (i
= 0; i
< int_shnum
; i
++)
948 /* Skip the already loaded hunks */
949 if (sh
[i
].type
== SHT_SYMTAB
|| sh
[i
].type
== SHT_STRTAB
|| sh
[i
].type
== SHT_SYMTAB_SHNDX
)
952 /* Load the section in memory if needed, and make a hunk out of it */
953 if (sh
[i
].flags
& SHF_ALLOC
)
957 /* Only allow alignment if this is an executable hunk
958 or if an executable hunk has been loaded already,
959 so to avoid the situation in which a data hunk has its
960 content displaced from the hunk's header in case it's the
961 first hunk (this happens with Keymaps, for instance). */
962 if (sh
[i
].flags
& SHF_EXECINSTR
)
963 exec_hunk_seen
= TRUE
;
965 if (!load_hunk(file
, &next_hunk_ptr
, &sh
[i
], strtab
? strtab
->addr
: NULL
, funcarray
, exec_hunk_seen
, &srb
, DOSBase
))
971 /* Relocate the sections */
972 for (i
= 0; i
< int_shnum
; i
++)
974 /* Does this relocation section refer to a hunk? If so, addr must be != 0 */
975 if ((sh
[i
].type
== AROS_ELF_REL
) && sh
[sh
[i
].info
].addr
)
977 sh
[i
].addr
= load_block(file
, sh
[i
].offset
, sh
[i
].size
, funcarray
, &srb
, DOSBase
);
978 if (!sh
[i
].addr
|| !relocate(&eh
, sh
, i
, symtab_shndx
, DOSBase
))
981 ilsFreeMem(sh
[i
].addr
, sh
[i
].size
);
986 /* Everything is loaded now. Register the module at kernel.resource */
987 register_elf(file
, hunks
, &eh
, sh
, DOSBase
);
992 /* There were some errors, deallocate The hunks */
994 InternalUnLoadSeg(hunks
, (VOID_FUNC
)funcarray
[2]);
1000 * Clear the caches to let the CPU see the new data and instructions.
1001 * We check for SysBase's lib_Version, since this code is also built
1002 * as linklib for AmigaOS version of AROS bootstrap, and it can be
1003 * running on AOS 1.3 or lower.
1005 if (SysBase
->LibNode
.lib_Version
>= 36)
1011 struct hunk
*hunk
= BPTR2HUNK(BADDR(curr
));
1013 CacheClearE(hunk
->data
, hunk
->size
, CACRF_ClearD
| CACRF_ClearI
);
1019 /* deallocate the symbol tables */
1020 for (i
= 0; i
< int_shnum
; i
++)
1022 if (((sh
[i
].type
== SHT_SYMTAB
) || (sh
[i
].type
== SHT_STRTAB
)) && (sh
[i
].addr
!= NULL
))
1023 ilsFreeMem(sh
[i
].addr
, sh
[i
].size
);
1026 /* Free the section headers */
1027 ilsFreeMem(sh
, int_shnum
* eh
.shentsize
);
1029 if (srb
.srb_Buffer
) FreeMem(srb
.srb_Buffer
, LOADSEG_SMALL_READ
);