Added kernel module for starting the usb stack at boot time. It's not activated thoug...
[cake.git] / rom / dos / internalloadseg_elf.c
blobdad801c8a02afa86f6c424baf25914a36583c734
1 /*
2 Copyright © 1995-2007, 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 DEBUG 0
14 #include <exec/memory.h>
15 #include <proto/exec.h>
16 #include <dos/dosasl.h>
17 #include <proto/dos.h>
18 #include <proto/arossupport.h>
19 #include <aros/asmcall.h>
20 #include "internalloadseg.h"
21 #include "dos_intern.h"
23 #include <aros/debug.h>
24 #include <string.h>
25 #include <stddef.h>
27 #include <aros/macros.h>
29 #define SHT_PROGBITS 1
30 #define SHT_SYMTAB 2
31 #define SHT_STRTAB 3
32 #define SHT_RELA 4
33 #define SHT_NOBITS 8
34 #define SHT_REL 9
35 #define SHT_SYMTAB_SHNDX 18
37 #define ET_REL 1
39 #define EM_386 3
40 #define EM_68K 4
41 #define EM_PPC 20
42 #define EM_ARM 40
43 #define EM_X86_64 62 /* AMD x86-64 */
45 #define R_386_NONE 0
46 #define R_386_32 1
47 #define R_386_PC32 2
49 /* AMD x86-64 relocations. */
50 #define R_X86_64_NONE 0 /* No reloc */
51 #define R_X86_64_64 1 /* Direct 64 bit */
52 #define R_X86_64_PC32 2 /* PC relative 32 bit signed */
54 #define R_68k_NONE 0
55 #define R_68K_32 1
56 #define R_68K_PC32 4
58 #define R_PPC_NONE 0
59 #define R_PPC_ADDR32 1
60 #define R_PPC_ADDR16_LO 4
61 #define R_PPC_ADDR16_HA 6
62 #define R_PPC_REL24 10
63 #define R_PPC_REL32 26
64 #define R_PPC_REL16_LO 250
65 #define R_PPC_REL16_HA 252
67 #define R_ARM_NONE 0
68 #define R_ARM_PC24 1
69 #define R_ARM_ABS32 2
71 #define STT_OBJECT 1
72 #define STT_FUNC 2
74 #define SHN_UNDEF 0
75 #define SHN_LORESERVE 0xff00
76 #define SHN_ABS 0xfff1
77 #define SHN_COMMON 0xfff2
78 #define SHN_XINDEX 0xffff
79 #define SHN_HIRESERVE 0xffff
81 #define SHF_ALLOC (1 << 1)
82 #define SHF_EXECINSTR (1 << 2)
84 #define ELF32_ST_TYPE(i) ((i) & 0x0F)
86 #define EI_VERSION 6
87 #define EV_CURRENT 1
89 #define EI_DATA 5
90 #define ELFDATA2LSB 1
91 #define ELFDATA2MSB 2
93 #define EI_CLASS 4
94 #define ELFCLASS32 1
95 #define ELFCLASS64 2 /* 64-bit objects */
97 #define ELF32_R_SYM(val) ((val) >> 8)
98 #define ELF32_R_TYPE(val) ((val) & 0xff)
99 #define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
102 struct elfheader
104 UBYTE ident[16];
105 UWORD type;
106 UWORD machine;
107 ULONG version;
108 APTR entry;
109 ULONG phoff;
110 ULONG shoff;
111 ULONG flags;
112 UWORD ehsize;
113 UWORD phentsize;
114 UWORD phnum;
115 UWORD shentsize;
116 UWORD shnum;
117 UWORD shstrndx;
119 /* these are internal, and not part of the header proper. they are wider
120 * versions of shnum and shstrndx for when they don't fit in the header
121 * and we need to get them from the first section header. see
122 * load_header() for details
124 ULONG int_shnum;
125 ULONG int_shstrndx;
128 struct sheader
130 ULONG name;
131 ULONG type;
132 ULONG flags;
133 APTR addr;
134 ULONG offset;
135 ULONG size;
136 ULONG link;
137 ULONG info;
138 ULONG addralign;
139 ULONG entsize;
142 struct symbol
144 ULONG name; /* Offset of the name string in the string table */
145 ULONG value; /* Varies; eg. the offset of the symbol in its hunk */
146 ULONG size; /* How much memory does the symbol occupy */
147 UBYTE info; /* What kind of symbol is this ? (global, variable, etc) */
148 UBYTE other; /* undefined */
149 UWORD shindex; /* In which section is the symbol defined ? */
152 struct relo
154 ULONG offset; /* Address of the relocation relative to the section it refers to */
155 ULONG info; /* Type of the relocation */
156 #if defined(__mc68000__) || defined (__x86_64__) || defined (__ppc__) || defined (__powerpc__) || defined(__arm__)
157 LONG addend; /* Constant addend used to compute value */
158 #endif
161 struct hunk
163 ULONG size;
164 BPTR next;
165 char data[0];
166 } __attribute__((packed));
168 #define BPTR2HUNK(bptr) ((struct hunk *)((char *)BADDR(bptr) - offsetof(struct hunk, next)))
169 #define HUNK2BPTR(hunk) MKBADDR(&hunk->next)
171 /* convert section header number to array index */
172 #define SHINDEX(n) \
173 ((n) < SHN_LORESERVE ? (n) : ((n) <= SHN_HIRESERVE ? 0 : (n) - (SHN_HIRESERVE + 1 - SHN_LORESERVE)))
175 /* convert section header array index to section number */
176 #define SHNUM(i) \
177 ((i) < SHN_LORESERVE ? (i) : (i) + (SHN_HIRESERVE + 1 - SHN_LORESERVE))
179 #undef MyRead
180 #undef MyAlloc
181 #undef MyFree
184 #define MyRead(file, buf, size) \
185 AROS_CALL3 \
187 LONG, funcarray[0], \
188 AROS_LCA(BPTR, file, D1), \
189 AROS_LCA(void *, buf, D2), \
190 AROS_LCA(LONG, size, D3), \
191 struct DosLibrary *, DOSBase \
195 #define MyAlloc(size, flags) \
196 AROS_CALL2 \
198 void *, funcarray[1], \
199 AROS_LCA(ULONG, size, D0), \
200 AROS_LCA(ULONG, flags, D1), \
201 struct ExecBase *, SysBase \
205 #define MyFree(addr, size) \
206 AROS_CALL2NR \
208 void, funcarray[2], \
209 AROS_LCA(void *, addr, A1), \
210 AROS_LCA(ULONG, size, D0), \
211 struct ExecBase *, SysBase \
214 static int read_block
216 BPTR file,
217 ULONG offset,
218 APTR buffer,
219 ULONG size,
220 SIPTR *funcarray,
221 struct DosLibrary *DOSBase
224 UBYTE *buf = (UBYTE *)buffer;
225 LONG subsize;
227 if (Seek(file, offset, OFFSET_BEGINNING) < 0)
228 return 0;
230 while (size)
232 subsize = MyRead(file, buf, size);
234 if (subsize <= 0)
236 if (subsize == 0)
237 SetIoErr(ERROR_BAD_HUNK);
239 return 0;
242 buf += subsize;
243 size -= subsize;
246 return 1;
249 static void * load_block
251 BPTR file,
252 ULONG offset,
253 ULONG size,
254 SIPTR *funcarray,
255 struct DosLibrary *DOSBase
258 D(bug("[ELF Loader] Load Block\n"));
259 D(bug("[ELF Loader] (size=%d)\n",size));
260 D(bug("[ELF Loader] (funcarray=0x%x)\n",funcarray));
261 D(bug("[ELF Loader] (funcarray[1]=0x%x)\n",funcarray[1]));
262 void *block = MyAlloc(size, MEMF_ANY);
263 if (block)
265 if (read_block(file, offset, block, size, funcarray, DOSBase))
266 return block;
268 MyFree(block, size);
270 else
271 SetIoErr(ERROR_NO_FREE_STORE);
273 return NULL;
276 static int load_header(BPTR file, struct elfheader *eh, SIPTR *funcarray, struct DosLibrary *DOSBase) {
277 if (!read_block(file, 0, eh, offsetof(struct elfheader, int_shnum), funcarray, DOSBase))
278 return 0;
280 if (eh->ident[0] != 0x7f || eh->ident[1] != 'E' ||
281 eh->ident[2] != 'L' || eh->ident[3] != 'F') {
282 D(bug("[ELF Loader] Not an ELF object\n"));
283 SetIoErr(ERROR_NOT_EXECUTABLE);
284 return 0;
286 D(bug("[ELF Loader] ELF object\n"));
288 eh->int_shnum = eh->shnum;
289 eh->int_shstrndx = eh->shstrndx;
291 /* the ELF header only uses 16 bits to store the count of section headers,
292 * so it can't handle more than 65535 headers. if the count is 0, and an
293 * offset is defined, then the real count can be found in the first
294 * section header (which always exists).
296 * similarly, if the string table index is SHN_XINDEX, then the actual
297 * index is found in the first section header also.
299 * see the System V ABI 2001-04-24 draft for more details.
301 if (eh->int_shnum == 0 || eh->int_shstrndx == SHN_XINDEX) {
302 if (eh->shoff == 0) {
303 SetIoErr(ERROR_NOT_EXECUTABLE);
304 return 0;
307 struct sheader sh;
308 if (!read_block(file, eh->shoff, &sh, sizeof(sh), funcarray, DOSBase))
309 return 0;
311 /* wider section header count is in the size field */
312 if (eh->int_shnum == 0)
313 eh->int_shnum = sh.size;
315 /* wider string table index is in the link field */
316 if (eh->int_shstrndx == SHN_XINDEX)
317 eh->int_shstrndx = sh.link;
319 /* sanity, if they're still invalid then this isn't elf */
320 if (eh->int_shnum == 0 || eh->int_shstrndx == SHN_XINDEX) {
321 SetIoErr(ERROR_NOT_EXECUTABLE);
322 return 0;
328 eh->ident[EI_CLASS] != ELFCLASS32 ||
329 eh->ident[EI_VERSION] != EV_CURRENT ||
330 eh->type != ET_REL ||
332 #if defined(__i386__)
333 eh->ident[EI_DATA] != ELFDATA2LSB ||
334 eh->machine != EM_386
336 #elif defined(__x86_64__)
337 eh->ident[EI_DATA] != ELFDATA2LSB ||
338 eh->machine != EM_X86_64
340 #elif defined(__mc68000__)
341 eh->ident[EI_DATA] != ELFDATA2MSB ||
342 eh->machine != EM_68K
344 #elif defined(__ppc__) || defined(__powerpc__)
345 eh->ident[EI_DATA] != ELFDATA2MSB ||
346 eh->machine != EM_PPC
348 #elif defined(__arm__)
349 eh->ident[EI_DATA] != ELFDATA2LSB ||
350 eh->machine != EM_ARM
351 #warning ARM has not been tested, yet!
353 #else
354 # error Your architecture is not supported
355 #endif
358 D(bug("[ELF Loader] Object is of wrong type\n"));
359 #if defined(__x86_64__)
360 D(bug("[ELF Loader] EI_CLASS is %d - should be %d\n", eh->ident[EI_CLASS], ELFCLASS64));
361 #else
362 D(bug("[ELF Loader] EI_CLASS is %d - should be %d\n", eh->ident[EI_CLASS], ELFCLASS32));
363 #endif
364 D(bug("[ELF Loader] EI_VERSION is %d - should be %d\n", eh->ident[EI_VERSION], EV_CURRENT));
365 D(bug("[ELF Loader] type is %d - should be %d\n", eh->type, ET_REL));
366 #if defined (__i386__)
367 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA],ELFDATA2LSB));
368 #elif defined (__mc68000__)
369 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA],ELFDATA2MSB));
370 #elif defined(__ppc__) || defined(__powerpc__)
371 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA],ELFDATA2MSB));
372 #elif defined (__arm__)
373 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA],ELFDATA2MSB));
374 #endif
376 #if defined (__i386__)
377 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine, EM_386));
378 #elif defined(__mc68000__)
379 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine, EM_68K));
380 #elif defined(__ppc__) || defined(__powerpc__)
381 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine, EM_PPC));
382 #elif defined(__arm__)
383 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine, EM_ARM));
384 #endif
386 SetIoErr(ERROR_NOT_EXECUTABLE);
387 return 0;
390 return 1;
393 static int load_hunk
395 BPTR file,
396 BPTR **next_hunk_ptr,
397 struct sheader *sh,
398 SIPTR *funcarray,
399 BOOL do_align,
400 struct DosLibrary *DOSBase
403 struct hunk *hunk;
404 ULONG hunk_size;
406 if (!sh->size)
407 return 1;
409 /* The size of the hunk is the size of the section, plus
410 the size of the hunk structure, plus the size of the alignment (if necessary)*/
411 hunk_size = sh->size + sizeof(struct hunk);
413 if (do_align)
415 hunk_size += sh->addralign;
417 /* Also create space for a trampoline, if necessary */
418 if (sh->flags & SHF_EXECINSTR)
419 hunk_size += sizeof(struct FullJumpVec);
422 hunk = MyAlloc(hunk_size, MEMF_ANY | (sh->type == SHT_NOBITS) ? MEMF_CLEAR : 0);
423 if (hunk)
425 hunk->next = 0;
426 hunk->size = hunk_size;
428 /* In case we are required to honour alignment, and If this section contains
429 executable code, create a trampoline to its beginning, so that even if the
430 alignment requirements make the actual code go much after the end of the
431 hunk structure, the code can still be reached in the usual way. */
432 if (do_align)
434 if (sh->flags & SHF_EXECINSTR)
436 sh->addr = (char *)AROS_ROUNDUP2
438 (ULONG)hunk->data + sizeof(struct FullJumpVec), sh->addralign
440 __AROS_SET_FULLJMP((struct FullJumpVec *)hunk->data, sh->addr);
442 else
443 sh->addr = (char *)AROS_ROUNDUP2((ULONG)hunk->data, sh->addralign);
445 else
446 sh->addr = hunk->data;
448 /* Link the previous one with the new one */
449 BPTR2HUNK(*next_hunk_ptr)->next = HUNK2BPTR(hunk);
451 D(bug("[dos] hunk @ %p\n", sh->addr));
453 /* Update the pointer to the previous one, which is now the current one */
454 *next_hunk_ptr = HUNK2BPTR(hunk);
456 if (sh->type != SHT_NOBITS)
457 return read_block(file, sh->offset, sh->addr, sh->size, funcarray, DOSBase);
459 return 1;
463 SetIoErr(ERROR_NO_FREE_STORE);
465 return 0;
468 static int relocate
470 struct elfheader *eh,
471 struct sheader *sh,
472 ULONG shrel_idx,
473 struct sheader *symtab_shndx,
474 struct DosLibrary *DOSBase
477 struct sheader *shrel = &sh[shrel_idx];
478 struct sheader *shsymtab = &sh[SHINDEX(shrel->link)];
479 struct sheader *toreloc = &sh[SHINDEX(shrel->info)];
481 struct symbol *symtab = (struct symbol *)shsymtab->addr;
482 struct relo *rel = (struct relo *)shrel->addr;
483 char *section = toreloc->addr;
485 /* this happens if the target section has no allocation. that can happen
486 * eg. with a .debug PROGBITS and a .rel.debug section */
487 if (section == NULL)
488 return 1;
490 ULONG numrel = shrel->size / shrel->entsize;
491 ULONG i;
493 struct symbol *SysBase_sym = NULL;
495 for (i=0; i<numrel; i++, rel++)
497 struct symbol *sym = &symtab[ELF32_R_SYM(rel->info)];
498 ULONG *p = (ULONG *)&section[rel->offset];
499 ULONG s;
500 ULONG shindex;
502 if (sym->shindex != SHN_XINDEX)
503 shindex = sym->shindex;
505 else {
506 if (symtab_shndx == NULL) {
507 D(bug("[ELF Loader] got symbol with shndx 0xfff, but there's no symtab shndx table\n"));
508 SetIoErr(ERROR_BAD_HUNK);
509 return 0;
511 shindex = ((ULONG *)symtab_shndx->addr)[ELF32_R_SYM(rel->info)];
514 switch (shindex)
517 case SHN_UNDEF:
518 D(bug("[ELF Loader] Undefined symbol '%s' while relocating the section '%s'\n",
519 (STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name,
520 (STRPTR)sh[SHINDEX(eh->int_shstrndx)].addr + toreloc->name));
521 SetIoErr(ERROR_BAD_HUNK);
522 return 0;
524 case SHN_COMMON:
525 D(bug("[ELF Loader] COMMON symbol '%s' while relocating the section '%s'\n",
526 (STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name,
527 (STRPTR)sh[SHINDEX(eh->int_shstrndx)].addr + toreloc->name));
528 SetIoErr(ERROR_BAD_HUNK);
530 return 0;
532 case SHN_ABS:
533 if (SysBase_sym == NULL)
535 if (strncmp((STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name, "SysBase", 8) == 0)
537 SysBase_sym = sym;
538 goto SysBase_yes;
540 else
541 goto SysBase_no;
543 else
544 if (SysBase_sym == sym)
546 SysBase_yes: s = (ULONG)&SysBase;
548 else
549 SysBase_no: s = sym->value;
550 break;
552 default:
553 s = (ULONG)sh[SHINDEX(shindex)].addr + sym->value;
556 switch (ELF32_R_TYPE(rel->info))
558 #if defined(__i386__)
560 case R_386_32: /* 32bit absolute */
561 *p += s;
562 break;
564 case R_386_PC32: /* 32bit PC relative */
565 *p += s - (ULONG)p;
566 break;
568 case R_386_NONE:
569 break;
571 #elif defined(__x86_64__)
572 /* These weren't tested */
573 case R_X86_64_64: /* 64bit direct/absolute */
574 *p = s + rel->addend;
575 break;
577 case R_X86_64_PC32: /* PC relative 32 bit signed */
578 *p = s + rel->addend - (ULONG)p;
579 break;
581 case R_X86_64_NONE: /* No reloc */
582 break;
584 #elif defined(__mc68000__)
586 case R_68K_32:
587 *p = s + rel->addend;
588 break;
590 case R_68K_PC32:
591 *p = s + rel->addend - (ULONG)p;
592 break;
594 case R_68k_NONE:
595 break;
597 #elif defined(__ppc__) || defined(__powerpc__)
599 case R_PPC_ADDR32:
600 *p = s + rel->addend;
601 break;
603 case R_PPC_ADDR16_LO:
605 unsigned short *c = (unsigned short *) p;
606 *c = (s + rel->addend) & 0xffff;
608 break;
610 case R_PPC_ADDR16_HA:
612 unsigned short *c = (unsigned short *) p;
613 ULONG temp = s + rel->addend;
614 *c = temp >> 16;
615 if ((temp & 0x8000) != 0)
616 (*c)++;
618 break;
620 case R_PPC_REL16_LO:
622 unsigned short *c = (unsigned short *) p;
623 *c = (s + rel->addend - (ULONG) p) & 0xffff;
625 break;
627 case R_PPC_REL16_HA:
629 unsigned short *c = (unsigned short *) p;
630 ULONG temp = s + rel->addend - (ULONG) p;
631 *c = temp >> 16;
632 if ((temp & 0x8000) != 0)
633 (*c)++;
635 break;
637 case R_PPC_REL24:
638 *p &= ~0x3fffffc;
639 *p |= (s + rel->addend - (ULONG) p) & 0x3fffffc;
640 break;
642 case R_PPC_REL32:
643 *p = s + rel->addend - (ULONG) p;
644 break;
646 case R_PPC_NONE:
647 break;
649 #elif defined(__arm__)
652 * This has not been tested. Taken from ARMELF.pdf
653 * from arm.com page 33ff.
655 case R_ARM_PC24:
656 *p = s + rel->addend - (ULONG)p;
657 break;
659 case R_ARM_ABS32:
660 *p = s + rel->addend;
661 break;
663 case R_ARM_NONE:
664 break;
666 #else
667 # error Your architecture is not supported
668 #endif
670 default:
671 D(bug("[ELF Loader] Unrecognized relocation type %d %d\n", i, ELF32_R_TYPE(rel->info)));
672 SetIoErr(ERROR_BAD_HUNK);
673 return 0;
677 return 1;
680 BPTR InternalLoadSeg_ELF
682 BPTR file,
683 BPTR table __unused,
684 SIPTR *funcarray,
685 SIPTR *stack __unused,
686 struct MinList *seginfos,
687 struct DosLibrary *DOSBase
690 struct elfheader eh;
691 struct sheader *sh;
692 struct sheader *symtab_shndx = NULL;
693 BPTR hunks = 0;
694 BPTR *next_hunk_ptr = MKBADDR(&hunks);
695 ULONG i;
696 BOOL exec_hunk_seen = FALSE;
698 /* load and validate ELF header */
699 if (!load_header(file, &eh, funcarray, DOSBase))
700 return 0;
702 /* load section headers */
703 if (!(sh = load_block(file, eh.shoff, eh.int_shnum * eh.shentsize, funcarray, DOSBase)))
704 return 0;
706 /* load the string table */
707 STRPTR st = NULL;
708 struct sheader *shstr = sh + SHINDEX(eh.int_shstrndx);
709 if (shstr->size != 0)
711 st = MyAlloc(shstr->size, MEMF_ANY | MEMF_CLEAR);
712 read_block(file, shstr->offset, st, shstr->size, funcarray, DOSBase);
715 /* Iterate over the section headers in order to do some stuff... */
716 for (i = 0; i < eh.int_shnum; i++)
719 Load the symbol and string table(s).
721 NOTICE: the ELF standard, at the moment (Nov 2002) explicitely states
722 that only one symbol table per file is allowed. However, it
723 also states that this may change in future... we already handle it.
725 if (sh[i].type == SHT_SYMTAB || sh[i].type == SHT_STRTAB || sh[i].type == SHT_SYMTAB_SHNDX)
727 sh[i].addr = load_block(file, sh[i].offset, sh[i].size, funcarray, DOSBase);
728 if (!sh[i].addr)
729 goto error;
731 if (sh[i].type == SHT_SYMTAB_SHNDX) {
732 if (symtab_shndx == NULL)
733 symtab_shndx = &sh[i];
734 else
735 D(bug("[ELF Loader] file contains multiple symtab shndx tables. only using the first one\n"));
738 else
739 /* Load the section in memory if needed, and make an hunk out of it */
740 if (sh[i].flags & SHF_ALLOC)
742 if (sh[i].size)
744 /* Only allow alignment if this is an executable hunk
745 or if an executable hunk has been loaded already,
746 so to avoid the situation in which a data hunk has its
747 content displaced from the hunk's header in case it's the
748 first hunk (this happens with Keymaps, for instance). */
749 if (sh[i].flags & SHF_EXECINSTR)
750 exec_hunk_seen = TRUE;
752 if (!load_hunk(file, &next_hunk_ptr, &sh[i], funcarray, exec_hunk_seen, DOSBase))
753 goto error;
755 if (seginfos)
757 STRPTR name = st + sh[i].name;
758 ULONG size = sizeof(struct seginfo);
759 struct seginfo *si = MyAlloc(size, MEMF_ANY);
761 D(bug("[ELF Loader] seg %s at 0x%x\n", name, sh[i].addr));
763 si->addr = sh[i].addr;
764 size = sizeof(si->name) - 1;
765 strncpy(si->name, name, size);
766 si->name[size] = '\0';
768 ADDTAIL(seginfos, &si->node);
775 /* Relocate the sections */
776 for (i = 0; i < eh.int_shnum; i++)
780 #if defined(__i386__)
782 sh[i].type == SHT_REL &&
784 #elif defined(__x86_64__)
786 sh[i].type == SHT_RELA &&
788 #elif defined(__mc68000__)
790 sh[i].type == SHT_RELA &&
792 #elif defined(__ppc__) || defined(__powerpc__)
794 sh[i].type == SHT_RELA &&
796 #elif defined(__arm__)
797 #warning Missing code for ARM
798 // sh[i].type = SHT_
800 #else
801 # error Your architecture is not supported
802 #endif
804 /* Does this relocation section refer to a hunk? If so, addr must be != 0 */
805 sh[SHINDEX(sh[i].info)].addr
808 sh[i].addr = load_block(file, sh[i].offset, sh[i].size, funcarray, DOSBase);
809 if (!sh[i].addr || !relocate(&eh, sh, i, symtab_shndx, DOSBase))
810 goto error;
812 MyFree(sh[i].addr, sh[i].size);
813 sh[i].addr = NULL;
818 goto end;
820 error:
822 /* There were some errors, deallocate The hunks */
824 InternalUnLoadSeg(hunks, (VOID_FUNC)funcarray[2]);
825 hunks = 0;
827 end:
829 /* Clear the caches to let the CPU see the new data and instructions */
831 BPTR curr = hunks;
832 while (curr)
834 struct hunk *hunk = BPTR2HUNK(curr);
836 CacheClearE(hunk->data, hunk->size, CACRF_ClearD | CACRF_ClearI);
838 curr = hunk->next;
842 /* deallocate the symbol tables */
843 for (i = 0; i < eh.int_shnum; i++)
845 if (((sh[i].type == SHT_SYMTAB) || (sh[i].type == SHT_STRTAB)) && (sh[i].addr != NULL))
846 MyFree(sh[i].addr, sh[i].size);
849 /* Free the string table */
850 MyFree(st, shstr->size);
852 /* Free the section headers */
853 MyFree(sh, eh.int_shnum * eh.shentsize);
855 return hunks;
858 #undef MyRead1
859 #undef MyAlloc
860 #undef MyFree