detect and setup mingw32 environment (patch from Carlo Bramini)
[tangerine.git] / rom / dos / internalloadseg_elf.c
blobe856061a63c96e1a7516cefd934bd0c662a8013c
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
65 #define R_ARM_NONE 0
66 #define R_ARM_PC24 1
67 #define R_ARM_ABS32 2
69 #define STT_OBJECT 1
70 #define STT_FUNC 2
72 #define SHN_UNDEF 0
73 #define SHN_LORESERVE 0xff00
74 #define SHN_ABS 0xfff1
75 #define SHN_COMMON 0xfff2
76 #define SHN_XINDEX 0xffff
77 #define SHN_HIRESERVE 0xffff
79 #define SHF_ALLOC (1 << 1)
80 #define SHF_EXECINSTR (1 << 2)
82 #define ELF32_ST_TYPE(i) ((i) & 0x0F)
84 #define EI_VERSION 6
85 #define EV_CURRENT 1
87 #define EI_DATA 5
88 #define ELFDATA2LSB 1
89 #define ELFDATA2MSB 2
91 #define EI_CLASS 4
92 #define ELFCLASS32 1
93 #define ELFCLASS64 2 /* 64-bit objects */
95 #define ELF32_R_SYM(val) ((val) >> 8)
96 #define ELF32_R_TYPE(val) ((val) & 0xff)
97 #define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
100 struct elfheader
102 UBYTE ident[16];
103 UWORD type;
104 UWORD machine;
105 ULONG version;
106 APTR entry;
107 ULONG phoff;
108 ULONG shoff;
109 ULONG flags;
110 UWORD ehsize;
111 UWORD phentsize;
112 UWORD phnum;
113 UWORD shentsize;
114 UWORD shnum;
115 UWORD shstrndx;
117 /* these are internal, and not part of the header proper. they are wider
118 * versions of shnum and shstrndx for when they don't fit in the header
119 * and we need to get them from the first section header. see
120 * load_header() for details
122 ULONG int_shnum;
123 ULONG int_shstrndx;
126 struct sheader
128 ULONG name;
129 ULONG type;
130 ULONG flags;
131 APTR addr;
132 ULONG offset;
133 ULONG size;
134 ULONG link;
135 ULONG info;
136 ULONG addralign;
137 ULONG entsize;
140 struct symbol
142 ULONG name; /* Offset of the name string in the string table */
143 ULONG value; /* Varies; eg. the offset of the symbol in its hunk */
144 ULONG size; /* How much memory does the symbol occupy */
145 UBYTE info; /* What kind of symbol is this ? (global, variable, etc) */
146 UBYTE other; /* undefined */
147 UWORD shindex; /* In which section is the symbol defined ? */
150 struct relo
152 ULONG offset; /* Address of the relocation relative to the section it refers to */
153 ULONG info; /* Type of the relocation */
154 #if defined(__mc68000__) || defined (__x86_64__) || defined (__ppc__) || defined (__powerpc__) || defined(__arm__)
155 LONG addend; /* Constant addend used to compute value */
156 #endif
159 struct hunk
161 ULONG size;
162 BPTR next;
163 char data[0];
164 } __attribute__((packed));
166 #define BPTR2HUNK(bptr) ((struct hunk *)((char *)BADDR(bptr) - offsetof(struct hunk, next)))
167 #define HUNK2BPTR(hunk) MKBADDR(&hunk->next)
169 /* convert section header number to array index */
170 #define SHINDEX(n) \
171 ((n) < SHN_LORESERVE ? (n) : ((n) <= SHN_HIRESERVE ? 0 : (n) - (SHN_HIRESERVE + 1 - SHN_LORESERVE)))
173 /* convert section header array index to section number */
174 #define SHNUM(i) \
175 ((i) < SHN_LORESERVE ? (i) : (i) + (SHN_HIRESERVE + 1 - SHN_LORESERVE))
177 #undef MyRead
178 #undef MyAlloc
179 #undef MyFree
182 #define MyRead(file, buf, size) \
183 AROS_CALL3 \
185 LONG, funcarray[0], \
186 AROS_LCA(BPTR, file, D1), \
187 AROS_LCA(void *, buf, D2), \
188 AROS_LCA(LONG, size, D3), \
189 struct DosLibrary *, DOSBase \
193 #define MyAlloc(size, flags) \
194 AROS_CALL2 \
196 void *, funcarray[1], \
197 AROS_LCA(ULONG, size, D0), \
198 AROS_LCA(ULONG, flags, D1), \
199 struct ExecBase *, SysBase \
203 #define MyFree(addr, size) \
204 AROS_CALL2NR \
206 void, funcarray[2], \
207 AROS_LCA(void *, addr, A1), \
208 AROS_LCA(ULONG, size, D0), \
209 struct ExecBase *, SysBase \
212 static int read_block
214 BPTR file,
215 ULONG offset,
216 APTR buffer,
217 ULONG size,
218 SIPTR *funcarray,
219 struct DosLibrary *DOSBase
222 UBYTE *buf = (UBYTE *)buffer;
223 LONG subsize;
225 if (Seek(file, offset, OFFSET_BEGINNING) < 0)
226 return 0;
228 while (size)
230 subsize = MyRead(file, buf, size);
232 if (subsize <= 0)
234 if (subsize == 0)
235 SetIoErr(ERROR_BAD_HUNK);
237 return 0;
240 buf += subsize;
241 size -= subsize;
244 return 1;
247 static void * load_block
249 BPTR file,
250 ULONG offset,
251 ULONG size,
252 SIPTR *funcarray,
253 struct DosLibrary *DOSBase
256 D(bug("[ELF Loader] Load Block\n"));
257 D(bug("[ELF Loader] (size=%d)\n",size));
258 D(bug("[ELF Loader] (funcarray=0x%x)\n",funcarray));
259 D(bug("[ELF Loader] (funcarray[1]=0x%x)\n",funcarray[1]));
260 void *block = MyAlloc(size, MEMF_ANY);
261 if (block)
263 if (read_block(file, offset, block, size, funcarray, DOSBase))
264 return block;
266 MyFree(block, size);
268 else
269 SetIoErr(ERROR_NO_FREE_STORE);
271 return NULL;
274 static int load_header(BPTR file, struct elfheader *eh, SIPTR *funcarray, struct DosLibrary *DOSBase) {
275 if (!read_block(file, 0, eh, offsetof(struct elfheader, int_shnum), funcarray, DOSBase))
276 return 0;
278 if (eh->ident[0] != 0x7f || eh->ident[1] != 'E' ||
279 eh->ident[2] != 'L' || eh->ident[3] != 'F') {
280 D(bug("[ELF Loader] Not an ELF object\n"));
281 SetIoErr(ERROR_NOT_EXECUTABLE);
282 return 0;
284 D(bug("[ELF Loader] ELF object\n"));
286 eh->int_shnum = eh->shnum;
287 eh->int_shstrndx = eh->shstrndx;
289 /* the ELF header only uses 16 bits to store the count of section headers,
290 * so it can't handle more than 65535 headers. if the count is 0, and an
291 * offset is defined, then the real count can be found in the first
292 * section header (which always exists).
294 * similarly, if the string table index is SHN_XINDEX, then the actual
295 * index is found in the first section header also.
297 * see the System V ABI 2001-04-24 draft for more details.
299 if (eh->int_shnum == 0 || eh->int_shstrndx == SHN_XINDEX) {
300 if (eh->shoff == 0) {
301 SetIoErr(ERROR_NOT_EXECUTABLE);
302 return 0;
305 struct sheader sh;
306 if (!read_block(file, eh->shoff, &sh, sizeof(sh), funcarray, DOSBase))
307 return 0;
309 /* wider section header count is in the size field */
310 if (eh->int_shnum == 0)
311 eh->int_shnum = sh.size;
313 /* wider string table index is in the link field */
314 if (eh->int_shstrndx == SHN_XINDEX)
315 eh->int_shstrndx = sh.link;
317 /* sanity, if they're still invalid then this isn't elf */
318 if (eh->int_shnum == 0 || eh->int_shstrndx == SHN_XINDEX) {
319 SetIoErr(ERROR_NOT_EXECUTABLE);
320 return 0;
326 eh->ident[EI_CLASS] != ELFCLASS32 ||
327 eh->ident[EI_VERSION] != EV_CURRENT ||
328 eh->type != ET_REL ||
330 #if defined(__i386__)
331 eh->ident[EI_DATA] != ELFDATA2LSB ||
332 eh->machine != EM_386
334 #elif defined(__x86_64__)
335 eh->ident[EI_DATA] != ELFDATA2LSB ||
336 eh->machine != EM_X86_64
338 #elif defined(__mc68000__)
339 eh->ident[EI_DATA] != ELFDATA2MSB ||
340 eh->machine != EM_68K
342 #elif defined(__ppc__) || defined(__powerpc__)
343 eh->ident[EI_DATA] != ELFDATA2MSB ||
344 eh->machine != EM_PPC
346 #elif defined(__arm__)
347 eh->ident[EI_DATA] != ELFDATA2LSB ||
348 eh->machine != EM_ARM
349 #warning ARM has not been tested, yet!
351 #else
352 # error Your architecture is not supported
353 #endif
356 D(bug("[ELF Loader] Object is of wrong type\n"));
357 #if defined(__x86_64__)
358 D(bug("[ELF Loader] EI_CLASS is %d - should be %d\n", eh->ident[EI_CLASS], ELFCLASS64));
359 #else
360 D(bug("[ELF Loader] EI_CLASS is %d - should be %d\n", eh->ident[EI_CLASS], ELFCLASS32));
361 #endif
362 D(bug("[ELF Loader] EI_VERSION is %d - should be %d\n", eh->ident[EI_VERSION], EV_CURRENT));
363 D(bug("[ELF Loader] type is %d - should be %d\n", eh->type, ET_REL));
364 #if defined (__i386__)
365 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA],ELFDATA2LSB));
366 #elif defined (__mc68000__)
367 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA],ELFDATA2MSB));
368 #elif defined(__ppc__) || defined(__powerpc__)
369 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA],ELFDATA2MSB));
370 #elif defined (__arm__)
371 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA],ELFDATA2MSB));
372 #endif
374 #if defined (__i386__)
375 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine, EM_386));
376 #elif defined(__mc68000__)
377 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine, EM_68K));
378 #elif defined(__ppc__) || defined(__powerpc__)
379 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine, EM_PPC));
380 #elif defined(__arm__)
381 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine, EM_ARM));
382 #endif
384 SetIoErr(ERROR_NOT_EXECUTABLE);
385 return 0;
388 return 1;
391 static int load_hunk
393 BPTR file,
394 BPTR **next_hunk_ptr,
395 struct sheader *sh,
396 SIPTR *funcarray,
397 BOOL do_align,
398 struct DosLibrary *DOSBase
401 struct hunk *hunk;
402 ULONG hunk_size;
404 if (!sh->size)
405 return 1;
407 /* The size of the hunk is the size of the section, plus
408 the size of the hunk structure, plus the size of the alignment (if necessary)*/
409 hunk_size = sh->size + sizeof(struct hunk);
411 if (do_align)
413 hunk_size += sh->addralign;
415 /* Also create space for a trampoline, if necessary */
416 if (sh->flags & SHF_EXECINSTR)
417 hunk_size += sizeof(struct FullJumpVec);
420 hunk = MyAlloc(hunk_size, MEMF_ANY | (sh->type == SHT_NOBITS) ? MEMF_CLEAR : 0);
421 if (hunk)
423 hunk->next = 0;
424 hunk->size = hunk_size;
426 /* In case we are required to honour alignment, and If this section contains
427 executable code, create a trampoline to its beginning, so that even if the
428 alignment requirements make the actual code go much after the end of the
429 hunk structure, the code can still be reached in the usual way. */
430 if (do_align)
432 if (sh->flags & SHF_EXECINSTR)
434 sh->addr = (char *)AROS_ROUNDUP2
436 (ULONG)hunk->data + sizeof(struct FullJumpVec), sh->addralign
438 __AROS_SET_FULLJMP((struct FullJumpVec *)hunk->data, sh->addr);
440 else
441 sh->addr = (char *)AROS_ROUNDUP2((ULONG)hunk->data, sh->addralign);
443 else
444 sh->addr = hunk->data;
446 /* Link the previous one with the new one */
447 BPTR2HUNK(*next_hunk_ptr)->next = HUNK2BPTR(hunk);
449 /* Update the pointer to the previous one, which is now the current one */
450 *next_hunk_ptr = HUNK2BPTR(hunk);
452 if (sh->type != SHT_NOBITS)
453 return read_block(file, sh->offset, sh->addr, sh->size, funcarray, DOSBase);
455 return 1;
459 SetIoErr(ERROR_NO_FREE_STORE);
461 return 0;
464 static int relocate
466 struct elfheader *eh,
467 struct sheader *sh,
468 ULONG shrel_idx,
469 struct sheader *symtab_shndx,
470 struct DosLibrary *DOSBase
473 struct sheader *shrel = &sh[shrel_idx];
474 struct sheader *shsymtab = &sh[SHINDEX(shrel->link)];
475 struct sheader *toreloc = &sh[SHINDEX(shrel->info)];
477 struct symbol *symtab = (struct symbol *)shsymtab->addr;
478 struct relo *rel = (struct relo *)shrel->addr;
479 char *section = toreloc->addr;
481 /* this happens if the target section has no allocation. that can happen
482 * eg. with a .debug PROGBITS and a .rel.debug section */
483 if (section == NULL)
484 return 1;
486 ULONG numrel = shrel->size / shrel->entsize;
487 ULONG i;
489 struct symbol *SysBase_sym = NULL;
491 for (i=0; i<numrel; i++, rel++)
493 struct symbol *sym = &symtab[ELF32_R_SYM(rel->info)];
494 ULONG *p = (ULONG *)&section[rel->offset];
495 ULONG s;
496 ULONG shindex;
498 if (sym->shindex != SHN_XINDEX)
499 shindex = sym->shindex;
501 else {
502 if (symtab_shndx == NULL) {
503 D(bug("[ELF Loader] got symbol with shndx 0xfff, but there's no symtab shndx table\n"));
504 SetIoErr(ERROR_BAD_HUNK);
505 return 0;
507 shindex = ((ULONG *)symtab_shndx->addr)[ELF32_R_SYM(rel->info)];
510 switch (shindex)
513 case SHN_UNDEF:
514 D(bug("[ELF Loader] Undefined symbol '%s' while relocating the section '%s'\n",
515 (STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name,
516 (STRPTR)sh[SHINDEX(eh->int_shstrndx)].addr + toreloc->name));
517 SetIoErr(ERROR_BAD_HUNK);
518 return 0;
520 case SHN_COMMON:
521 D(bug("[ELF Loader] COMMON symbol '%s' while relocating the section '%s'\n",
522 (STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name,
523 (STRPTR)sh[SHINDEX(eh->int_shstrndx)].addr + toreloc->name));
524 SetIoErr(ERROR_BAD_HUNK);
526 return 0;
528 case SHN_ABS:
529 if (SysBase_sym == NULL)
531 if (strncmp((STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name, "SysBase", 8) == 0)
533 SysBase_sym = sym;
534 goto SysBase_yes;
536 else
537 goto SysBase_no;
539 else
540 if (SysBase_sym == sym)
542 SysBase_yes: s = (ULONG)&SysBase;
544 else
545 SysBase_no: s = sym->value;
546 break;
548 default:
549 s = (ULONG)sh[SHINDEX(shindex)].addr + sym->value;
552 switch (ELF32_R_TYPE(rel->info))
554 #if defined(__i386__)
556 case R_386_32: /* 32bit absolute */
557 *p += s;
558 break;
560 case R_386_PC32: /* 32bit PC relative */
561 *p += s - (ULONG)p;
562 break;
564 case R_386_NONE:
565 break;
567 #elif defined(__x86_64__)
568 /* These weren't tested */
569 case R_X86_64_64: /* 64bit direct/absolute */
570 *p = s + rel->addend;
571 break;
573 case R_X86_64_PC32: /* PC relative 32 bit signed */
574 *p = s + rel->addend - (ULONG)p;
575 break;
577 case R_X86_64_NONE: /* No reloc */
578 break;
580 #elif defined(__mc68000__)
582 case R_68K_32:
583 *p = s + rel->addend;
584 break;
586 case R_68K_PC32:
587 *p = s + rel->addend - (ULONG)p;
588 break;
590 case R_68k_NONE:
591 break;
593 #elif defined(__ppc__) || defined(__powerpc__)
595 case R_PPC_ADDR32:
596 *p = s + rel->addend;
597 break;
599 case R_PPC_ADDR16_LO:
601 unsigned short *c = (unsigned short *) p;
602 *c = (s + rel->addend) & 0xffff;
604 break;
606 case R_PPC_ADDR16_HA:
608 unsigned short *c = (unsigned short *) p;
609 ULONG temp = s + rel->addend;
610 *c = temp >> 16;
611 if ((temp & 0x8000) != 0)
612 (*c)++;
614 break;
616 case R_PPC_REL24:
617 *p &= ~0x3fffffc;
618 *p |= (s + rel->addend - (ULONG) p) & 0x3fffffc;
619 break;
621 case R_PPC_REL32:
622 *p = s + rel->addend - (ULONG) p;
623 break;
625 case R_PPC_NONE:
626 break;
628 #elif defined(__arm__)
631 * This has not been tested. Taken from ARMELF.pdf
632 * from arm.com page 33ff.
634 case R_ARM_PC24:
635 *p = s + rel->addend - (ULONG)p;
636 break;
638 case R_ARM_ABS32:
639 *p = s + rel->addend;
640 break;
642 case R_ARM_NONE:
643 break;
645 #else
646 # error Your architecture is not supported
647 #endif
649 default:
650 D(bug("[ELF Loader] Unrecognized relocation type %d %d\n", i, ELF32_R_TYPE(rel->info)));
651 SetIoErr(ERROR_BAD_HUNK);
652 return 0;
656 return 1;
659 BPTR InternalLoadSeg_ELF
661 BPTR file,
662 BPTR table __unused,
663 SIPTR *funcarray,
664 SIPTR *stack __unused,
665 struct MinList *seginfos,
666 struct DosLibrary *DOSBase
669 struct elfheader eh;
670 struct sheader *sh;
671 struct sheader *symtab_shndx = NULL;
672 BPTR hunks = 0;
673 BPTR *next_hunk_ptr = MKBADDR(&hunks);
674 ULONG i;
675 BOOL exec_hunk_seen = FALSE;
677 /* load and validate ELF header */
678 if (!load_header(file, &eh, funcarray, DOSBase))
679 return 0;
681 /* load section headers */
682 if (!(sh = load_block(file, eh.shoff, eh.int_shnum * eh.shentsize, funcarray, DOSBase)))
683 return 0;
685 /* load the string table */
686 STRPTR st = NULL;
687 struct sheader *shstr = sh + SHINDEX(eh.int_shstrndx);
688 if (shstr->size != 0)
690 st = MyAlloc(shstr->size, MEMF_ANY | MEMF_CLEAR);
691 read_block(file, shstr->offset, st, shstr->size, funcarray, DOSBase);
694 /* Iterate over the section headers in order to do some stuff... */
695 for (i = 0; i < eh.int_shnum; i++)
698 Load the symbol and string table(s).
700 NOTICE: the ELF standard, at the moment (Nov 2002) explicitely states
701 that only one symbol table per file is allowed. However, it
702 also states that this may change in future... we already handle it.
704 if (sh[i].type == SHT_SYMTAB || sh[i].type == SHT_STRTAB || sh[i].type == SHT_SYMTAB_SHNDX)
706 sh[i].addr = load_block(file, sh[i].offset, sh[i].size, funcarray, DOSBase);
707 if (!sh[i].addr)
708 goto error;
710 if (sh[i].type == SHT_SYMTAB_SHNDX) {
711 if (symtab_shndx == NULL)
712 symtab_shndx = &sh[i];
713 else
714 D(bug("[ELF Loader] file contains multiple symtab shndx tables. only using the first one\n"));
717 else
718 /* Load the section in memory if needed, and make an hunk out of it */
719 if (sh[i].flags & SHF_ALLOC)
721 if (sh[i].size)
723 /* Only allow alignment if this is an executable hunk
724 or if an executable hunk has been loaded already,
725 so to avoid the situation in which a data hunk has its
726 content displaced from the hunk's header in case it's the
727 first hunk (this happens with Keymaps, for instance). */
728 if (sh[i].flags & SHF_EXECINSTR)
729 exec_hunk_seen = TRUE;
731 if (!load_hunk(file, &next_hunk_ptr, &sh[i], funcarray, exec_hunk_seen, DOSBase))
732 goto error;
734 if (seginfos)
736 STRPTR name = st + sh[i].name;
737 ULONG size = sizeof(struct seginfo);
738 struct seginfo *si = MyAlloc(size, MEMF_ANY);
740 D(bug("[ELF Loader] seg %s at 0x%x\n", name, sh[i].addr));
742 si->addr = sh[i].addr;
743 size = sizeof(si->name) - 1;
744 strncpy(si->name, name, size);
745 si->name[size] = '\0';
747 ADDTAIL(seginfos, &si->node);
754 /* Relocate the sections */
755 for (i = 0; i < eh.int_shnum; i++)
759 #if defined(__i386__)
761 sh[i].type == SHT_REL &&
763 #elif defined(__x86_64__)
765 sh[i].type == SHT_RELA &&
767 #elif defined(__mc68000__)
769 sh[i].type == SHT_RELA &&
771 #elif defined(__ppc__) || defined(__powerpc__)
773 sh[i].type == SHT_RELA &&
775 #elif defined(__arm__)
776 #warning Missing code for ARM
777 // sh[i].type = SHT_
779 #else
780 # error Your architecture is not supported
781 #endif
783 /* Does this relocation section refer to a hunk? If so, addr must be != 0 */
784 sh[SHINDEX(sh[i].info)].addr
787 sh[i].addr = load_block(file, sh[i].offset, sh[i].size, funcarray, DOSBase);
788 if (!sh[i].addr || !relocate(&eh, sh, i, symtab_shndx, DOSBase))
789 goto error;
791 MyFree(sh[i].addr, sh[i].size);
792 sh[i].addr = NULL;
797 goto end;
799 error:
801 /* There were some errors, deallocate The hunks */
803 InternalUnLoadSeg(hunks, (VOID_FUNC)funcarray[2]);
804 hunks = 0;
806 end:
808 /* Clear the caches to let the CPU see the new data and instructions */
810 BPTR curr = hunks;
811 while (curr)
813 struct hunk *hunk = BPTR2HUNK(curr);
815 CacheClearE(hunk->data, hunk->size, CACRF_ClearD | CACRF_ClearI);
817 curr = hunk->next;
821 /* deallocate the symbol tables */
822 for (i = 0; i < eh.int_shnum; i++)
824 if (((sh[i].type == SHT_SYMTAB) || (sh[i].type == SHT_STRTAB)) && (sh[i].addr != NULL))
825 MyFree(sh[i].addr, sh[i].size);
828 /* Free the string table */
829 MyFree(st, shstr->size);
831 /* Free the section headers */
832 MyFree(sh, eh.int_shnum * eh.shentsize);
834 return hunks;
837 #undef MyRead1
838 #undef MyAlloc
839 #undef MyFree