Updated PCI IDs to latest snapshot.
[tangerine.git] / arch / ppc-chrp / dos / internalloadseg_elf.c
blob60f31044f69e191da016960b29fcaf8eee156e26
1 /*
2 Copyright � 1995-2007, The AROS Development Team. All rights reserved.
3 $Id: internalloadseg_elf.c 28685 2008-05-12 19:42:21Z schulz $
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 <proto/kernel.h>
20 #include <aros/asmcall.h>
21 #include "internalloadseg.h"
22 #include "dos_intern.h"
24 #include <aros/debug.h>
25 #include <string.h>
26 #include <stddef.h>
28 #include <aros/macros.h>
30 #define SHT_PROGBITS 1
31 #define SHT_SYMTAB 2
32 #define SHT_STRTAB 3
33 #define SHT_RELA 4
34 #define SHT_NOBITS 8
35 #define SHT_REL 9
36 #define SHT_SYMTAB_SHNDX 18
38 #define ET_REL 1
40 #define EM_386 3
41 #define EM_68K 4
42 #define EM_PPC 20
43 #define EM_ARM 40
44 #define EM_X86_64 62 /* AMD x86-64 */
46 #define R_386_NONE 0
47 #define R_386_32 1
48 #define R_386_PC32 2
50 /* AMD x86-64 relocations. */
51 #define R_X86_64_NONE 0 /* No reloc */
52 #define R_X86_64_64 1 /* Direct 64 bit */
53 #define R_X86_64_PC32 2 /* PC relative 32 bit signed */
55 #define R_68k_NONE 0
56 #define R_68K_32 1
57 #define R_68K_PC32 4
59 #define R_PPC_NONE 0
60 #define R_PPC_ADDR32 1
61 #define R_PPC_ADDR16_LO 4
62 #define R_PPC_ADDR16_HA 6
63 #define R_PPC_REL24 10
64 #define R_PPC_REL32 26
65 #define R_PPC_REL16_LO 250
66 #define R_PPC_REL16_HA 252
68 #define R_ARM_NONE 0
69 #define R_ARM_PC24 1
70 #define R_ARM_ABS32 2
72 #define STT_OBJECT 1
73 #define STT_FUNC 2
75 #define SHN_UNDEF 0
76 #define SHN_LORESERVE 0xff00
77 #define SHN_ABS 0xfff1
78 #define SHN_COMMON 0xfff2
79 #define SHN_XINDEX 0xffff
80 #define SHN_HIRESERVE 0xffff
82 #define SHF_ALLOC (1 << 1)
83 #define SHF_EXECINSTR (1 << 2)
85 #define ELF32_ST_TYPE(i) ((i) & 0x0F)
87 #define EI_VERSION 6
88 #define EV_CURRENT 1
90 #define EI_DATA 5
91 #define ELFDATA2LSB 1
92 #define ELFDATA2MSB 2
94 #define EI_CLASS 4
95 #define ELFCLASS32 1
96 #define ELFCLASS64 2 /* 64-bit objects */
98 #define ELF32_R_SYM(val) ((val) >> 8)
99 #define ELF32_R_TYPE(val) ((val) & 0xff)
100 #define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
103 struct elfheader
105 UBYTE ident[16];
106 UWORD type;
107 UWORD machine;
108 ULONG version;
109 APTR entry;
110 ULONG phoff;
111 ULONG shoff;
112 ULONG flags;
113 UWORD ehsize;
114 UWORD phentsize;
115 UWORD phnum;
116 UWORD shentsize;
117 UWORD shnum;
118 UWORD shstrndx;
120 /* these are internal, and not part of the header proper. they are wider
121 * versions of shnum and shstrndx for when they don't fit in the header
122 * and we need to get them from the first section header. see
123 * load_header() for details
125 ULONG int_shnum;
126 ULONG int_shstrndx;
129 struct sheader
131 ULONG name;
132 ULONG type;
133 ULONG flags;
134 APTR addr;
135 ULONG offset;
136 ULONG size;
137 ULONG link;
138 ULONG info;
139 ULONG addralign;
140 ULONG entsize;
143 struct symbol
145 ULONG name; /* Offset of the name string in the string table */
146 ULONG value; /* Varies; eg. the offset of the symbol in its hunk */
147 ULONG size; /* How much memory does the symbol occupy */
148 UBYTE info; /* What kind of symbol is this ? (global, variable, etc) */
149 UBYTE other; /* undefined */
150 UWORD shindex; /* In which section is the symbol defined ? */
153 struct relo
155 ULONG offset; /* Address of the relocation relative to the section it refers to */
156 ULONG info; /* Type of the relocation */
157 #if defined(__mc68000__) || defined (__x86_64__) || defined (__ppc__) || defined (__powerpc__) || defined(__arm__)
158 LONG addend; /* Constant addend used to compute value */
159 #endif
162 struct hunk
164 ULONG size;
165 BPTR next;
166 char data[0];
167 } __attribute__((packed));
169 #define BPTR2HUNK(bptr) ((struct hunk *)((char *)BADDR(bptr) - offsetof(struct hunk, next)))
170 #define HUNK2BPTR(hunk) MKBADDR(&hunk->next)
172 /* convert section header number to array index */
173 #define SHINDEX(n) \
174 ((n) < SHN_LORESERVE ? (n) : ((n) <= SHN_HIRESERVE ? 0 : (n) - (SHN_HIRESERVE + 1 - SHN_LORESERVE)))
176 /* convert section header array index to section number */
177 #define SHNUM(i) \
178 ((i) < SHN_LORESERVE ? (i) : (i) + (SHN_HIRESERVE + 1 - SHN_LORESERVE))
180 #undef MyRead
181 #undef MyAlloc
182 #undef MyFree
185 #define MyRead(file, buf, size) \
186 AROS_CALL3 \
188 LONG, funcarray[0], \
189 AROS_LCA(BPTR, file, D1), \
190 AROS_LCA(void *, buf, D2), \
191 AROS_LCA(LONG, size, D3), \
192 struct DosLibrary *, DOSBase \
196 #define MyAlloc(size, flags) \
197 AROS_CALL2 \
199 void *, funcarray[1], \
200 AROS_LCA(ULONG, size, D0), \
201 AROS_LCA(ULONG, flags, D1), \
202 struct ExecBase *, SysBase \
206 #define MyFree(addr, size) \
207 AROS_CALL2NR \
209 void, funcarray[2], \
210 AROS_LCA(void *, addr, A1), \
211 AROS_LCA(ULONG, size, D0), \
212 struct ExecBase *, SysBase \
215 static int read_block
217 BPTR file,
218 ULONG offset,
219 APTR buffer,
220 ULONG size,
221 SIPTR *funcarray,
222 struct DosLibrary *DOSBase
225 UBYTE *buf = (UBYTE *)buffer;
226 LONG subsize;
228 if (Seek(file, offset, OFFSET_BEGINNING) < 0)
229 return 0;
231 while (size)
233 subsize = MyRead(file, buf, size);
235 if (subsize <= 0)
237 if (subsize == 0)
238 SetIoErr(ERROR_BAD_HUNK);
240 return 0;
243 buf += subsize;
244 size -= subsize;
247 return 1;
250 static void * load_block
252 BPTR file,
253 ULONG offset,
254 ULONG size,
255 SIPTR *funcarray,
256 struct DosLibrary *DOSBase
259 D(bug("[ELF Loader] Load Block\n"));
260 D(bug("[ELF Loader] (size=%d)\n",size));
261 D(bug("[ELF Loader] (funcarray=0x%x)\n",funcarray));
262 D(bug("[ELF Loader] (funcarray[1]=0x%x)\n",funcarray[1]));
263 void *block = MyAlloc(size, MEMF_ANY);
264 if (block)
266 if (read_block(file, offset, block, size, funcarray, DOSBase))
267 return block;
269 MyFree(block, size);
271 else
272 SetIoErr(ERROR_NO_FREE_STORE);
274 return NULL;
277 static int load_header(BPTR file, struct elfheader *eh, SIPTR *funcarray, struct DosLibrary *DOSBase) {
278 if (!read_block(file, 0, eh, offsetof(struct elfheader, int_shnum), funcarray, DOSBase))
279 return 0;
281 if (eh->ident[0] != 0x7f || eh->ident[1] != 'E' ||
282 eh->ident[2] != 'L' || eh->ident[3] != 'F') {
283 D(bug("[ELF Loader] Not an ELF object\n"));
284 SetIoErr(ERROR_NOT_EXECUTABLE);
285 return 0;
287 D(bug("[ELF Loader] ELF object\n"));
289 eh->int_shnum = eh->shnum;
290 eh->int_shstrndx = eh->shstrndx;
292 /* the ELF header only uses 16 bits to store the count of section headers,
293 * so it can't handle more than 65535 headers. if the count is 0, and an
294 * offset is defined, then the real count can be found in the first
295 * section header (which always exists).
297 * similarly, if the string table index is SHN_XINDEX, then the actual
298 * index is found in the first section header also.
300 * see the System V ABI 2001-04-24 draft for more details.
302 if (eh->int_shnum == 0 || eh->int_shstrndx == SHN_XINDEX) {
303 if (eh->shoff == 0) {
304 SetIoErr(ERROR_NOT_EXECUTABLE);
305 return 0;
308 struct sheader sh;
309 if (!read_block(file, eh->shoff, &sh, sizeof(sh), funcarray, DOSBase))
310 return 0;
312 /* wider section header count is in the size field */
313 if (eh->int_shnum == 0)
314 eh->int_shnum = sh.size;
316 /* wider string table index is in the link field */
317 if (eh->int_shstrndx == SHN_XINDEX)
318 eh->int_shstrndx = sh.link;
320 /* sanity, if they're still invalid then this isn't elf */
321 if (eh->int_shnum == 0 || eh->int_shstrndx == SHN_XINDEX) {
322 SetIoErr(ERROR_NOT_EXECUTABLE);
323 return 0;
329 eh->ident[EI_CLASS] != ELFCLASS32 ||
330 eh->ident[EI_VERSION] != EV_CURRENT ||
331 eh->type != ET_REL ||
333 #if defined(__i386__)
334 eh->ident[EI_DATA] != ELFDATA2LSB ||
335 eh->machine != EM_386
337 #elif defined(__x86_64__)
338 eh->ident[EI_DATA] != ELFDATA2LSB ||
339 eh->machine != EM_X86_64
341 #elif defined(__mc68000__)
342 eh->ident[EI_DATA] != ELFDATA2MSB ||
343 eh->machine != EM_68K
345 #elif defined(__ppc__) || defined(__powerpc__)
346 eh->ident[EI_DATA] != ELFDATA2MSB ||
347 eh->machine != EM_PPC
349 #elif defined(__arm__)
350 eh->ident[EI_DATA] != ELFDATA2LSB ||
351 eh->machine != EM_ARM
352 #warning ARM has not been tested, yet!
354 #else
355 # error Your architecture is not supported
356 #endif
359 D(bug("[ELF Loader] Object is of wrong type\n"));
360 #if defined(__x86_64__)
361 D(bug("[ELF Loader] EI_CLASS is %d - should be %d\n", eh->ident[EI_CLASS], ELFCLASS64));
362 #else
363 D(bug("[ELF Loader] EI_CLASS is %d - should be %d\n", eh->ident[EI_CLASS], ELFCLASS32));
364 #endif
365 D(bug("[ELF Loader] EI_VERSION is %d - should be %d\n", eh->ident[EI_VERSION], EV_CURRENT));
366 D(bug("[ELF Loader] type is %d - should be %d\n", eh->type, ET_REL));
367 #if defined (__i386__)
368 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA],ELFDATA2LSB));
369 #elif defined (__mc68000__)
370 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA],ELFDATA2MSB));
371 #elif defined(__ppc__) || defined(__powerpc__)
372 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA],ELFDATA2MSB));
373 #elif defined (__arm__)
374 D(bug("[ELF Loader] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA],ELFDATA2MSB));
375 #endif
377 #if defined (__i386__)
378 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine, EM_386));
379 #elif defined(__mc68000__)
380 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine, EM_68K));
381 #elif defined(__ppc__) || defined(__powerpc__)
382 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine, EM_PPC));
383 #elif defined(__arm__)
384 D(bug("[ELF Loader] machine is %d - should be %d\n", eh->machine, EM_ARM));
385 #endif
387 SetIoErr(ERROR_NOT_EXECUTABLE);
388 return 0;
391 return 1;
394 static int load_hunk
396 BPTR file,
397 BPTR **next_hunk_ptr,
398 struct sheader *sh,
399 SIPTR *funcarray,
400 BOOL do_align,
401 struct DosLibrary *DOSBase
404 struct hunk *hunk;
405 ULONG hunk_size;
407 if (!sh->size)
408 return 1;
410 /* The size of the hunk is the size of the section, plus
411 the size of the hunk structure, plus the size of the alignment (if necessary)*/
412 hunk_size = sh->size + sizeof(struct hunk);
414 if (do_align)
416 hunk_size += sh->addralign;
418 /* Also create space for a trampoline, if necessary */
419 if (sh->flags & SHF_EXECINSTR)
420 hunk_size += sizeof(struct FullJumpVec);
423 hunk = MyAlloc(hunk_size, MEMF_ANY | (sh->type == SHT_NOBITS) ? MEMF_CLEAR : 0);
424 if (hunk)
426 hunk->next = 0;
427 hunk->size = hunk_size;
429 /* In case we are required to honour alignment, and If this section contains
430 executable code, create a trampoline to its beginning, so that even if the
431 alignment requirements make the actual code go much after the end of the
432 hunk structure, the code can still be reached in the usual way. */
433 if (do_align)
435 if (sh->flags & SHF_EXECINSTR)
437 sh->addr = (char *)AROS_ROUNDUP2
439 (ULONG)hunk->data + sizeof(struct FullJumpVec), sh->addralign
441 __AROS_SET_FULLJMP((struct FullJumpVec *)hunk->data, sh->addr);
443 else
444 sh->addr = (char *)AROS_ROUNDUP2((ULONG)hunk->data, sh->addralign);
446 else
447 sh->addr = hunk->data;
449 /* Link the previous one with the new one */
450 BPTR2HUNK(*next_hunk_ptr)->next = HUNK2BPTR(hunk);
452 D(bug("[dos] hunk @ %p\n", sh->addr));
454 /* Update the pointer to the previous one, which is now the current one */
455 *next_hunk_ptr = HUNK2BPTR(hunk);
457 if (sh->type != SHT_NOBITS)
458 return read_block(file, sh->offset, sh->addr, sh->size, funcarray, DOSBase);
460 return 1;
464 SetIoErr(ERROR_NO_FREE_STORE);
466 return 0;
469 static int relocate
471 struct elfheader *eh,
472 struct sheader *sh,
473 ULONG shrel_idx,
474 struct sheader *symtab_shndx,
475 struct DosLibrary *DOSBase
478 struct sheader *shrel = &sh[shrel_idx];
479 struct sheader *shsymtab = &sh[SHINDEX(shrel->link)];
480 struct sheader *toreloc = &sh[SHINDEX(shrel->info)];
482 struct symbol *symtab = (struct symbol *)shsymtab->addr;
483 struct relo *rel = (struct relo *)shrel->addr;
484 char *section = toreloc->addr;
486 /* this happens if the target section has no allocation. that can happen
487 * eg. with a .debug PROGBITS and a .rel.debug section */
488 if (section == NULL)
489 return 1;
491 ULONG numrel = shrel->size / shrel->entsize;
492 ULONG i;
494 struct symbol *SysBase_sym = NULL;
496 for (i=0; i<numrel; i++, rel++)
498 struct symbol *sym = &symtab[ELF32_R_SYM(rel->info)];
499 ULONG *p = (ULONG *)&section[rel->offset];
500 ULONG s;
501 ULONG shindex;
503 if (sym->shindex != SHN_XINDEX)
504 shindex = sym->shindex;
506 else {
507 if (symtab_shndx == NULL) {
508 D(bug("[ELF Loader] got symbol with shndx 0xfff, but there's no symtab shndx table\n"));
509 SetIoErr(ERROR_BAD_HUNK);
510 return 0;
512 shindex = ((ULONG *)symtab_shndx->addr)[ELF32_R_SYM(rel->info)];
515 switch (shindex)
518 case SHN_UNDEF:
519 D(bug("[ELF Loader] Undefined symbol '%s' while relocating the section '%s'\n",
520 (STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name,
521 (STRPTR)sh[SHINDEX(eh->int_shstrndx)].addr + toreloc->name));
522 SetIoErr(ERROR_BAD_HUNK);
523 return 0;
525 case SHN_COMMON:
526 D(bug("[ELF Loader] COMMON symbol '%s' while relocating the section '%s'\n",
527 (STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name,
528 (STRPTR)sh[SHINDEX(eh->int_shstrndx)].addr + toreloc->name));
529 SetIoErr(ERROR_BAD_HUNK);
531 return 0;
533 case SHN_ABS:
534 if (SysBase_sym == NULL)
536 if (strncmp((STRPTR)sh[SHINDEX(shsymtab->link)].addr + sym->name, "SysBase", 8) == 0)
538 SysBase_sym = sym;
539 goto SysBase_yes;
541 else
542 goto SysBase_no;
544 else
545 if (SysBase_sym == sym)
547 SysBase_yes: s = (ULONG)&SysBase;
549 else
550 SysBase_no: s = sym->value;
551 break;
553 default:
554 s = (ULONG)sh[SHINDEX(shindex)].addr + sym->value;
557 switch (ELF32_R_TYPE(rel->info))
559 #if defined(__i386__)
561 case R_386_32: /* 32bit absolute */
562 *p += s;
563 break;
565 case R_386_PC32: /* 32bit PC relative */
566 *p += s - (ULONG)p;
567 break;
569 case R_386_NONE:
570 break;
572 #elif defined(__x86_64__)
573 /* These weren't tested */
574 case R_X86_64_64: /* 64bit direct/absolute */
575 *p = s + rel->addend;
576 break;
578 case R_X86_64_PC32: /* PC relative 32 bit signed */
579 *p = s + rel->addend - (ULONG)p;
580 break;
582 case R_X86_64_NONE: /* No reloc */
583 break;
585 #elif defined(__mc68000__)
587 case R_68K_32:
588 *p = s + rel->addend;
589 break;
591 case R_68K_PC32:
592 *p = s + rel->addend - (ULONG)p;
593 break;
595 case R_68k_NONE:
596 break;
598 #elif defined(__ppc__) || defined(__powerpc__)
600 case R_PPC_ADDR32:
601 *p = s + rel->addend;
602 break;
604 case R_PPC_ADDR16_LO:
606 unsigned short *c = (unsigned short *) p;
607 *c = (s + rel->addend) & 0xffff;
609 break;
611 case R_PPC_ADDR16_HA:
613 unsigned short *c = (unsigned short *) p;
614 ULONG temp = s + rel->addend;
615 *c = temp >> 16;
616 if ((temp & 0x8000) != 0)
617 (*c)++;
619 break;
621 case R_PPC_REL16_LO:
623 unsigned short *c = (unsigned short *) p;
624 *c = (s + rel->addend - (ULONG) p) & 0xffff;
626 break;
628 case R_PPC_REL16_HA:
630 unsigned short *c = (unsigned short *) p;
631 ULONG temp = s + rel->addend - (ULONG) p;
632 *c = temp >> 16;
633 if ((temp & 0x8000) != 0)
634 (*c)++;
636 break;
638 case R_PPC_REL24:
639 *p &= ~0x3fffffc;
640 *p |= (s + rel->addend - (ULONG) p) & 0x3fffffc;
641 break;
643 case R_PPC_REL32:
644 *p = s + rel->addend - (ULONG) p;
645 break;
647 case R_PPC_NONE:
648 break;
650 #elif defined(__arm__)
653 * This has not been tested. Taken from ARMELF.pdf
654 * from arm.com page 33ff.
656 case R_ARM_PC24:
657 *p = s + rel->addend - (ULONG)p;
658 break;
660 case R_ARM_ABS32:
661 *p = s + rel->addend;
662 break;
664 case R_ARM_NONE:
665 break;
667 #else
668 # error Your architecture is not supported
669 #endif
671 default:
672 D(bug("[ELF Loader] Unrecognized relocation type %d %d\n", i, ELF32_R_TYPE(rel->info)));
673 SetIoErr(ERROR_BAD_HUNK);
674 return 0;
678 return 1;
681 BPTR InternalLoadSeg_ELF
683 BPTR file,
684 BPTR table __unused,
685 SIPTR *funcarray,
686 SIPTR *stack __unused,
687 struct MinList *seginfos,
688 struct DosLibrary *DOSBase
691 struct elfheader eh;
692 struct sheader *sh;
693 struct sheader *symtab_shndx = NULL;
694 BPTR hunks = 0;
695 BPTR *next_hunk_ptr = MKBADDR(&hunks);
696 ULONG i;
697 BOOL exec_hunk_seen = FALSE;
699 /* load and validate ELF header */
700 if (!load_header(file, &eh, funcarray, DOSBase))
701 return 0;
703 /* load section headers */
704 if (!(sh = load_block(file, eh.shoff, eh.int_shnum * eh.shentsize, funcarray, DOSBase)))
705 return 0;
707 /* load the string table */
708 STRPTR st = NULL;
709 struct sheader *shstr = sh + SHINDEX(eh.int_shstrndx);
710 if (shstr->size != 0)
712 st = MyAlloc(shstr->size, MEMF_ANY | MEMF_CLEAR);
713 read_block(file, shstr->offset, st, shstr->size, funcarray, DOSBase);
716 /* Iterate over the section headers in order to do some stuff... */
717 for (i = 0; i < eh.int_shnum; i++)
720 Load the symbol and string table(s).
722 NOTICE: the ELF standard, at the moment (Nov 2002) explicitely states
723 that only one symbol table per file is allowed. However, it
724 also states that this may change in future... we already handle it.
726 if (sh[i].type == SHT_SYMTAB || sh[i].type == SHT_STRTAB || sh[i].type == SHT_SYMTAB_SHNDX)
728 sh[i].addr = load_block(file, sh[i].offset, sh[i].size, funcarray, DOSBase);
729 if (!sh[i].addr)
730 goto error;
732 if (sh[i].type == SHT_SYMTAB_SHNDX) {
733 if (symtab_shndx == NULL)
734 symtab_shndx = &sh[i];
735 else
736 D(bug("[ELF Loader] file contains multiple symtab shndx tables. only using the first one\n"));
739 else
740 /* Load the section in memory if needed, and make an hunk out of it */
741 if (sh[i].flags & SHF_ALLOC)
743 if (sh[i].size)
745 /* Only allow alignment if this is an executable hunk
746 or if an executable hunk has been loaded already,
747 so to avoid the situation in which a data hunk has its
748 content displaced from the hunk's header in case it's the
749 first hunk (this happens with Keymaps, for instance). */
750 if (sh[i].flags & SHF_EXECINSTR)
751 exec_hunk_seen = TRUE;
753 if (!load_hunk(file, &next_hunk_ptr, &sh[i], funcarray, exec_hunk_seen, DOSBase))
754 goto error;
756 if (seginfos)
758 STRPTR name = st + sh[i].name;
759 ULONG size = sizeof(struct seginfo);
760 struct seginfo *si = MyAlloc(size, MEMF_ANY);
762 D(bug("[ELF Loader] seg %s at 0x%x\n", name, sh[i].addr));
764 si->addr = sh[i].addr;
765 size = sizeof(si->name) - 1;
766 strncpy(si->name, name, size);
767 si->name[size] = '\0';
769 ADDTAIL(seginfos, &si->node);
776 /* Relocate the sections */
777 for (i = 0; i < eh.int_shnum; i++)
781 #if defined(__i386__)
783 sh[i].type == SHT_REL &&
785 #elif defined(__x86_64__)
787 sh[i].type == SHT_RELA &&
789 #elif defined(__mc68000__)
791 sh[i].type == SHT_RELA &&
793 #elif defined(__ppc__) || defined(__powerpc__)
795 sh[i].type == SHT_RELA &&
797 #elif defined(__arm__)
798 #warning Missing code for ARM
799 // sh[i].type = SHT_
801 #else
802 # error Your architecture is not supported
803 #endif
805 /* Does this relocation section refer to a hunk? If so, addr must be != 0 */
806 sh[SHINDEX(sh[i].info)].addr
809 sh[i].addr = load_block(file, sh[i].offset, sh[i].size, funcarray, DOSBase);
810 if (!sh[i].addr || !relocate(&eh, sh, i, symtab_shndx, DOSBase))
811 goto error;
813 MyFree(sh[i].addr, sh[i].size);
814 sh[i].addr = NULL;
818 /* Everything is loaded now. Register the module at kernel.resource */
820 char buffer[512], *nameptr = buffer;
822 if (NameFromFH(file, buffer, 512))
824 void *KernelBase = OpenResource("kernel.resource");
826 /* First, go through the name, till end of the string */
827 while(*nameptr++);
829 /* Now, go back until either ":" or "/" is found */
831 while(nameptr > buffer && nameptr[-1] != ':' && nameptr[-1] != '/')
833 nameptr--;
836 KrnRegisterModule(nameptr, sh, &eh);
839 goto end;
841 error:
843 /* There were some errors, deallocate The hunks */
845 InternalUnLoadSeg(hunks, (VOID_FUNC)funcarray[2]);
846 hunks = 0;
848 end:
850 /* Clear the caches to let the CPU see the new data and instructions */
852 BPTR curr = hunks;
853 while (curr)
855 struct hunk *hunk = BPTR2HUNK(curr);
857 CacheClearE(hunk->data, hunk->size, CACRF_ClearD | CACRF_ClearI);
859 curr = hunk->next;
863 /* deallocate the symbol tables */
864 for (i = 0; i < eh.int_shnum; i++)
866 if (((sh[i].type == SHT_SYMTAB) || (sh[i].type == SHT_STRTAB)) && (sh[i].addr != NULL))
867 MyFree(sh[i].addr, sh[i].size);
870 /* Free the string table */
871 MyFree(st, shstr->size);
873 /* Free the section headers */
874 MyFree(sh, eh.int_shnum * eh.shentsize);
876 return hunks;
879 #undef MyRead1
880 #undef MyAlloc
881 #undef MyFree