Fix IRQ name
[AROS.git] / workbench / devs / AHI / Device / elfloader.c
blob6d5a035e54d7d6abfce892301e840627d996cc9f
1 /*
2 AHI - Hardware independent audio subsystem
3 Copyright (C) 1996-2005 Martin Blom <martin@blom.org>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
18 MA 02139, USA.
22 ** Based on code from the ppc.library emulator by Frank Wille:
23 ** ppc.library emulation
24 ** (c)1998-99 Frank Wille <frank@phoenix.owl.de>
28 #include <exec/types.h>
29 #include <exec/memory.h>
30 #include <exec/nodes.h>
31 #include <dos/dos.h>
32 #include <proto/dos.h>
33 #include <proto/exec.h>
35 // Even though this is WarpUp only, we still need a few defines from PowerUp...
36 #include <powerup/ppclib/object.h>
38 #include <string.h>
40 #include "ahi_def.h"
41 #include "elfloader.h"
42 #include "misc.h"
44 /*** elfcommon.h *************************************************************/
46 /* e_indent indexes */
47 #define EI_NIDENT 16
48 #define EI_MAG0 0
49 #define EI_MAG1 1
50 #define EI_MAG2 2
51 #define EI_MAG3 3
52 #define EI_CLASS 4
53 #define EI_DATA 5
54 #define EI_VERSION 6
55 #define EI_PAD 7
57 /* EI_CLASS */
58 #define ELFCLASSNONE 0
59 #define ELFCLASS32 1
60 #define ELFCLASS64 2
62 /* EI_DATA */
63 #define ELFDATANONE 0
64 #define ELFDATA2LSB 1
65 #define ELFDATA2MSB 2
67 /* e_type */
68 #define ET_NONE 0 /* No file type */
69 #define ET_REL 1 /* Relocatable file */
70 #define ET_EXEC 2 /* Executable file */
71 #define ET_DYN 3 /* Shared object file */
72 #define ET_CORE 4 /* Core file */
73 #define ET_LOPROC 0xFF00 /* Processor-specific */
74 #define ET_HIPROC 0xFFFF /* Processor-specific */
76 /* e_version */
77 #define EV_NONE 0
78 #define EV_CURRENT 1
80 /* e_machine */
81 #define EM_NONE 0
82 #define EM_M32 1
83 #define EM_SPARC 2
84 #define EM_386 3
85 #define EM_68K 4
86 #define EM_88K 5
87 #define EM_860 7
88 #define EM_MIPS 8
89 #define EM_MIPS_RS4_BE 10
90 #define EM_SPARC64 11
91 #define EM_PARISC 15
92 #define EM_PPC_OLD 17
93 #define EM_SPARC32PLUS 18
94 #define EM_PPC 20
95 #define EM_CYGNUS_POWERPC 0x9025
96 #define EM_ALPHA 0x9026
98 /* values for program header, p_type field */
99 #define PT_NULL 0 /* Program header table entry unused */
100 #define PT_LOAD 1 /* Loadable program segment */
101 #define PT_DYNAMIC 2 /* Dynamic linking information */
102 #define PT_INTERP 3 /* Program interpreter */
103 #define PT_NOTE 4 /* Auxiliary information */
104 #define PT_SHLIB 5 /* Reserved, unspecified semantics */
105 #define PT_PHDR 6 /* Entry for header table itself */
106 #define PT_LOPROC 0x70000000 /* Processor-specific */
107 #define PT_HIPROC 0x7FFFFFFF /* Processor-specific */
109 /* Program segment permissions, in program header p_flags field */
110 #define PF_X (1 << 0) /* Segment is executable */
111 #define PF_W (1 << 1) /* Segment is writable */
112 #define PF_R (1 << 2) /* Segment is readable */
113 #define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */
115 /* special sections indexes */
116 #define SHN_UNDEF 0
117 #define SHN_ABS 0xfff1
118 #define SHN_COMMON 0xfff2
120 /* sh_type */
121 #define SHT_NULL 0 /* Section header table entry unused */
122 #define SHT_PROGBITS 1 /* Program specific (private) data */
123 #define SHT_SYMTAB 2 /* Link editing symbol table */
124 #define SHT_STRTAB 3 /* A string table */
125 #define SHT_RELA 4 /* Relocation entries with addends */
126 #define SHT_HASH 5 /* A symbol hash table */
127 #define SHT_DYNAMIC 6 /* Information for dynamic linking */
128 #define SHT_NOTE 7 /* Information that marks file */
129 #define SHT_NOBITS 8 /* Section occupies no space in file */
130 #define SHT_REL 9 /* Relocation entries, no addends */
131 #define SHT_SHLIB 10 /* Reserved, unspecified semantics */
132 #define SHT_DYNSYM 11 /* Dynamic linking symbol table */
133 #define SHT_LOPROC 0x70000000 /* Processor-specific semantics, lo */
134 #define SHT_HIPROC 0x7FFFFFFF /* Processor-specific semantics, hi */
135 #define SHT_LOUSER 0x80000000 /* Application-specific semantics */
136 #define SHT_HIUSER 0x8FFFFFFF /* Application-specific semantics */
138 /* sh_flags */
139 #define SHF_WRITE (1 << 0) /* Writable data during execution */
140 #define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
141 #define SHF_EXECINSTR (1 << 2) /* Executable machine instructions */
142 #define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */
144 /* Values of note segment descriptor types for core files. */
145 #define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
146 #define NT_FPREGSET 2 /* Contains copy of fpregset struct */
147 #define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
149 #define STN_UNDEF 0 /* undefined symbol index */
151 /* ST_BIND */
152 #define STB_LOCAL 0 /* Symbol not visible outside obj */
153 #define STB_GLOBAL 1 /* Symbol visible outside obj */
154 #define STB_WEAK 2 /* Like globals, lower precedence */
155 #define STB_LOPROC 13 /* Application-specific semantics */
156 #define STB_HIPROC 15 /* Application-specific semantics */
158 /* ST_TYPE */
159 #define STT_NOTYPE 0 /* Symbol type is unspecified */
160 #define STT_OBJECT 1 /* Symbol is a data object */
161 #define STT_FUNC 2 /* Symbol is a code object */
162 #define STT_SECTION 3 /* Symbol associated with a section */
163 #define STT_FILE 4 /* Symbol gives a file name */
164 #define STT_LOPROC 13 /* Application-specific semantics */
165 #define STT_HIPROC 15 /* Application-specific semantics */
167 /* Dynamic section tags */
168 #define DT_NULL 0
169 #define DT_NEEDED 1
170 #define DT_PLTRELSZ 2
171 #define DT_PLTGOT 3
172 #define DT_HASH 4
173 #define DT_STRTAB 5
174 #define DT_SYMTAB 6
175 #define DT_RELA 7
176 #define DT_RELASZ 8
177 #define DT_RELAENT 9
178 #define DT_STRSZ 10
179 #define DT_SYMENT 11
180 #define DT_INIT 12
181 #define DT_FINI 13
182 #define DT_SONAME 14
183 #define DT_RPATH 15
184 #define DT_SYMBOLIC 16
185 #define DT_REL 17
186 #define DT_RELSZ 18
187 #define DT_RELENT 19
188 #define DT_PLTREL 20
189 #define DT_DEBUG 21
190 #define DT_TEXTREL 22
191 #define DT_JMPREL 23
192 #define DT_LOPROC 0x70000000
193 #define DT_HIPROC 0x7fffffff
195 /*** elf32.h *****************************************************************/
197 typedef unsigned char uint8;
198 typedef unsigned short uint16;
199 typedef unsigned long uint32;
202 struct Elf32_Ehdr {
203 unsigned char e_ident[EI_NIDENT];
204 uint16 e_type;
205 uint16 e_machine;
206 uint32 e_version;
207 uint32 e_entry;
208 uint32 e_phoff;
209 uint32 e_shoff;
210 uint32 e_flags;
211 uint16 e_ehsize;
212 uint16 e_phentsize;
213 uint16 e_phnum;
214 uint16 e_shentsize;
215 uint16 e_shnum;
216 uint16 e_shstrndx;
219 struct Elf32_Shdr {
220 uint32 sh_name;
221 uint32 sh_type;
222 uint32 sh_flags;
223 uint32 sh_addr;
224 uint32 sh_offset;
225 uint32 sh_size;
226 uint32 sh_link;
227 uint32 sh_info;
228 uint32 sh_addralign;
229 uint32 sh_entsize;
232 struct Elf32_Sym {
233 uint32 st_name;
234 uint32 st_value;
235 uint32 st_size;
236 uint8 st_info;
237 uint8 st_other;
238 uint16 st_shndx;
241 /* st_info */
242 #define ELF32_ST_BIND(i) ((i)>>4)
243 #define ELF32_ST_TYPE(i) ((i)&0xf)
244 #define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
246 struct Elf32_Rel {
247 uint32 r_offset;
248 uint32 r_info;
251 struct Elf32_Rela {
252 uint32 r_offset;
253 uint32 r_info;
254 uint32 r_addend;
257 /* r_info */
258 #define ELF32_R_SYM(i) ((i)>>8)
259 #define ELF32_R_TYPE(i) ((unsigned char)(i))
260 #define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t))
262 /*** elfobject.h *************************************************************/
264 struct ELFSection { /* prog. sections for new tasks */
265 char *name;
266 APTR address; /* physical RAM address or NULL */
267 UWORD flags;
268 UWORD alignment;
269 long offset; /* file offset and section size */
270 ULONG size;
271 int nrel; /* number of relocs */
272 struct Elf32_Rela *relocs; /* array of Elf32_Rela structs */
275 #define ElfSecB_NOBITS 0 /* bss section */
276 #define ElfSecF_NOBITS 1
277 #define ElfSecB_RELA 1 /* Relocs are of .rela type */
278 #define ElfSecF_RELA 2
281 struct ElfObject {
282 // struct Node n; /* contains object's name ptr */
283 UWORD flags;
284 // struct PPCLibBase *ppcbase;
285 // void *pool; /* pooled memory for object data */
286 BPTR handle; /* ELF file handle */
287 // APTR handle; /* ELF file handle */
288 // struct Hook *hook; /* hook functions for read/seek */
289 // struct Hook defaultHook;
290 char *secnames; /* .shstrtab - section names */
291 char *symnames; /* .strtab - symbol mames */
292 struct Elf32_Ehdr *header; /* the ELF file header */
293 struct Elf32_Sym *symtab; /* .symtab - symbol table */
294 uint32 nsyms; /* number of symbols */
295 uint32 gsyms; /* first global symbol */
296 struct ELFSection **sections; /* ELFSection pointers */
297 uint32 nsects; /* number of sections */
298 // struct SignalSemaphore ElfSS; /* ElfObject access arbitration */
301 #define ElfObjB_Relocated 0 /* Object is relocated */
302 #define ElfObjF_Relocated 1
304 /*** relocnames.c ************************************************************/
306 const char *reloc_name[] = {
307 "R_NONE",
308 "R_PPC_ADDR32",
309 "R_PPC_ADDR24",
310 "R_PPC_ADDR16",
311 "R_PPC_ADDR16_LO",
312 "R_PPC_ADDR16_HI",
313 "R_PPC_ADDR16_HA",
314 "R_PPC_ADDR14",
315 "R_PPC_ADDR14_BRTAKEN",
316 "R_PPC_ADDR14_BRNTAKEN",
317 "R_PPC_REL24",
318 "R_PPC_REL14",
319 "R_PPC_REL14_BRTAKEN",
320 "R_PPC_REL14_BRNTAKEN",
321 "R_PPC_GOT16",
322 "R_PPC_GOT16_LO",
323 "R_PPC_GOT16_HI",
324 "R_PPC_GOT16_HA",
325 "R_PPC_PLTREL24",
326 "R_PPC_COPY",
327 "R_PPC_GLOB_DAT",
328 "R_PPC_JMP_SLOT",
329 "R_PPC_RELATIVE",
330 "R_PPC_LOCAL24PC",
331 "R_PPC_UADDR32",
332 "R_PPC_UADDR16",
333 "R_PPC_REL32",
334 "R_PPC_PLT32",
335 "R_PPC_PLTREL32",
336 "R_PPC_PLT16_LO",
337 "R_PPC_PLT16_HI",
338 "R_PPC_PLT16_HA",
339 "R_PPC_SDAREL16",
340 "R_PPC_SECTOFF",
341 "R_PPC_SECTOFF_LO",
342 "R_PPC_SECTOFF_HI",
343 "R_PPC_SECTOFF_HA"
346 /*** ppcobject.c *************************************************************/
349 /* Bug fix for powerup/ppclib/object.h */
350 #ifdef R_PPC_ADDR16_L
351 #ifndef R_PPC_ADDR16_LO
352 #define R_PPC_ADDR16_LO R_PPC_ADDR16_L
353 #endif
354 #endif
356 static void
357 freeelfobj(struct ElfObject *elfobj);
359 static BOOL
360 loadelf32(struct ElfObject *eo,struct Elf32_Shdr *shdrs);
362 static BOOL
363 scanElfSymbols(struct ElfObject *eo,struct PPCObjectInfo *info,
364 BOOL relmode);
366 static BOOL
367 getsyminfo(struct ElfObject *eo,struct PPCObjectInfo *info,
368 struct Elf32_Sym *stab);
370 static APTR
371 loadprogram(struct ElfObject *eo);
373 static void
374 freeprogram(struct ElfObject *eo);
376 static BOOL
377 relocate(struct ElfObject *eo);
379 static void*
380 allocstr( const char* string );
382 static void*
383 alloc32c( size_t size );
385 static void*
386 alloc32( size_t size );
388 void
389 free32( void* addr );
391 static BPTR
392 opstream(struct ElfObject *eo, const char* name );
394 static BOOL
395 clstream(struct ElfObject *eo);
397 static BOOL
398 rdstream(struct ElfObject *eo,void *buf,long len);
400 static long
401 skstream(struct ElfObject *eo,long offs,long mode);
403 static BOOL
404 prstream(struct ElfObject *eo,long offs,void *buf,long len);
406 static void*
407 readsection(struct ElfObject *eo,struct Elf32_Shdr *sh);
409 static struct ELFSection*
410 progsection(struct ElfObject *eo, struct Elf32_Shdr *sh);
412 static BOOL
413 common_symbols(struct ElfObject *eo);
415 static BOOL
416 getrelocs(struct ElfObject *eo,struct Elf32_Shdr *sh);
418 static const char ELFid[4] = {
419 0x7f,'E','L','F'
422 void*
423 ELFLoadObject( const char* objname )
425 struct ElfObject *elfobj = NULL;
427 /* allocate ElfObject structure */
429 elfobj = alloc32( sizeof( struct ElfObject ) );
431 if( elfobj != NULL )
433 memset(elfobj,0,sizeof(struct ElfObject));
435 elfobj->header = alloc32( sizeof( struct Elf32_Ehdr ) );
437 if( elfobj->header != NULL )
439 /* open ELF stream for reading */
441 elfobj->handle = opstream( elfobj, objname );
443 if( elfobj->handle != NULL )
445 /* read and identify ELF 32bit PowerPC BigEndian header */
447 if( rdstream( elfobj, elfobj->header, sizeof(struct Elf32_Ehdr) ) )
449 struct Elf32_Ehdr *hdr = elfobj->header;
451 if (!strncmp(hdr->e_ident,ELFid,4) &&
452 hdr->e_ident[EI_CLASS]==ELFCLASS32 &&
453 hdr->e_ident[EI_DATA]==ELFDATA2MSB &&
454 hdr->e_ident[EI_VERSION]==1 && hdr->e_version==1 &&
455 (hdr->e_machine==EM_PPC || hdr->e_machine==EM_PPC_OLD ||
456 hdr->e_machine==EM_CYGNUS_POWERPC) && hdr->e_type==ET_REL)
458 struct Elf32_Shdr *shdrs;
459 ULONG shdrsize = (ULONG) hdr->e_shnum * (ULONG) hdr->e_shentsize;
461 // KPrintF("elf32ppcbe format recognized\n");
463 shdrs = alloc32( shdrsize );
465 if( shdrs != NULL )
467 /* read section header table and parse rest of object */
469 if( prstream( elfobj, hdr->e_shoff, shdrs, shdrsize ) )
471 if( loadelf32( elfobj, shdrs ) )
473 void* start;
474 // KPrintF("ELF object loaded (0x%08lx)\n", elfobj );
475 start = loadprogram( elfobj );
476 // KPrintF("Start of PPC code: 0x%08lx\n", start );
477 free32( shdrs );
478 return (elfobj);
481 free32( shdrs );
484 else
485 KPrintF( "Not an ELF32-PPC-BE\nrelocatable object.");
488 freeelfobj(elfobj);
492 return (NULL);
496 void
497 ELFUnLoadObject( void* obj )
499 struct ElfObject* elfobj = (struct ElfObject*) obj;
501 if(elfobj->sections != NULL && elfobj->nsects > 0 )
503 freeprogram(elfobj);
506 freeelfobj(elfobj);
509 BOOL
510 ELFGetSymbol( void* obj,
511 const char* name,
512 void** ptr )
514 struct PPCObjectInfo oi =
517 NULL,
518 PPCELFINFOTYPE_SYMBOL,
519 STT_SECTION,
520 STB_GLOBAL,
524 BOOL rc;
526 oi.Name = (char*) name;
527 rc = scanElfSymbols( (struct ElfObject*) obj, &oi, FALSE );
529 if( rc )
531 *ptr = (void*) oi.Address;
534 return rc;
538 static void freeelfobj(struct ElfObject *elfobj)
539 /* free all memory connected to an ElfObject */
541 if (elfobj) {
542 if (elfobj->handle)
543 clstream(elfobj);
544 free32(elfobj);
549 static BOOL loadelf32(struct ElfObject *eo,struct Elf32_Shdr *shdrs)
550 /* parse ELF object, initialize ElfObject structure */
552 struct Elf32_Ehdr *hdr = eo->header;
553 struct ELFSection *s;
554 uint16 i;
556 if ((eo->secnames = readsection(eo,&shdrs[hdr->e_shstrndx])) &&
557 (eo->sections = alloc32((hdr->e_shnum+1)*sizeof(void *)))) {
558 memset(eo->sections,0,(hdr->e_shnum+1)*sizeof(void *));
559 eo->nsects = hdr->e_shnum + 1; /* +1 section for COMMON symbols */
560 for (i=1; i<hdr->e_shnum; i++) {
561 switch (shdrs[i].sh_type) {
562 case SHT_PROGBITS:
563 case SHT_NOBITS:
564 if (!(eo->sections[i] = progsection(eo,&shdrs[i])))
565 return (FALSE);
566 break;
567 case SHT_SYMTAB:
568 if (!(eo->symnames = readsection(eo,&shdrs[shdrs[i].sh_link]))
569 || !(eo->symtab = readsection(eo,&shdrs[i])))
570 return (FALSE);
571 eo->nsyms = shdrs[i].sh_size / sizeof(struct Elf32_Sym);
572 eo->gsyms = shdrs[i].sh_info;
573 break;
574 default:
575 break;
578 for (i=1; i<hdr->e_shnum; i++) {
579 switch (shdrs[i].sh_type) {
580 case SHT_REL:
581 case SHT_RELA:
582 if (!getrelocs(eo,&shdrs[i]))
583 return (FALSE);
584 break;
585 default:
586 break;
589 /* allocate space for Common symbols */
590 return (common_symbols(eo));
592 return (FALSE);
596 static BOOL scanElfSymbols(struct ElfObject *eo,struct PPCObjectInfo *info,
597 BOOL relmode)
598 /* Find an ELF symbol by its name or address and return all infos */
599 /* in the supplied PPCObjectInfo structure. Return FALSE if symbol */
600 /* doesn't exist. */
601 /* ATTENTION: PPCLibBase may be locked at that stage! */
603 ULONG addr = info->Address;
604 char *name = info->Name;
605 //KPrintF( "scanElfSymbols( 0x%08lx, 0x%08lx, %ld\n", eo, info, relmode );
606 if (relmode) {
607 unsigned int i;
608 int j;
609 struct ELFSection *es;
610 struct Elf32_Rela *r;
612 for (i=1; i<(eo->nsects-1); i++) {
613 if( (es = eo->sections[i]) != NULL ) {
614 for (j=0,r=es->relocs; j<es->nrel; j++,r++) {
615 if (getsyminfo(eo,info,&eo->symtab[ELF32_R_SYM(r->r_info)])) {
616 info->Address = (ULONG)es->address + r->r_offset;
617 info->Type = PPCELFINFOTYPE_RELOC;
618 info->SubType = (ULONG)ELF32_R_TYPE(r->r_info);
619 if (info->Address == addr) {
620 if (name) {
621 if (!strcmp(name,info->Name))
622 return (TRUE);
624 else
625 return (TRUE);
633 else {
634 struct Elf32_Sym *stab = eo->symtab;
635 int i = eo->nsyms;
636 while (--i) {
637 //KPrintF( "i=%ld\n", i );
638 if (getsyminfo(eo,info,++stab)) {
639 if (!name) {
640 if (info->Size) {
641 if (addr>=info->Address && addr<(info->Address+info->Size))
642 return (TRUE);
644 else {
645 if (addr == info->Address)
646 return (TRUE);
649 else {
650 //KPrintF( "comparing %s and %s\n", name,info->Name );
651 if (!strcmp(name,info->Name))
652 return (TRUE);
657 return (FALSE);
661 static BOOL getsyminfo(struct ElfObject *eo,struct PPCObjectInfo *info,
662 struct Elf32_Sym *stab)
664 struct ELFSection *es;
665 ULONG subtype;
667 subtype = (ULONG)ELF32_ST_TYPE(stab->st_info);
668 if (subtype < STT_FILE) {
669 info->Type = subtype==STT_SECTION ? PPCELFINFOTYPE_SECTION
670 : PPCELFINFOTYPE_SYMBOL;
671 switch (stab->st_shndx) {
672 case SHN_UNDEF:
673 /* undefined symbols will disappear after relocation */
674 case SHN_ABS:
675 info->Address = stab->st_value;
676 break;
677 case SHN_COMMON:
678 /* @@@ common symbols should have disappeared after common_symbols() */
679 info->Type = PPCELFINFOTYPE_COMSYMBOL;
680 info->Address = 0;
681 break;
682 default:
683 if( (es = eo->sections[stab->st_shndx]) != NULL )
684 info->Address = (ULONG)es->address + stab->st_value;
685 else
686 info->Address = stab->st_value;
687 break;
689 info->Name = eo->symnames + stab->st_name;
690 info->SubType = subtype;
691 info->Binding = (ULONG)ELF32_ST_BIND(stab->st_info);
692 info->Size = stab->st_size;
693 return (TRUE);
695 return (FALSE);
698 static APTR loadprogram(struct ElfObject *eo)
699 /* load all sections into memory and relocate them */
701 static const char *FN = "loadprogram(): ";
702 struct ELFSection *s;
703 uint8 *p,*entry=NULL;
704 unsigned int i;
706 for (i=0; i<(eo->nsects-1); i++) {
707 if( (s = eo->sections[i]) != NULL ) {
708 BOOL text = !strcmp(s->name,".text"); /* .text section flag */
709 ULONG size = s->size;
711 /* align to 32 bytes and allocate 32-byte aligned memory */
712 size = (size+31)&~31;
713 if( (p = alloc32c(size)) != NULL ) {
714 s->address = (APTR)p; /* store section's base address */
715 if (!(s->flags & ElfSecF_NOBITS)) {
716 /* a PROGBITS section - load it from file */
718 // KPrintF("%sreading section %s\n",FN,s->name);
719 if (prstream(eo,s->offset,p,s->size)) {
720 if (text) {
721 /* get start address of PPC program in .text */
722 entry = p;
723 if ((*entry & 0xfc) == 0) {
724 // KPrintF("%sgcc traceback status word "
725 // "detected\n",FN);
726 entry += 4; /* 1st long reserved for gcc traceback word */
728 /* copy kernel stubs */
730 KPrintF("%sentry=0x%08lx, "
731 "invoking dynamic linker\n",FN,entry);
732 if (!dynamic_linker(i,eo,p)) {
733 entry = NULL;
734 break;
739 else {
740 entry = NULL;
741 break;
745 else {
746 KPrintF("Failed to allocate %ld bytes\n"
747 "for PPC %s section.",size,s->name);
748 entry = NULL;
749 break;
754 if (entry) {
755 if (!relocate(eo)) { /* relocate sections */
756 entry = NULL;
757 freeprogram(eo);
760 else
761 freeprogram(eo);
763 // KPrintF("%sreturning with entry=0x%08lx\n",FN,entry);
764 return (entry);
768 static void freeprogram(struct ElfObject *eo)
770 struct ELFSection *s;
771 unsigned int i;
773 for (i=0; i<eo->nsects; i++) {
774 if( (s = eo->sections[i]) != NULL ) {
775 if (s->address) {
776 free32(s->address);
777 s->address = NULL;
784 static BOOL relocate(struct ElfObject *eo)
786 struct ELFSection *es;
787 unsigned int shndx;
789 for (shndx=0; shndx<(eo->nsects-1); shndx++) {
790 if( (es = eo->sections[shndx]) != NULL ) {
791 BOOL rela = (es->flags & ElfSecF_RELA) != 0;
792 struct Elf32_Rela *r;
793 int i;
795 // KPrintF("relocate(): relocating section %s "
796 // "at 0x%08lx\n",es->name,es->address);
797 for (i=0,r=es->relocs; i<es->nrel; i++,r++) {
798 struct Elf32_Sym *sym = &eo->symtab[ELF32_R_SYM(r->r_info)];
799 long s = (long)eo->sections[sym->st_shndx]->address + sym->st_value;
800 uint8 *p = (uint8 *)es->address + r->r_offset;
802 switch (ELF32_R_TYPE(r->r_info)) {
803 case R_PPC_NONE:
804 break;
806 case R_PPC_ADDR32:
807 if (rela)
808 *(long *)p = s + r->r_addend;
809 else
810 *(long *)p += s;
811 break;
813 case R_PPC_ADDR16:
814 if (rela)
815 *(short *)p = s + r->r_addend;
816 else
817 *(short *)p += s;
818 break;
820 case R_PPC_ADDR16_LO:
821 if (rela)
822 *(short *)p = (s + r->r_addend) & 0xffff;
823 else
824 *(short *)p = (s + *(short *)p) & 0xffff;
825 break;
827 case R_PPC_ADDR16_HI:
828 if (rela)
829 *(short *)p = (s + r->r_addend) >> 16;
830 else
831 *(short *)p = (s + *(short *)p) >> 16;
832 break;
834 case R_PPC_ADDR16_HA:
835 if (rela)
836 s += r->r_addend;
837 else
838 s += *(short *)p;
839 *(short *)p = (s>>16) + ((s&0x8000) ? 1 : 0);
840 break;
842 case R_PPC_REL24:
843 if (rela) {
844 s = (s + r->r_addend) - (long)p;
846 else {
847 if (*p & 0x02)
848 s = (s + ((*(long *)p & 0x03fffffc) - 0x04000000)) - (long)p;
849 else
850 s = (s + (*(long *)p & 0x03fffffc)) - (long)p;
852 *(unsigned long *)p = (*(unsigned long *)p & 0xfc000003) |
853 ((unsigned long)s & 0x03fffffc);
854 break;
856 case R_PPC_REL32:
857 if (rela)
858 *(long *)p = (s + r->r_addend) - (long)p;
859 else
860 *(long *)p = (s + *(long *)p) - (long)p;
861 break;
863 default:
864 KPrintF("Relocation type %s\nat %s+%ld referencing\n"
865 "symbol %s+%ld\nis not supported.",
866 reloc_name[ELF32_R_TYPE(r->r_info)],es->name,r->r_offset,
867 eo->symnames+sym->st_name,sym->st_value);
868 return (FALSE);
873 return (TRUE);
876 static void*
877 alloc32( size_t size )
879 return AHIAllocVec( size, MEMF_ANY );
882 static void*
883 alloc32c( size_t size )
885 return AHIAllocVec( size, MEMF_ANY | MEMF_CLEAR );
888 void
889 free32( void* addr )
891 AHIFreeVec( addr );
895 static void*
896 allocstr( const char* string )
898 void* mem;
900 mem = AllocVec( strlen( string ) + 1, MEMF_ANY );
902 if( mem != NULL )
904 strcpy( mem, string );
907 return mem;
911 static BPTR
912 opstream(struct ElfObject *eo, const char* name )
914 BPTR handle = NULL;
916 if( name != NULL )
918 handle = Open( (char*) name, MODE_OLDFILE );
921 return (handle);
925 static BOOL
926 clstream(struct ElfObject *eo)
928 Close( eo->handle );
929 return TRUE;
933 static BOOL
934 rdstream(struct ElfObject *eo,void *buf,long len)
936 long r;
938 r = Read( eo->handle, buf, len );
940 if( r != len )
942 return (FALSE);
944 return (TRUE);
948 static long
949 skstream(struct ElfObject *eo,long offs,long mode)
951 long r;
953 r = Seek( eo->handle, offs, mode );
954 return (r);
958 static BOOL
959 prstream(struct ElfObject *eo,long offs,void *buf,long len)
960 /* position and read stream */
962 if (skstream(eo,offs,OFFSET_BEGINNING) != -1)
963 return (rdstream(eo,buf,len));
964 return FALSE;
968 static void *readsection(struct ElfObject *eo,struct Elf32_Shdr *sh)
969 /* allocate memory and read section contents */
971 void *p;
973 if( (p = AllocVec(sh->sh_size,MEMF_ANY)) != NULL )
974 if (prstream(eo,sh->sh_offset,p,sh->sh_size))
975 return (p);
976 return (NULL);
980 static struct ELFSection *progsection(struct ElfObject *eo,
981 struct Elf32_Shdr *sh)
982 /* Create Section structure from Elf32_Shdr. The contents of these */
983 /* sections will be loaded and relocated on demand, e.g. if a new task */
984 /* is created. */
986 struct ELFSection *s;
988 if( (s = AllocVec(sizeof(struct ELFSection),MEMF_ANY)) != NULL ) {
989 memset(s,0,sizeof(struct ELFSection));
990 s->name = eo->secnames + sh->sh_name;
991 s->flags = sh->sh_type==SHT_NOBITS ? ElfSecF_NOBITS:0;
992 s->alignment = (uint8)sh->sh_addralign;
993 s->offset = sh->sh_offset;
994 s->size = sh->sh_size;
995 return (s);
997 return (NULL);
1001 static BOOL common_symbols(struct ElfObject *eo)
1002 /* Create a and initialize Section structure for Common symbols. */
1004 static const char *FN = "common_symbols(): ";
1005 static const char *bssname = ".bss";
1006 struct ELFSection *s = NULL;
1007 struct Elf32_Sym *sym;
1008 uint16 *relocp;
1009 uint32 offset = 0,idx = 0,cnt=0;
1010 unsigned int i;
1012 /* First try to find a .bss, where Common symbols could be appended */
1013 for (i=0; i<(eo->nsects-1); i++) {
1014 if( (s = eo->sections[i]) != NULL ) {
1015 if (!strcmp(s->name,bssname) && (s->flags & ElfSecF_NOBITS)) {
1016 idx = i;
1017 offset = s->size;
1018 // KPrintF("%sfound %s at index %ld with size=%ld\n",
1019 // FN,bssname,idx,offset);
1020 break;
1022 else
1023 s = NULL;
1027 if (!s) {
1028 /* No .bss section present, allocate an own one */
1029 if( (s = AllocVec(sizeof(struct ELFSection),MEMF_ANY)) != NULL ) {
1030 memset(s,0,sizeof(struct ELFSection));
1031 s->name = allocstr((char *)bssname);
1032 s->flags = ElfSecF_NOBITS;
1033 s->alignment = 32;
1034 offset = 0;
1035 idx = eo->nsects-1;
1036 eo->sections[idx] = s;
1037 // KPrintF("%screated new %s at index %ld\n",FN,bssname,idx);
1039 else
1040 return (FALSE);
1043 /* Ok, search for COMMON symbols now */
1044 for (i=1,sym=&eo->symtab[1]; i<eo->nsyms; i++,sym++) {
1045 if (sym->st_shndx == SHN_COMMON) {
1046 offset = (offset + sym->st_value-1) & ~(sym->st_value-1);
1047 sym->st_value = offset;
1048 sym->st_shndx = idx;
1049 offset += sym->st_size;
1050 cnt++;
1053 // KPrintF("%sassigned %ld common symbols (%ld bytes)\n",
1054 // FN,cnt,offset-s->size);
1055 s->size = offset; /* set new .bss section size */
1057 return (TRUE);
1061 static BOOL getrelocs(struct ElfObject *eo,struct Elf32_Shdr *sh)
1062 /* read relocation entries for a section */
1064 uint32 rsize = sh->sh_entsize;
1065 int nrelocs = (int)(sh->sh_size/rsize);
1066 struct ELFSection *s = eo->sections[sh->sh_info];
1069 s->nrel = nrelocs;
1070 if (sh->sh_type == SHT_RELA) {
1071 s->flags |= ElfSecF_RELA;
1072 if( (s->relocs = readsection(eo,sh)) != NULL )
1073 return (TRUE);
1075 else {
1076 struct Elf32_Rela *r;
1078 if ((r = s->relocs = AllocVec(nrelocs*sizeof(struct Elf32_Rela),
1079 MEMF_ANY)) &&
1080 (skstream(eo,sh->sh_offset,OFFSET_BEGINNING) != -1)) {
1081 while (nrelocs--) {
1082 r->r_addend = 0;
1083 if (!rdstream(eo,r,sizeof(struct Elf32_Rel)))
1084 return (FALSE);
1085 r++;
1087 return (TRUE);
1090 return (FALSE);