revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / AHI / Device / elfloader.c
blobc478e116823d7b4d152ffef4a52d211030fdbbcd
1 /*
2 AHI - Hardware independent audio subsystem
3 Copyright (C) 2017 The AROS Dev Team
4 Copyright (C) 1996-2005 Martin Blom <martin@blom.org>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with this library; if not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
19 MA 02139, USA.
23 ** Based on code from the ppc.library emulator by Frank Wille:
24 ** ppc.library emulation
25 ** (c)1998-99 Frank Wille <frank@phoenix.owl.de>
29 #include <exec/types.h>
30 #include <exec/memory.h>
31 #include <exec/nodes.h>
32 #include <dos/dos.h>
33 #include <proto/dos.h>
34 #include <proto/exec.h>
36 // Even though this is WarpUp only, we still need a few defines from PowerUp...
37 #include <powerup/ppclib/object.h>
39 #include <string.h>
41 #include "ahi_def.h"
42 #include "elfloader.h"
43 #include "misc.h"
45 /*** elfcommon.h *************************************************************/
47 /* e_indent indexes */
48 #define EI_NIDENT 16
49 #define EI_MAG0 0
50 #define EI_MAG1 1
51 #define EI_MAG2 2
52 #define EI_MAG3 3
53 #define EI_CLASS 4
54 #define EI_DATA 5
55 #define EI_VERSION 6
56 #define EI_PAD 7
58 /* EI_CLASS */
59 #define ELFCLASSNONE 0
60 #define ELFCLASS32 1
61 #define ELFCLASS64 2
63 /* EI_DATA */
64 #define ELFDATANONE 0
65 #define ELFDATA2LSB 1
66 #define ELFDATA2MSB 2
68 /* e_type */
69 #define ET_NONE 0 /* No file type */
70 #define ET_REL 1 /* Relocatable file */
71 #define ET_EXEC 2 /* Executable file */
72 #define ET_DYN 3 /* Shared object file */
73 #define ET_CORE 4 /* Core file */
74 #define ET_LOPROC 0xFF00 /* Processor-specific */
75 #define ET_HIPROC 0xFFFF /* Processor-specific */
77 /* e_version */
78 #define EV_NONE 0
79 #define EV_CURRENT 1
81 /* e_machine */
82 #define EM_NONE 0
83 #define EM_M32 1
84 #define EM_SPARC 2
85 #define EM_386 3
86 #define EM_68K 4
87 #define EM_88K 5
88 #define EM_860 7
89 #define EM_MIPS 8
90 #define EM_MIPS_RS4_BE 10
91 #define EM_SPARC64 11
92 #define EM_PARISC 15
93 #define EM_PPC_OLD 17
94 #define EM_SPARC32PLUS 18
95 #define EM_PPC 20
96 #define EM_CYGNUS_POWERPC 0x9025
97 #define EM_ALPHA 0x9026
99 /* values for program header, p_type field */
100 #define PT_NULL 0 /* Program header table entry unused */
101 #define PT_LOAD 1 /* Loadable program segment */
102 #define PT_DYNAMIC 2 /* Dynamic linking information */
103 #define PT_INTERP 3 /* Program interpreter */
104 #define PT_NOTE 4 /* Auxiliary information */
105 #define PT_SHLIB 5 /* Reserved, unspecified semantics */
106 #define PT_PHDR 6 /* Entry for header table itself */
107 #define PT_LOPROC 0x70000000 /* Processor-specific */
108 #define PT_HIPROC 0x7FFFFFFF /* Processor-specific */
110 /* Program segment permissions, in program header p_flags field */
111 #define PF_X (1 << 0) /* Segment is executable */
112 #define PF_W (1 << 1) /* Segment is writable */
113 #define PF_R (1 << 2) /* Segment is readable */
114 #define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */
116 /* special sections indexes */
117 #define SHN_UNDEF 0
118 #define SHN_ABS 0xfff1
119 #define SHN_COMMON 0xfff2
121 /* sh_type */
122 #define SHT_NULL 0 /* Section header table entry unused */
123 #define SHT_PROGBITS 1 /* Program specific (private) data */
124 #define SHT_SYMTAB 2 /* Link editing symbol table */
125 #define SHT_STRTAB 3 /* A string table */
126 #define SHT_RELA 4 /* Relocation entries with addends */
127 #define SHT_HASH 5 /* A symbol hash table */
128 #define SHT_DYNAMIC 6 /* Information for dynamic linking */
129 #define SHT_NOTE 7 /* Information that marks file */
130 #define SHT_NOBITS 8 /* Section occupies no space in file */
131 #define SHT_REL 9 /* Relocation entries, no addends */
132 #define SHT_SHLIB 10 /* Reserved, unspecified semantics */
133 #define SHT_DYNSYM 11 /* Dynamic linking symbol table */
134 #define SHT_LOPROC 0x70000000 /* Processor-specific semantics, lo */
135 #define SHT_HIPROC 0x7FFFFFFF /* Processor-specific semantics, hi */
136 #define SHT_LOUSER 0x80000000 /* Application-specific semantics */
137 #define SHT_HIUSER 0x8FFFFFFF /* Application-specific semantics */
139 /* sh_flags */
140 #define SHF_WRITE (1 << 0) /* Writable data during execution */
141 #define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
142 #define SHF_EXECINSTR (1 << 2) /* Executable machine instructions */
143 #define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */
145 /* Values of note segment descriptor types for core files. */
146 #define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
147 #define NT_FPREGSET 2 /* Contains copy of fpregset struct */
148 #define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
150 #define STN_UNDEF 0 /* undefined symbol index */
152 /* ST_BIND */
153 #define STB_LOCAL 0 /* Symbol not visible outside obj */
154 #define STB_GLOBAL 1 /* Symbol visible outside obj */
155 #define STB_WEAK 2 /* Like globals, lower precedence */
156 #define STB_LOPROC 13 /* Application-specific semantics */
157 #define STB_HIPROC 15 /* Application-specific semantics */
159 /* ST_TYPE */
160 #define STT_NOTYPE 0 /* Symbol type is unspecified */
161 #define STT_OBJECT 1 /* Symbol is a data object */
162 #define STT_FUNC 2 /* Symbol is a code object */
163 #define STT_SECTION 3 /* Symbol associated with a section */
164 #define STT_FILE 4 /* Symbol gives a file name */
165 #define STT_LOPROC 13 /* Application-specific semantics */
166 #define STT_HIPROC 15 /* Application-specific semantics */
168 /* Dynamic section tags */
169 #define DT_NULL 0
170 #define DT_NEEDED 1
171 #define DT_PLTRELSZ 2
172 #define DT_PLTGOT 3
173 #define DT_HASH 4
174 #define DT_STRTAB 5
175 #define DT_SYMTAB 6
176 #define DT_RELA 7
177 #define DT_RELASZ 8
178 #define DT_RELAENT 9
179 #define DT_STRSZ 10
180 #define DT_SYMENT 11
181 #define DT_INIT 12
182 #define DT_FINI 13
183 #define DT_SONAME 14
184 #define DT_RPATH 15
185 #define DT_SYMBOLIC 16
186 #define DT_REL 17
187 #define DT_RELSZ 18
188 #define DT_RELENT 19
189 #define DT_PLTREL 20
190 #define DT_DEBUG 21
191 #define DT_TEXTREL 22
192 #define DT_JMPREL 23
193 #define DT_LOPROC 0x70000000
194 #define DT_HIPROC 0x7fffffff
196 /*** elf32.h *****************************************************************/
198 typedef unsigned char uint8;
199 typedef unsigned short uint16;
200 typedef unsigned long uint32;
203 struct Elf32_Ehdr {
204 unsigned char e_ident[EI_NIDENT];
205 uint16 e_type;
206 uint16 e_machine;
207 uint32 e_version;
208 uint32 e_entry;
209 uint32 e_phoff;
210 uint32 e_shoff;
211 uint32 e_flags;
212 uint16 e_ehsize;
213 uint16 e_phentsize;
214 uint16 e_phnum;
215 uint16 e_shentsize;
216 uint16 e_shnum;
217 uint16 e_shstrndx;
220 struct Elf32_Shdr {
221 uint32 sh_name;
222 uint32 sh_type;
223 uint32 sh_flags;
224 uint32 sh_addr;
225 uint32 sh_offset;
226 uint32 sh_size;
227 uint32 sh_link;
228 uint32 sh_info;
229 uint32 sh_addralign;
230 uint32 sh_entsize;
233 struct Elf32_Sym {
234 uint32 st_name;
235 uint32 st_value;
236 uint32 st_size;
237 uint8 st_info;
238 uint8 st_other;
239 uint16 st_shndx;
242 /* st_info */
243 #define ELF32_ST_BIND(i) ((i)>>4)
244 #define ELF32_ST_TYPE(i) ((i)&0xf)
245 #define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
247 struct Elf32_Rel {
248 uint32 r_offset;
249 uint32 r_info;
252 struct Elf32_Rela {
253 uint32 r_offset;
254 uint32 r_info;
255 uint32 r_addend;
258 /* r_info */
259 #define ELF32_R_SYM(i) ((i)>>8)
260 #define ELF32_R_TYPE(i) ((unsigned char)(i))
261 #define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t))
263 /*** elfobject.h *************************************************************/
265 struct ELFSection { /* prog. sections for new tasks */
266 char *name;
267 APTR address; /* physical RAM address or NULL */
268 UWORD flags;
269 UWORD alignment;
270 long offset; /* file offset and section size */
271 ULONG size;
272 int nrel; /* number of relocs */
273 struct Elf32_Rela *relocs; /* array of Elf32_Rela structs */
276 #define ElfSecB_NOBITS 0 /* bss section */
277 #define ElfSecF_NOBITS 1
278 #define ElfSecB_RELA 1 /* Relocs are of .rela type */
279 #define ElfSecF_RELA 2
282 struct ElfObject {
283 // struct Node n; /* contains object's name ptr */
284 UWORD flags;
285 // struct PPCLibBase *ppcbase;
286 // void *pool; /* pooled memory for object data */
287 BPTR handle; /* ELF file handle */
288 // APTR handle; /* ELF file handle */
289 // struct Hook *hook; /* hook functions for read/seek */
290 // struct Hook defaultHook;
291 char *secnames; /* .shstrtab - section names */
292 char *symnames; /* .strtab - symbol mames */
293 struct Elf32_Ehdr *header; /* the ELF file header */
294 struct Elf32_Sym *symtab; /* .symtab - symbol table */
295 uint32 nsyms; /* number of symbols */
296 uint32 gsyms; /* first global symbol */
297 struct ELFSection **sections; /* ELFSection pointers */
298 uint32 nsects; /* number of sections */
299 // struct SignalSemaphore ElfSS; /* ElfObject access arbitration */
302 #define ElfObjB_Relocated 0 /* Object is relocated */
303 #define ElfObjF_Relocated 1
305 /*** relocnames.c ************************************************************/
307 const char *reloc_name[] = {
308 "R_NONE",
309 "R_PPC_ADDR32",
310 "R_PPC_ADDR24",
311 "R_PPC_ADDR16",
312 "R_PPC_ADDR16_LO",
313 "R_PPC_ADDR16_HI",
314 "R_PPC_ADDR16_HA",
315 "R_PPC_ADDR14",
316 "R_PPC_ADDR14_BRTAKEN",
317 "R_PPC_ADDR14_BRNTAKEN",
318 "R_PPC_REL24",
319 "R_PPC_REL14",
320 "R_PPC_REL14_BRTAKEN",
321 "R_PPC_REL14_BRNTAKEN",
322 "R_PPC_GOT16",
323 "R_PPC_GOT16_LO",
324 "R_PPC_GOT16_HI",
325 "R_PPC_GOT16_HA",
326 "R_PPC_PLTREL24",
327 "R_PPC_COPY",
328 "R_PPC_GLOB_DAT",
329 "R_PPC_JMP_SLOT",
330 "R_PPC_RELATIVE",
331 "R_PPC_LOCAL24PC",
332 "R_PPC_UADDR32",
333 "R_PPC_UADDR16",
334 "R_PPC_REL32",
335 "R_PPC_PLT32",
336 "R_PPC_PLTREL32",
337 "R_PPC_PLT16_LO",
338 "R_PPC_PLT16_HI",
339 "R_PPC_PLT16_HA",
340 "R_PPC_SDAREL16",
341 "R_PPC_SECTOFF",
342 "R_PPC_SECTOFF_LO",
343 "R_PPC_SECTOFF_HI",
344 "R_PPC_SECTOFF_HA"
347 /*** ppcobject.c *************************************************************/
350 /* Bug fix for powerup/ppclib/object.h */
351 #ifdef R_PPC_ADDR16_L
352 #ifndef R_PPC_ADDR16_LO
353 #define R_PPC_ADDR16_LO R_PPC_ADDR16_L
354 #endif
355 #endif
357 static void
358 freeelfobj(struct ElfObject *elfobj);
360 static BOOL
361 loadelf32(struct ElfObject *eo,struct Elf32_Shdr *shdrs);
363 static BOOL
364 scanElfSymbols(struct ElfObject *eo,struct PPCObjectInfo *info,
365 BOOL relmode);
367 static BOOL
368 getsyminfo(struct ElfObject *eo,struct PPCObjectInfo *info,
369 struct Elf32_Sym *stab);
371 static APTR
372 loadprogram(struct ElfObject *eo);
374 static void
375 freeprogram(struct ElfObject *eo);
377 static BOOL
378 relocate(struct ElfObject *eo);
380 static void*
381 allocstr( const char* string );
383 static void*
384 alloc32c( size_t size );
386 static void*
387 alloc32( size_t size );
389 void
390 free32( void* addr );
392 static BPTR
393 opstream(struct ElfObject *eo, const char* name );
395 static BOOL
396 clstream(struct ElfObject *eo);
398 static BOOL
399 rdstream(struct ElfObject *eo,void *buf,long len);
401 static long
402 skstream(struct ElfObject *eo,long offs,long mode);
404 static BOOL
405 prstream(struct ElfObject *eo,long offs,void *buf,long len);
407 static void*
408 readsection(struct ElfObject *eo,struct Elf32_Shdr *sh);
410 static struct ELFSection*
411 progsection(struct ElfObject *eo, struct Elf32_Shdr *sh);
413 static BOOL
414 common_symbols(struct ElfObject *eo);
416 static BOOL
417 getrelocs(struct ElfObject *eo,struct Elf32_Shdr *sh);
419 static const char ELFid[4] = {
420 0x7f,'E','L','F'
423 void*
424 ELFLoadObject( const char* objname )
426 struct ElfObject *elfobj = NULL;
428 /* allocate ElfObject structure */
430 elfobj = alloc32( sizeof( struct ElfObject ) );
432 if( elfobj != NULL )
434 memset(elfobj,0,sizeof(struct ElfObject));
436 elfobj->header = alloc32( sizeof( struct Elf32_Ehdr ) );
438 if( elfobj->header != NULL )
440 /* open ELF stream for reading */
442 elfobj->handle = opstream( elfobj, objname );
444 if( elfobj->handle != NULL )
446 /* read and identify ELF 32bit PowerPC BigEndian header */
448 if( rdstream( elfobj, elfobj->header, sizeof(struct Elf32_Ehdr) ) )
450 struct Elf32_Ehdr *hdr = elfobj->header;
452 if (!strncmp(hdr->e_ident,ELFid,4) &&
453 hdr->e_ident[EI_CLASS]==ELFCLASS32 &&
454 hdr->e_ident[EI_DATA]==ELFDATA2MSB &&
455 hdr->e_ident[EI_VERSION]==1 && hdr->e_version==1 &&
456 (hdr->e_machine==EM_PPC || hdr->e_machine==EM_PPC_OLD ||
457 hdr->e_machine==EM_CYGNUS_POWERPC) && hdr->e_type==ET_REL)
459 struct Elf32_Shdr *shdrs;
460 ULONG shdrsize = (ULONG) hdr->e_shnum * (ULONG) hdr->e_shentsize;
462 // KPrintF("elf32ppcbe format recognized\n");
464 shdrs = alloc32( shdrsize );
466 if( shdrs != NULL )
468 /* read section header table and parse rest of object */
470 if( prstream( elfobj, hdr->e_shoff, shdrs, shdrsize ) )
472 if( loadelf32( elfobj, shdrs ) )
474 void* start;
475 // KPrintF("ELF object loaded (0x%08lx)\n", elfobj );
476 start = loadprogram( elfobj );
477 // KPrintF("Start of PPC code: 0x%08lx\n", start );
478 free32( shdrs );
479 return (elfobj);
482 free32( shdrs );
485 else
486 KPrintF( "Not an ELF32-PPC-BE\nrelocatable object.");
489 freeelfobj(elfobj);
493 return (NULL);
497 void
498 ELFUnLoadObject( void* obj )
500 struct ElfObject* elfobj = (struct ElfObject*) obj;
502 if(elfobj->sections != NULL && elfobj->nsects > 0 )
504 freeprogram(elfobj);
507 freeelfobj(elfobj);
510 BOOL
511 ELFGetSymbol( void* obj,
512 const char* name,
513 void** ptr )
515 struct PPCObjectInfo oi =
518 NULL,
519 PPCELFINFOTYPE_SYMBOL,
520 STT_SECTION,
521 STB_GLOBAL,
525 BOOL rc;
527 oi.Name = (char*) name;
528 rc = scanElfSymbols( (struct ElfObject*) obj, &oi, FALSE );
530 if( rc )
532 *ptr = (void*) oi.Address;
535 return rc;
539 static void freeelfobj(struct ElfObject *elfobj)
540 /* free all memory connected to an ElfObject */
542 if (elfobj) {
543 if (elfobj->handle)
544 clstream(elfobj);
545 free32(elfobj);
550 static BOOL loadelf32(struct ElfObject *eo,struct Elf32_Shdr *shdrs)
551 /* parse ELF object, initialize ElfObject structure */
553 struct Elf32_Ehdr *hdr = eo->header;
554 struct ELFSection *s;
555 uint16 i;
557 if ((eo->secnames = readsection(eo,&shdrs[hdr->e_shstrndx])) &&
558 (eo->sections = alloc32((hdr->e_shnum+1)*sizeof(void *)))) {
559 memset(eo->sections,0,(hdr->e_shnum+1)*sizeof(void *));
560 eo->nsects = hdr->e_shnum + 1; /* +1 section for COMMON symbols */
561 for (i=1; i<hdr->e_shnum; i++) {
562 switch (shdrs[i].sh_type) {
563 case SHT_PROGBITS:
564 case SHT_NOBITS:
565 if (!(eo->sections[i] = progsection(eo,&shdrs[i])))
566 return (FALSE);
567 break;
568 case SHT_SYMTAB:
569 if (!(eo->symnames = readsection(eo,&shdrs[shdrs[i].sh_link]))
570 || !(eo->symtab = readsection(eo,&shdrs[i])))
571 return (FALSE);
572 eo->nsyms = shdrs[i].sh_size / sizeof(struct Elf32_Sym);
573 eo->gsyms = shdrs[i].sh_info;
574 break;
575 default:
576 break;
579 for (i=1; i<hdr->e_shnum; i++) {
580 switch (shdrs[i].sh_type) {
581 case SHT_REL:
582 case SHT_RELA:
583 if (!getrelocs(eo,&shdrs[i]))
584 return (FALSE);
585 break;
586 default:
587 break;
590 /* allocate space for Common symbols */
591 return (common_symbols(eo));
593 return (FALSE);
597 static BOOL scanElfSymbols(struct ElfObject *eo,struct PPCObjectInfo *info,
598 BOOL relmode)
599 /* Find an ELF symbol by its name or address and return all infos */
600 /* in the supplied PPCObjectInfo structure. Return FALSE if symbol */
601 /* doesn't exist. */
602 /* ATTENTION: PPCLibBase may be locked at that stage! */
604 IPTR addr = info->Address;
605 char *name = info->Name;
606 //KPrintF( "scanElfSymbols( 0x%08lx, 0x%08lx, %ld\n", eo, info, relmode );
607 if (relmode) {
608 unsigned int i;
609 int j;
610 struct ELFSection *es;
611 struct Elf32_Rela *r;
613 for (i=1; i<(eo->nsects-1); i++) {
614 if( (es = eo->sections[i]) != NULL ) {
615 for (j=0,r=es->relocs; j<es->nrel; j++,r++) {
616 if (getsyminfo(eo,info,&eo->symtab[ELF32_R_SYM(r->r_info)])) {
617 info->Address = (IPTR)es->address + r->r_offset;
618 info->Type = PPCELFINFOTYPE_RELOC;
619 info->SubType = (ULONG)ELF32_R_TYPE(r->r_info);
620 if (info->Address == addr) {
621 if (name) {
622 if (!strcmp(name,info->Name))
623 return (TRUE);
625 else
626 return (TRUE);
634 else {
635 struct Elf32_Sym *stab = eo->symtab;
636 int i = eo->nsyms;
637 while (--i) {
638 //KPrintF( "i=%ld\n", i );
639 if (getsyminfo(eo,info,++stab)) {
640 if (!name) {
641 if (info->Size) {
642 if (addr>=info->Address && addr<(info->Address+info->Size))
643 return (TRUE);
645 else {
646 if (addr == info->Address)
647 return (TRUE);
650 else {
651 //KPrintF( "comparing %s and %s\n", name,info->Name );
652 if (!strcmp(name,info->Name))
653 return (TRUE);
658 return (FALSE);
662 static BOOL getsyminfo(struct ElfObject *eo,struct PPCObjectInfo *info,
663 struct Elf32_Sym *stab)
665 struct ELFSection *es;
666 ULONG subtype;
668 subtype = (ULONG)ELF32_ST_TYPE(stab->st_info);
669 if (subtype < STT_FILE) {
670 info->Type = subtype==STT_SECTION ? PPCELFINFOTYPE_SECTION
671 : PPCELFINFOTYPE_SYMBOL;
672 switch (stab->st_shndx) {
673 case SHN_UNDEF:
674 /* undefined symbols will disappear after relocation */
675 case SHN_ABS:
676 info->Address = stab->st_value;
677 break;
678 case SHN_COMMON:
679 /* @@@ common symbols should have disappeared after common_symbols() */
680 info->Type = PPCELFINFOTYPE_COMSYMBOL;
681 info->Address = 0;
682 break;
683 default:
684 if( (es = eo->sections[stab->st_shndx]) != NULL )
685 info->Address = (IPTR)es->address + stab->st_value;
686 else
687 info->Address = stab->st_value;
688 break;
690 info->Name = eo->symnames + stab->st_name;
691 info->SubType = subtype;
692 info->Binding = (ULONG)ELF32_ST_BIND(stab->st_info);
693 info->Size = stab->st_size;
694 return (TRUE);
696 return (FALSE);
699 static APTR loadprogram(struct ElfObject *eo)
700 /* load all sections into memory and relocate them */
702 static const char *FN = "loadprogram(): ";
703 struct ELFSection *s;
704 uint8 *p,*entry=NULL;
705 unsigned int i;
707 for (i=0; i<(eo->nsects-1); i++) {
708 if( (s = eo->sections[i]) != NULL ) {
709 BOOL text = !strcmp(s->name,".text"); /* .text section flag */
710 ULONG size = s->size;
712 /* align to 32 bytes and allocate 32-byte aligned memory */
713 size = (size+31)&~31;
714 if( (p = alloc32c(size)) != NULL ) {
715 s->address = (APTR)p; /* store section's base address */
716 if (!(s->flags & ElfSecF_NOBITS)) {
717 /* a PROGBITS section - load it from file */
719 // KPrintF("%sreading section %s\n",FN,s->name);
720 if (prstream(eo,s->offset,p,s->size)) {
721 if (text) {
722 /* get start address of PPC program in .text */
723 entry = p;
724 if ((*entry & 0xfc) == 0) {
725 // KPrintF("%sgcc traceback status word "
726 // "detected\n",FN);
727 entry += 4; /* 1st long reserved for gcc traceback word */
729 /* copy kernel stubs */
731 KPrintF("%sentry=0x%08lx, "
732 "invoking dynamic linker\n",FN,entry);
733 if (!dynamic_linker(i,eo,p)) {
734 entry = NULL;
735 break;
740 else {
741 entry = NULL;
742 break;
746 else {
747 KPrintF("Failed to allocate %ld bytes\n"
748 "for PPC %s section.",size,s->name);
749 entry = NULL;
750 break;
755 if (entry) {
756 if (!relocate(eo)) { /* relocate sections */
757 entry = NULL;
758 freeprogram(eo);
761 else
762 freeprogram(eo);
764 // KPrintF("%sreturning with entry=0x%08lx\n",FN,entry);
765 return (entry);
769 static void freeprogram(struct ElfObject *eo)
771 struct ELFSection *s;
772 unsigned int i;
774 for (i=0; i<eo->nsects; i++) {
775 if( (s = eo->sections[i]) != NULL ) {
776 if (s->address) {
777 free32(s->address);
778 s->address = NULL;
785 static BOOL relocate(struct ElfObject *eo)
787 struct ELFSection *es;
788 unsigned int shndx;
790 for (shndx=0; shndx<(eo->nsects-1); shndx++) {
791 if( (es = eo->sections[shndx]) != NULL ) {
792 BOOL rela = (es->flags & ElfSecF_RELA) != 0;
793 struct Elf32_Rela *r;
794 int i;
796 // KPrintF("relocate(): relocating section %s "
797 // "at 0x%08lx\n",es->name,es->address);
798 for (i=0,r=es->relocs; i<es->nrel; i++,r++) {
799 struct Elf32_Sym *sym = &eo->symtab[ELF32_R_SYM(r->r_info)];
800 long s = (long)eo->sections[sym->st_shndx]->address + sym->st_value;
801 uint8 *p = (uint8 *)es->address + r->r_offset;
803 switch (ELF32_R_TYPE(r->r_info)) {
804 case R_PPC_NONE:
805 break;
807 case R_PPC_ADDR32:
808 if (rela)
809 *(long *)p = s + r->r_addend;
810 else
811 *(long *)p += s;
812 break;
814 case R_PPC_ADDR16:
815 if (rela)
816 *(short *)p = s + r->r_addend;
817 else
818 *(short *)p += s;
819 break;
821 case R_PPC_ADDR16_LO:
822 if (rela)
823 *(short *)p = (s + r->r_addend) & 0xffff;
824 else
825 *(short *)p = (s + *(short *)p) & 0xffff;
826 break;
828 case R_PPC_ADDR16_HI:
829 if (rela)
830 *(short *)p = (s + r->r_addend) >> 16;
831 else
832 *(short *)p = (s + *(short *)p) >> 16;
833 break;
835 case R_PPC_ADDR16_HA:
836 if (rela)
837 s += r->r_addend;
838 else
839 s += *(short *)p;
840 *(short *)p = (s>>16) + ((s&0x8000) ? 1 : 0);
841 break;
843 case R_PPC_REL24:
844 if (rela) {
845 s = (s + r->r_addend) - (long)p;
847 else {
848 if (*p & 0x02)
849 s = (s + ((*(long *)p & 0x03fffffc) - 0x04000000)) - (long)p;
850 else
851 s = (s + (*(long *)p & 0x03fffffc)) - (long)p;
853 *(unsigned long *)p = (*(unsigned long *)p & 0xfc000003) |
854 ((unsigned long)s & 0x03fffffc);
855 break;
857 case R_PPC_REL32:
858 if (rela)
859 *(long *)p = (s + r->r_addend) - (long)p;
860 else
861 *(long *)p = (s + *(long *)p) - (long)p;
862 break;
864 default:
865 KPrintF("Relocation type %s\nat %s+%ld referencing\n"
866 "symbol %s+%ld\nis not supported.",
867 reloc_name[ELF32_R_TYPE(r->r_info)],es->name,r->r_offset,
868 eo->symnames+sym->st_name,sym->st_value);
869 return (FALSE);
874 return (TRUE);
877 static void*
878 alloc32( size_t size )
880 return AHIAllocVec( size, MEMF_ANY );
883 static void*
884 alloc32c( size_t size )
886 return AHIAllocVec( size, MEMF_ANY | MEMF_CLEAR );
889 void
890 free32( void* addr )
892 AHIFreeVec( addr );
896 static void*
897 allocstr( const char* string )
899 void* mem;
901 mem = AllocVec( strlen( string ) + 1, MEMF_ANY );
903 if( mem != NULL )
905 strcpy( mem, string );
908 return mem;
912 static BPTR
913 opstream(struct ElfObject *eo, const char* name )
915 BPTR handle = NULL;
917 if( name != NULL )
919 handle = Open( (char*) name, MODE_OLDFILE );
922 return (handle);
926 static BOOL
927 clstream(struct ElfObject *eo)
929 Close( eo->handle );
930 return TRUE;
934 static BOOL
935 rdstream(struct ElfObject *eo,void *buf,long len)
937 long r;
939 r = Read( eo->handle, buf, len );
941 if( r != len )
943 return (FALSE);
945 return (TRUE);
949 static long
950 skstream(struct ElfObject *eo,long offs,long mode)
952 long r;
954 r = Seek( eo->handle, offs, mode );
955 return (r);
959 static BOOL
960 prstream(struct ElfObject *eo,long offs,void *buf,long len)
961 /* position and read stream */
963 if (skstream(eo,offs,OFFSET_BEGINNING) != -1)
964 return (rdstream(eo,buf,len));
965 return FALSE;
969 static void *readsection(struct ElfObject *eo,struct Elf32_Shdr *sh)
970 /* allocate memory and read section contents */
972 void *p;
974 if( (p = AllocVec(sh->sh_size,MEMF_ANY)) != NULL )
975 if (prstream(eo,sh->sh_offset,p,sh->sh_size))
976 return (p);
977 return (NULL);
981 static struct ELFSection *progsection(struct ElfObject *eo,
982 struct Elf32_Shdr *sh)
983 /* Create Section structure from Elf32_Shdr. The contents of these */
984 /* sections will be loaded and relocated on demand, e.g. if a new task */
985 /* is created. */
987 struct ELFSection *s;
989 if( (s = AllocVec(sizeof(struct ELFSection),MEMF_ANY)) != NULL ) {
990 memset(s,0,sizeof(struct ELFSection));
991 s->name = eo->secnames + sh->sh_name;
992 s->flags = sh->sh_type==SHT_NOBITS ? ElfSecF_NOBITS:0;
993 s->alignment = (uint8)sh->sh_addralign;
994 s->offset = sh->sh_offset;
995 s->size = sh->sh_size;
996 return (s);
998 return (NULL);
1002 static BOOL common_symbols(struct ElfObject *eo)
1003 /* Create a and initialize Section structure for Common symbols. */
1005 static const char *FN = "common_symbols(): ";
1006 static const char *bssname = ".bss";
1007 struct ELFSection *s = NULL;
1008 struct Elf32_Sym *sym;
1009 uint16 *relocp;
1010 uint32 offset = 0,idx = 0,cnt=0;
1011 unsigned int i;
1013 /* First try to find a .bss, where Common symbols could be appended */
1014 for (i=0; i<(eo->nsects-1); i++) {
1015 if( (s = eo->sections[i]) != NULL ) {
1016 if (!strcmp(s->name,bssname) && (s->flags & ElfSecF_NOBITS)) {
1017 idx = i;
1018 offset = s->size;
1019 // KPrintF("%sfound %s at index %ld with size=%ld\n",
1020 // FN,bssname,idx,offset);
1021 break;
1023 else
1024 s = NULL;
1028 if (!s) {
1029 /* No .bss section present, allocate an own one */
1030 if( (s = AllocVec(sizeof(struct ELFSection),MEMF_ANY)) != NULL ) {
1031 memset(s,0,sizeof(struct ELFSection));
1032 s->name = allocstr((char *)bssname);
1033 s->flags = ElfSecF_NOBITS;
1034 s->alignment = 32;
1035 offset = 0;
1036 idx = eo->nsects-1;
1037 eo->sections[idx] = s;
1038 // KPrintF("%screated new %s at index %ld\n",FN,bssname,idx);
1040 else
1041 return (FALSE);
1044 /* Ok, search for COMMON symbols now */
1045 for (i=1,sym=&eo->symtab[1]; i<eo->nsyms; i++,sym++) {
1046 if (sym->st_shndx == SHN_COMMON) {
1047 offset = (offset + sym->st_value-1) & ~(sym->st_value-1);
1048 sym->st_value = offset;
1049 sym->st_shndx = idx;
1050 offset += sym->st_size;
1051 cnt++;
1054 // KPrintF("%sassigned %ld common symbols (%ld bytes)\n",
1055 // FN,cnt,offset-s->size);
1056 s->size = offset; /* set new .bss section size */
1058 return (TRUE);
1062 static BOOL getrelocs(struct ElfObject *eo,struct Elf32_Shdr *sh)
1063 /* read relocation entries for a section */
1065 uint32 rsize = sh->sh_entsize;
1066 int nrelocs = (int)(sh->sh_size/rsize);
1067 struct ELFSection *s = eo->sections[sh->sh_info];
1070 s->nrel = nrelocs;
1071 if (sh->sh_type == SHT_RELA) {
1072 s->flags |= ElfSecF_RELA;
1073 if( (s->relocs = readsection(eo,sh)) != NULL )
1074 return (TRUE);
1076 else {
1077 struct Elf32_Rela *r;
1079 if ((r = s->relocs = AllocVec(nrelocs*sizeof(struct Elf32_Rela),
1080 MEMF_ANY)) &&
1081 (skstream(eo,sh->sh_offset,OFFSET_BEGINNING) != -1)) {
1082 while (nrelocs--) {
1083 r->r_addend = 0;
1084 if (!rdstream(eo,r,sizeof(struct Elf32_Rel)))
1085 return (FALSE);
1086 r++;
1088 return (TRUE);
1091 return (FALSE);