added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / rom / dos / internalloadseg_elf.c
blobfa7c2220712174ac31f7483c655b8a90c30c29dd
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 /* Update the pointer to the previous one, which is now the current one */
452 *next_hunk_ptr = HUNK2BPTR(hunk);
454 if (sh->type != SHT_NOBITS)
455 return read_block(file, sh->offset, sh->addr, sh->size, funcarray, DOSBase);
457 return 1;
461 SetIoErr(ERROR_NO_FREE_STORE);
463 return 0;
466 static int relocate
468 struct elfheader *eh,
469 struct sheader *sh,
470 ULONG shrel_idx,
471 struct sheader *symtab_shndx,
472 struct DosLibrary *DOSBase
475 struct sheader *shrel = &sh[shrel_idx];
476 struct sheader *shsymtab = &sh[SHINDEX(shrel->link)];
477 struct sheader *toreloc = &sh[SHINDEX(shrel->info)];
479 struct symbol *symtab = (struct symbol *)shsymtab->addr;
480 struct relo *rel = (struct relo *)shrel->addr;
481 char *section = toreloc->addr;
483 /* this happens if the target section has no allocation. that can happen
484 * eg. with a .debug PROGBITS and a .rel.debug section */
485 if (section == NULL)
486 return 1;
488 ULONG numrel = shrel->size / shrel->entsize;
489 ULONG i;
491 struct symbol *SysBase_sym = NULL;
493 for (i=0; i<numrel; i++, rel++)
495 struct symbol *sym = &symtab[ELF32_R_SYM(rel->info)];
496 ULONG *p = (ULONG *)&section[rel->offset];
497 ULONG s;
498 ULONG shindex;
500 if (sym->shindex != SHN_XINDEX)
501 shindex = sym->shindex;
503 else {
504 if (symtab_shndx == NULL) {
505 D(bug("[ELF Loader] got symbol with shndx 0xfff, but there's no symtab shndx table\n"));
506 SetIoErr(ERROR_BAD_HUNK);
507 return 0;
509 shindex = ((ULONG *)symtab_shndx->addr)[ELF32_R_SYM(rel->info)];
512 switch (shindex)
515 case SHN_UNDEF:
516 D(bug("[ELF Loader] Undefined symbol '%s' while relocating the section '%s'\n",
517 (STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name,
518 (STRPTR)sh[SHINDEX(eh->int_shstrndx)].addr + toreloc->name));
519 SetIoErr(ERROR_BAD_HUNK);
520 return 0;
522 case SHN_COMMON:
523 D(bug("[ELF Loader] COMMON symbol '%s' while relocating the section '%s'\n",
524 (STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name,
525 (STRPTR)sh[SHINDEX(eh->int_shstrndx)].addr + toreloc->name));
526 SetIoErr(ERROR_BAD_HUNK);
528 return 0;
530 case SHN_ABS:
531 if (SysBase_sym == NULL)
533 if (strncmp((STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name, "SysBase", 8) == 0)
535 SysBase_sym = sym;
536 goto SysBase_yes;
538 else
539 goto SysBase_no;
541 else
542 if (SysBase_sym == sym)
544 SysBase_yes: s = (ULONG)&SysBase;
546 else
547 SysBase_no: s = sym->value;
548 break;
550 default:
551 s = (ULONG)sh[SHINDEX(shindex)].addr + sym->value;
554 switch (ELF32_R_TYPE(rel->info))
556 #if defined(__i386__)
558 case R_386_32: /* 32bit absolute */
559 *p += s;
560 break;
562 case R_386_PC32: /* 32bit PC relative */
563 *p += s - (ULONG)p;
564 break;
566 case R_386_NONE:
567 break;
569 #elif defined(__x86_64__)
570 /* These weren't tested */
571 case R_X86_64_64: /* 64bit direct/absolute */
572 *p = s + rel->addend;
573 break;
575 case R_X86_64_PC32: /* PC relative 32 bit signed */
576 *p = s + rel->addend - (ULONG)p;
577 break;
579 case R_X86_64_NONE: /* No reloc */
580 break;
582 #elif defined(__mc68000__)
584 case R_68K_32:
585 *p = s + rel->addend;
586 break;
588 case R_68K_PC32:
589 *p = s + rel->addend - (ULONG)p;
590 break;
592 case R_68k_NONE:
593 break;
595 #elif defined(__ppc__) || defined(__powerpc__)
597 case R_PPC_ADDR32:
598 *p = s + rel->addend;
599 break;
601 case R_PPC_ADDR16_LO:
603 unsigned short *c = (unsigned short *) p;
604 *c = (s + rel->addend) & 0xffff;
606 break;
608 case R_PPC_ADDR16_HA:
610 unsigned short *c = (unsigned short *) p;
611 ULONG temp = s + rel->addend;
612 *c = temp >> 16;
613 if ((temp & 0x8000) != 0)
614 (*c)++;
616 break;
618 case R_PPC_REL16_LO:
620 unsigned short *c = (unsigned short *) p;
621 *c = (s + rel->addend - (ULONG) p) & 0xffff;
623 break;
625 case R_PPC_REL16_HA:
627 unsigned short *c = (unsigned short *) p;
628 ULONG temp = s + rel->addend - (ULONG) p;
629 *c = temp >> 16;
630 if ((temp & 0x8000) != 0)
631 (*c)++;
633 break;
635 case R_PPC_REL24:
636 *p &= ~0x3fffffc;
637 *p |= (s + rel->addend - (ULONG) p) & 0x3fffffc;
638 break;
640 case R_PPC_REL32:
641 *p = s + rel->addend - (ULONG) p;
642 break;
644 case R_PPC_NONE:
645 break;
647 #elif defined(__arm__)
650 * This has not been tested. Taken from ARMELF.pdf
651 * from arm.com page 33ff.
653 case R_ARM_PC24:
654 *p = s + rel->addend - (ULONG)p;
655 break;
657 case R_ARM_ABS32:
658 *p = s + rel->addend;
659 break;
661 case R_ARM_NONE:
662 break;
664 #else
665 # error Your architecture is not supported
666 #endif
668 default:
669 D(bug("[ELF Loader] Unrecognized relocation type %d %d\n", i, ELF32_R_TYPE(rel->info)));
670 SetIoErr(ERROR_BAD_HUNK);
671 return 0;
675 return 1;
678 BPTR InternalLoadSeg_ELF
680 BPTR file,
681 BPTR table __unused,
682 SIPTR *funcarray,
683 SIPTR *stack __unused,
684 struct MinList *seginfos,
685 struct DosLibrary *DOSBase
688 struct elfheader eh;
689 struct sheader *sh;
690 struct sheader *symtab_shndx = NULL;
691 BPTR hunks = 0;
692 BPTR *next_hunk_ptr = MKBADDR(&hunks);
693 ULONG i;
694 BOOL exec_hunk_seen = FALSE;
696 /* load and validate ELF header */
697 if (!load_header(file, &eh, funcarray, DOSBase))
698 return 0;
700 /* load section headers */
701 if (!(sh = load_block(file, eh.shoff, eh.int_shnum * eh.shentsize, funcarray, DOSBase)))
702 return 0;
704 /* load the string table */
705 STRPTR st = NULL;
706 struct sheader *shstr = sh + SHINDEX(eh.int_shstrndx);
707 if (shstr->size != 0)
709 st = MyAlloc(shstr->size, MEMF_ANY | MEMF_CLEAR);
710 read_block(file, shstr->offset, st, shstr->size, funcarray, DOSBase);
713 /* Iterate over the section headers in order to do some stuff... */
714 for (i = 0; i < eh.int_shnum; i++)
717 Load the symbol and string table(s).
719 NOTICE: the ELF standard, at the moment (Nov 2002) explicitely states
720 that only one symbol table per file is allowed. However, it
721 also states that this may change in future... we already handle it.
723 if (sh[i].type == SHT_SYMTAB || sh[i].type == SHT_STRTAB || sh[i].type == SHT_SYMTAB_SHNDX)
725 sh[i].addr = load_block(file, sh[i].offset, sh[i].size, funcarray, DOSBase);
726 if (!sh[i].addr)
727 goto error;
729 if (sh[i].type == SHT_SYMTAB_SHNDX) {
730 if (symtab_shndx == NULL)
731 symtab_shndx = &sh[i];
732 else
733 D(bug("[ELF Loader] file contains multiple symtab shndx tables. only using the first one\n"));
736 else
737 /* Load the section in memory if needed, and make an hunk out of it */
738 if (sh[i].flags & SHF_ALLOC)
740 if (sh[i].size)
742 /* Only allow alignment if this is an executable hunk
743 or if an executable hunk has been loaded already,
744 so to avoid the situation in which a data hunk has its
745 content displaced from the hunk's header in case it's the
746 first hunk (this happens with Keymaps, for instance). */
747 if (sh[i].flags & SHF_EXECINSTR)
748 exec_hunk_seen = TRUE;
750 if (!load_hunk(file, &next_hunk_ptr, &sh[i], funcarray, exec_hunk_seen, DOSBase))
751 goto error;
753 if (seginfos)
755 STRPTR name = st + sh[i].name;
756 ULONG size = sizeof(struct seginfo);
757 struct seginfo *si = MyAlloc(size, MEMF_ANY);
759 D(bug("[ELF Loader] seg %s at 0x%x\n", name, sh[i].addr));
761 si->addr = sh[i].addr;
762 size = sizeof(si->name) - 1;
763 strncpy(si->name, name, size);
764 si->name[size] = '\0';
766 ADDTAIL(seginfos, &si->node);
773 /* Relocate the sections */
774 for (i = 0; i < eh.int_shnum; i++)
778 #if defined(__i386__)
780 sh[i].type == SHT_REL &&
782 #elif defined(__x86_64__)
784 sh[i].type == SHT_RELA &&
786 #elif defined(__mc68000__)
788 sh[i].type == SHT_RELA &&
790 #elif defined(__ppc__) || defined(__powerpc__)
792 sh[i].type == SHT_RELA &&
794 #elif defined(__arm__)
795 #warning Missing code for ARM
796 // sh[i].type = SHT_
798 #else
799 # error Your architecture is not supported
800 #endif
802 /* Does this relocation section refer to a hunk? If so, addr must be != 0 */
803 sh[SHINDEX(sh[i].info)].addr
806 sh[i].addr = load_block(file, sh[i].offset, sh[i].size, funcarray, DOSBase);
807 if (!sh[i].addr || !relocate(&eh, sh, i, symtab_shndx, DOSBase))
808 goto error;
810 MyFree(sh[i].addr, sh[i].size);
811 sh[i].addr = NULL;
816 goto end;
818 error:
820 /* There were some errors, deallocate The hunks */
822 InternalUnLoadSeg(hunks, (VOID_FUNC)funcarray[2]);
823 hunks = 0;
825 end:
827 /* Clear the caches to let the CPU see the new data and instructions */
829 BPTR curr = hunks;
830 while (curr)
832 struct hunk *hunk = BPTR2HUNK(curr);
834 CacheClearE(hunk->data, hunk->size, CACRF_ClearD | CACRF_ClearI);
836 curr = hunk->next;
840 /* deallocate the symbol tables */
841 for (i = 0; i < eh.int_shnum; i++)
843 if (((sh[i].type == SHT_SYMTAB) || (sh[i].type == SHT_STRTAB)) && (sh[i].addr != NULL))
844 MyFree(sh[i].addr, sh[i].size);
847 /* Free the string table */
848 MyFree(st, shstr->size);
850 /* Free the section headers */
851 MyFree(sh, eh.int_shnum * eh.shentsize);
853 return hunks;
856 #undef MyRead1
857 #undef MyAlloc
858 #undef MyFree