home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 106 / EnigmaAmiga106CD.iso / software / sviluppo / ahisrc / device / elfloader.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-11  |  28.7 KB  |  1,085 lines

  1. /* $Id: elfloader.c,v 1.5 1999/09/11 08:22:20 lcs Exp $ */
  2.  
  3. /*
  4.      AHI - Hardware independent audio subsystem
  5.      Copyright (C) 1996-1999 Martin Blom <martin@blom.org>
  6.      
  7.      This library is free software; you can redistribute it and/or
  8.      modify it under the terms of the GNU Library General Public
  9.      License as published by the Free Software Foundation; either
  10.      version 2 of the License, or (at your option) any later version.
  11.      
  12.      This library is distributed in the hope that it will be useful,
  13.      but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.      Library General Public License for more details.
  16.      
  17.      You should have received a copy of the GNU Library General Public
  18.      License along with this library; if not, write to the
  19.      Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
  20.      MA 02139, USA.
  21. */
  22.  
  23. /*
  24. ** Based on code from the ppc.library emulator by Frank Wille:
  25. ** ppc.library emulation
  26. ** (c)1998-99 Frank Wille <frank@phoenix.owl.de>
  27. */
  28.  
  29.  
  30. #include <exec/types.h>
  31. #include <exec/memory.h>
  32. #include <exec/nodes.h>
  33. #include <dos/dos.h>
  34. #include <proto/dos.h>
  35. #include <proto/exec.h>
  36.  
  37. // Even though this is WarpUp only, we still need a few defines from PowerUp...
  38. #include <powerup/ppclib/object.h>
  39.  
  40. #include <string.h>
  41.  
  42. #include "elfloader.h"
  43. #include "misc.h"
  44.  
  45. /*** elfcommon.h *************************************************************/
  46.  
  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
  57.  
  58. /* EI_CLASS */
  59. #define ELFCLASSNONE 0
  60. #define ELFCLASS32   1
  61. #define ELFCLASS64   2
  62.  
  63. /* EI_DATA */
  64. #define ELFDATANONE 0
  65. #define ELFDATA2LSB 1
  66. #define ELFDATA2MSB 2
  67.  
  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 */
  76.  
  77. /* e_version */
  78. #define EV_NONE    0
  79. #define EV_CURRENT 1
  80.  
  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
  98.  
  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 */
  109.  
  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 */
  115.  
  116. /* special sections indexes */
  117. #define SHN_UNDEF 0
  118. #define SHN_ABS 0xfff1
  119. #define SHN_COMMON 0xfff2
  120.  
  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 */
  138.  
  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 */
  144.  
  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 */
  149.  
  150. #define STN_UNDEF 0                 /* undefined symbol index */
  151.  
  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 */
  158.  
  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 */
  167.  
  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
  195.  
  196. /*** elf32.h *****************************************************************/
  197.  
  198. typedef unsigned char uint8;
  199. typedef unsigned short uint16;
  200. typedef unsigned long uint32;
  201.  
  202.  
  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;
  218. };
  219.  
  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;
  231. };
  232.  
  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;
  240. };
  241.  
  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))
  246.  
  247. struct Elf32_Rel {
  248.   uint32 r_offset;
  249.   uint32 r_info;
  250. };
  251.  
  252. struct Elf32_Rela {
  253.   uint32 r_offset;
  254.   uint32 r_info;
  255.   uint32 r_addend;
  256. };
  257.  
  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))
  262.  
  263. /*** elfobject.h *************************************************************/
  264.  
  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 */
  274. };
  275.  
  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
  280.  
  281.  
  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 */
  300. };
  301.  
  302. #define ElfObjB_Relocated       0       /* Object is relocated */
  303. #define ElfObjF_Relocated       1
  304.  
  305. /*** relocnames.c ************************************************************/
  306.  
  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"
  345. };
  346.  
  347. /*** ppcobject.c *************************************************************/
  348.  
  349.  
  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
  356.  
  357. static void
  358. freeelfobj(struct ElfObject *elfobj);
  359.  
  360. static BOOL
  361. loadelf32(struct ElfObject *eo,struct Elf32_Shdr *shdrs);
  362.  
  363. static BOOL
  364. scanElfSymbols(struct ElfObject *eo,struct PPCObjectInfo *info,
  365.                       BOOL relmode);
  366.  
  367. static BOOL
  368. getsyminfo(struct ElfObject *eo,struct PPCObjectInfo *info,
  369.            struct Elf32_Sym *stab);
  370.  
  371. static APTR
  372. loadprogram(struct ElfObject *eo);
  373.  
  374. static void
  375. freeprogram(struct ElfObject *eo);
  376.  
  377. static BOOL
  378. relocate(struct ElfObject *eo);
  379.  
  380. static void*
  381. allocstr( const char* string );
  382.  
  383. static void*
  384. alloc32c( size_t size );
  385.  
  386. static void*
  387. alloc32( size_t size );
  388.  
  389. void
  390. free32( void* addr );
  391.  
  392. static BPTR
  393. opstream(struct ElfObject *eo, const char* name );
  394.  
  395. static BOOL
  396. clstream(struct ElfObject *eo);
  397.  
  398. static BOOL
  399. rdstream(struct ElfObject *eo,void *buf,long len);
  400.  
  401. static long
  402. skstream(struct ElfObject *eo,long offs,long mode);
  403.  
  404. static BOOL
  405. prstream(struct ElfObject *eo,long offs,void *buf,long len);
  406.  
  407. static void*
  408. readsection(struct ElfObject *eo,struct Elf32_Shdr *sh);
  409.  
  410. static struct ELFSection*
  411. progsection(struct ElfObject *eo, struct Elf32_Shdr *sh);
  412.  
  413. static BOOL
  414. common_symbols(struct ElfObject *eo);
  415.  
  416. static BOOL
  417. getrelocs(struct ElfObject *eo,struct Elf32_Shdr *sh);
  418.  
  419. static const char ELFid[4] = {
  420.   0x7f,'E','L','F'
  421. };
  422.  
  423. void*
  424. ELFLoadObject( const char* objname )
  425. {
  426.   struct ElfObject *elfobj = NULL;
  427.  
  428.   /* allocate ElfObject structure */
  429.  
  430.   elfobj = alloc32( sizeof( struct ElfObject ) );
  431.  
  432.   if( elfobj != NULL )
  433.   {
  434.     memset(elfobj,sizeof(struct ElfObject),0);
  435.  
  436.     elfobj->header = alloc32( sizeof( struct Elf32_Ehdr ) );
  437.  
  438.     if( elfobj->header != NULL )
  439.     {
  440.       /* open ELF stream for reading */
  441.  
  442.       elfobj->handle = opstream( elfobj, objname );
  443.  
  444.       if( elfobj->handle != NULL )
  445.       {
  446.         /* read and identify ELF 32bit PowerPC BigEndian header */
  447.  
  448.         if( rdstream( elfobj, elfobj->header, sizeof(struct Elf32_Ehdr) ) )
  449.         {
  450.           struct Elf32_Ehdr *hdr = elfobj->header;
  451.  
  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)
  458.           {
  459.             struct Elf32_Shdr *shdrs;
  460.             ULONG shdrsize = (ULONG) hdr->e_shnum * (ULONG) hdr->e_shentsize;
  461.  
  462.             kprintf("elf32ppcbe format recognized\n");
  463.  
  464.             shdrs = alloc32( shdrsize );
  465.  
  466.             if( shdrs != NULL )
  467.             {
  468.               /* read section header table and parse rest of object */
  469.  
  470.               if( prstream( elfobj, hdr->e_shoff, shdrs, shdrsize ) )
  471.               {
  472.                 if( loadelf32( elfobj, shdrs ) )
  473.                 {
  474.                   kprintf("ELF object loaded (0x%08lx)\n", elfobj );
  475.                   free32( shdrs );
  476.                   return (elfobj);
  477.                 }
  478.               }
  479.               free32( shdrs );
  480.             }
  481.           }
  482.           else
  483.             kprintf( "Not an ELF32-PPC-BE\nrelocatable object.");
  484.         }
  485.       }
  486.       freeelfobj(elfobj);
  487.     }
  488.   }
  489.  
  490.   return (NULL);
  491. }
  492.  
  493.  
  494. void
  495. ELFUnLoadObject( void* obj )
  496. {
  497.   struct ElfObject* elfobj = (struct ElfObject*) obj;
  498.  
  499.   if(elfobj->sections != NULL && elfobj->nsects > 0 )
  500.   {
  501.     freeprogram(elfobj);
  502.   }
  503.  
  504.   freeelfobj(elfobj);
  505. }
  506.  
  507. BOOL
  508. ELFGetSymbol( void* obj,
  509.               const char* name, 
  510.               void** ptr )
  511. {
  512.   struct PPCObjectInfo oi =
  513.   {
  514.     0,
  515.     NULL,
  516.     PPCELFINFOTYPE_SYMBOL,
  517.     STT_SECTION,
  518.     STB_GLOBAL,
  519.     0
  520.   };
  521.  
  522.   BOOL rc;
  523.  
  524.   oi.Name = (char*) name;
  525.   rc = scanElfSymbols( (struct ElfObject*) obj, &oi, FALSE );
  526.   *ptr = (void*) oi.Address;
  527.  
  528.   return rc;
  529. }
  530.  
  531.  
  532. static void freeelfobj(struct ElfObject *elfobj)
  533. /* free all memory connected to an ElfObject */
  534. {
  535.   if (elfobj) {
  536.     if (elfobj->handle)
  537.       clstream(elfobj);
  538.     free32(elfobj);
  539.   }
  540. }
  541.  
  542.  
  543. static BOOL loadelf32(struct ElfObject *eo,struct Elf32_Shdr *shdrs)
  544. /* parse ELF object, initialize ElfObject structure */
  545. {
  546.   struct Elf32_Ehdr *hdr = eo->header;
  547.   struct ELFSection *s;
  548.   uint16 i;
  549.  
  550.   if ((eo->secnames = readsection(eo,&shdrs[hdr->e_shstrndx])) &&
  551.       (eo->sections = alloc32((hdr->e_shnum+1)*sizeof(void *)))) {
  552.     memset(eo->sections,(hdr->e_shnum+1)*sizeof(void *),0);
  553.     eo->nsects = hdr->e_shnum + 1;  /* +1 section for COMMON symbols */
  554.     for (i=1; i<hdr->e_shnum; i++) {
  555.       switch (shdrs[i].sh_type) {
  556.         case SHT_PROGBITS:
  557.         case SHT_NOBITS:
  558.           if (!(eo->sections[i] = progsection(eo,&shdrs[i])))
  559.             return (FALSE);
  560.           break;
  561.         case SHT_SYMTAB:
  562.           if (!(eo->symnames = readsection(eo,&shdrs[shdrs[i].sh_link]))
  563.               || !(eo->symtab = readsection(eo,&shdrs[i])))
  564.             return (FALSE);
  565.           eo->nsyms = shdrs[i].sh_size / sizeof(struct Elf32_Sym);
  566.           eo->gsyms = shdrs[i].sh_info;
  567.           break;
  568.         default:
  569.           break;
  570.       }
  571.     }
  572.     for (i=1; i<hdr->e_shnum; i++) {
  573.       switch (shdrs[i].sh_type) {
  574.         case SHT_REL:
  575.         case SHT_RELA:
  576.           if (!getrelocs(eo,&shdrs[i]))
  577.             return (FALSE);
  578.           break;
  579.         default:
  580.           break;
  581.       }
  582.     }
  583.     /* allocate space for Common symbols */
  584.     return (common_symbols(eo));
  585.   }
  586.   return (FALSE);
  587. }
  588.  
  589.  
  590. static BOOL scanElfSymbols(struct ElfObject *eo,struct PPCObjectInfo *info,
  591.                            BOOL relmode)
  592. /* Find an ELF symbol by its name or address and return all infos  */
  593. /* in the supplied PPCObjectInfo structure. Return FALSE if symbol */
  594. /* doesn't exist. */
  595. /* ATTENTION: PPCLibBase may be locked at that stage! */
  596. {
  597.   ULONG addr = info->Address;
  598.   char *name = info->Name;
  599. //kprintf( "scanElfSymbols( 0x%08lx, 0x%08lx, %ld\n", eo, info, relmode );
  600.   if (relmode) {
  601.     int i,j;
  602.     struct ELFSection *es;
  603.     struct Elf32_Rela *r;
  604.  
  605.     for (i=1; i<(eo->nsects-1); i++) {
  606.       if( (es = eo->sections[i]) != NULL ) {
  607.         for (j=0,r=es->relocs; j<es->nrel; j++,r++) {
  608.           if (getsyminfo(eo,info,&eo->symtab[ELF32_R_SYM(r->r_info)])) {
  609.             info->Address = (ULONG)es->address + r->r_offset;
  610.             info->Type = PPCELFINFOTYPE_RELOC;
  611.             info->SubType = (ULONG)ELF32_R_TYPE(r->r_info);
  612.             if (info->Address == addr) {
  613.               if (name) {
  614.                 if (!strcmp(name,info->Name))
  615.                   return (TRUE);
  616.               }
  617.               else
  618.                 return (TRUE);
  619.             }
  620.           }
  621.         }
  622.       }
  623.     }
  624.   }
  625.  
  626.   else {
  627.     struct Elf32_Sym *stab = eo->symtab;
  628.     int i = eo->nsyms;
  629.     while (--i) {
  630. //kprintf( "i=%ld\n", i );
  631.       if (getsyminfo(eo,info,++stab)) {
  632.         if (!name) {
  633.           if (info->Size) {
  634.             if (addr>=info->Address && addr<(info->Address+info->Size))
  635.               return (TRUE);
  636.           }
  637.           else {
  638.             if (addr == info->Address)
  639.               return (TRUE);
  640.           }
  641.         }
  642.         else {
  643. //kprintf( "comparing %s and %s\n", name,info->Name );
  644.           if (!strcmp(name,info->Name))
  645.             return (TRUE);
  646.         }
  647.       }
  648.     }
  649.   }
  650.   return (FALSE);
  651. }
  652.  
  653.  
  654. static BOOL getsyminfo(struct ElfObject *eo,struct PPCObjectInfo *info,
  655.                        struct Elf32_Sym *stab)
  656. {
  657.   struct ELFSection *es;
  658.   ULONG subtype;
  659.  
  660.   subtype = (ULONG)ELF32_ST_TYPE(stab->st_info);
  661.   if (subtype < STT_FILE) {
  662.     info->Type = subtype==STT_SECTION ? PPCELFINFOTYPE_SECTION
  663.                                       : PPCELFINFOTYPE_SYMBOL;
  664.     switch (stab->st_shndx) {
  665.       case SHN_UNDEF:
  666.         /* undefined symbols will disappear after relocation */
  667.       case SHN_ABS:
  668.         info->Address = stab->st_value;
  669.         break;
  670.       case SHN_COMMON:
  671.         /* @@@ common symbols should have disappeared after common_symbols() */
  672.         info->Type = PPCELFINFOTYPE_COMSYMBOL;
  673.         info->Address = 0;
  674.         break;
  675.       default:
  676.         if( (es = eo->sections[stab->st_shndx]) != NULL )
  677.           info->Address = (ULONG)es->address + stab->st_value;
  678.         else
  679.           info->Address = stab->st_value;
  680.         break;
  681.     }
  682.     info->Name = eo->symnames + stab->st_name;
  683.     info->SubType = subtype;
  684.     info->Binding = (ULONG)ELF32_ST_BIND(stab->st_info);
  685.     info->Size = stab->st_size;
  686.     return (TRUE);
  687.   }
  688.   return (FALSE);
  689. }
  690.  
  691. static APTR loadprogram(struct ElfObject *eo)
  692. /* load all sections into memory and relocate them */
  693. {
  694.   static const char *FN = "loadprogram(): ";
  695.   struct ELFSection *s;
  696.   uint8 *p,*entry=NULL;
  697.   unsigned int i;
  698.  
  699.   for (i=0; i<(eo->nsects-1); i++) {
  700.     if( (s = eo->sections[i]) != NULL ) {
  701.       BOOL text = !strcmp(s->name,".text");   /* .text section flag */
  702.       ULONG size = s->size;
  703.  
  704.       /* align to 32 bytes and allocate 32-byte aligned memory */
  705.       size = (size+31)&~31;
  706.       if( (p = alloc32c(size)) != NULL ) {
  707.         s->address = (APTR)p;  /* store section's base address */
  708.         if (!(s->flags & ElfSecF_NOBITS)) {
  709.           /* a PROGBITS section - load it from file */
  710.  
  711.           kprintf("%sreading section %s\n",FN,s->name);
  712.           if (prstream(eo,s->offset,p,s->size)) {
  713.             if (text) {
  714.               /* get start address of PPC program in .text */
  715.               entry = p;
  716.               if ((*entry & 0xfc) == 0) {
  717.                 kprintf("%sgcc traceback status word "
  718.                         "detected\n",FN);
  719.                 entry += 4;  /* 1st long reserved for gcc traceback word */
  720.               }
  721.               /* copy kernel stubs */
  722. /*
  723.                kprintf("%sentry=0x%08lx, "
  724.                        "invoking dynamic linker\n",FN,entry);
  725.               if (!dynamic_linker(i,eo,p)) {
  726.                 entry = NULL;
  727.                 break;
  728.               }
  729. */
  730.             }
  731.           }
  732.           else {
  733.             entry = NULL;
  734.             break;
  735.           }
  736.         }
  737.       }
  738.       else {
  739.         kprintf("Failed to allocate %ld bytes\n"
  740.                "for PPC %s section.",size,s->name);
  741.         entry = NULL;
  742.         break;
  743.       }
  744.     }
  745.   }
  746.  
  747.   if (entry) {
  748.     if (!relocate(eo)) {  /* relocate sections */
  749.       entry = NULL;
  750.       freeprogram(eo);
  751.     }
  752.   }
  753.   else
  754.     freeprogram(eo);
  755.  
  756.   kprintf("%sreturning with entry=0x%08lx\n",FN,entry);
  757.   return (entry);
  758. }
  759.  
  760.  
  761. static void freeprogram(struct ElfObject *eo)
  762. {
  763.   struct ELFSection *s;
  764.   unsigned int i;
  765.  
  766.   for (i=0; i<eo->nsects; i++) {
  767.     if( (s = eo->sections[i]) != NULL ) {
  768.       if (s->address) {
  769.         free32(s->address);
  770.         s->address = NULL;
  771.       }
  772.     }
  773.   }
  774. }
  775.  
  776.  
  777. static BOOL relocate(struct ElfObject *eo)
  778. {
  779.   struct ELFSection *es;
  780.   unsigned int shndx;
  781.  
  782.   for (shndx=0; shndx<(eo->nsects-1); shndx++) {
  783.     if( (es = eo->sections[shndx]) != NULL ) {
  784.       BOOL rela = (es->flags & ElfSecF_RELA) != 0;
  785.       struct Elf32_Rela *r;
  786.       int i;
  787.  
  788.       kprintf("relocate(): relocating section %s "
  789.               "at 0x%08lx\n",es->name,es->address);
  790.       for (i=0,r=es->relocs; i<es->nrel; i++,r++) {
  791.         struct Elf32_Sym *sym = &eo->symtab[ELF32_R_SYM(r->r_info)];
  792.         long s = (long)eo->sections[sym->st_shndx]->address + sym->st_value;
  793.         uint8 *p = (uint8 *)es->address + r->r_offset;
  794.  
  795.         switch (ELF32_R_TYPE(r->r_info)) {
  796.           case R_PPC_NONE:
  797.             break;
  798.  
  799.           case R_PPC_ADDR32:
  800.             if (rela)
  801.               *(long *)p = s + r->r_addend;
  802.             else
  803.               *(long *)p += s;
  804.             break;
  805.  
  806.           case R_PPC_ADDR16:
  807.             if (rela)
  808.               *(short *)p = s + r->r_addend;
  809.             else
  810.               *(short *)p += s;
  811.             break;
  812.  
  813.           case R_PPC_ADDR16_LO:
  814.             if (rela)
  815.               *(short *)p = (s + r->r_addend) & 0xffff;
  816.             else
  817.               *(short *)p = (s + *(short *)p) & 0xffff;
  818.             break;
  819.  
  820.           case R_PPC_ADDR16_HI:
  821.             if (rela)
  822.               *(short *)p = (s + r->r_addend) >> 16;
  823.             else
  824.               *(short *)p = (s + *(short *)p) >> 16;
  825.             break;
  826.  
  827.           case R_PPC_ADDR16_HA:
  828.             if (rela)
  829.               s += r->r_addend;
  830.             else
  831.               s += *(short *)p;
  832.             *(short *)p = (s>>16) + ((s&0x8000) ? 1 : 0);
  833.             break;
  834.  
  835.           case R_PPC_REL24:
  836.             if (rela) {
  837.               s = (s + r->r_addend) - (long)p;
  838.             }
  839.             else {
  840.               if (*p & 0x02)
  841.                 s = (s + ((*(long *)p & 0x03fffffc) - 0x04000000)) - (long)p;
  842.               else
  843.                 s = (s + (*(long *)p & 0x03fffffc)) - (long)p;
  844.             }
  845.             *(unsigned long *)p = (*(unsigned long *)p & 0xfc000003) |
  846.                                   ((unsigned long)s & 0x03fffffc);
  847.             break;
  848.  
  849.           case R_PPC_REL32:
  850.             if (rela)
  851.               *(long *)p = (s + r->r_addend) - (long)p;
  852.             else
  853.               *(long *)p = (s + *(long *)p) - (long)p;
  854.             break;
  855.  
  856.           default:
  857.             kprintf("Relocation type %s\nat %s+%ld referencing\n"
  858.                    "symbol %s+%ld\nis not supported.",
  859.                    reloc_name[ELF32_R_TYPE(r->r_info)],es->name,r->r_offset,
  860.                    eo->symnames+sym->st_name,sym->st_value);
  861.             return (FALSE);
  862.         }
  863.       }
  864.     }
  865.   }
  866.   return (TRUE);
  867. }
  868.  
  869. static void*
  870. alloc32( size_t size )
  871. {
  872.   return AHIAllocVec( size, MEMF_ANY );
  873. }
  874.  
  875. static void*
  876. alloc32c( size_t size )
  877. {
  878.   return AHIAllocVec( size, MEMF_ANY | MEMF_CLEAR );
  879. }
  880.  
  881. void
  882. free32( void* addr )
  883. {
  884.   AHIFreeVec( addr );
  885. }
  886.  
  887.  
  888. static void*
  889. allocstr( const char* string )
  890. {
  891.   void* mem;
  892.  
  893.   mem = AllocVec( strlen( string ) + 1, MEMF_ANY );
  894.  
  895.   if( mem != NULL )
  896.   {
  897.     strcpy( mem, string );
  898.   }
  899.  
  900.   return mem;
  901. }
  902.  
  903.  
  904. static BPTR
  905. opstream(struct ElfObject *eo, const char* name )
  906. {
  907.   BPTR handle;
  908.  
  909.   if( name != NULL )
  910.   {
  911.     handle = Open( name, MODE_OLDFILE );
  912.   }
  913.  
  914.   return (handle);
  915. }
  916.  
  917.  
  918. static BOOL
  919. clstream(struct ElfObject *eo)
  920. {
  921.   Close( eo->handle );
  922.   return TRUE;
  923. }
  924.  
  925.  
  926. static BOOL
  927. rdstream(struct ElfObject *eo,void *buf,long len)
  928. {
  929.   long r;
  930.   
  931.   r = Read( eo->handle, buf, len );
  932.  
  933.   if( r != len )
  934.   {
  935.     return (FALSE);
  936.   }
  937.   return (TRUE);
  938. }
  939.  
  940.  
  941. static long
  942. skstream(struct ElfObject *eo,long offs,long mode)
  943. {
  944.   long r;
  945.  
  946.   r = Seek( eo->handle, offs, mode );
  947.   return (r);
  948. }
  949.  
  950.  
  951. static BOOL
  952. prstream(struct ElfObject *eo,long offs,void *buf,long len)
  953. /* position and read stream */
  954. {
  955.   if (skstream(eo,offs,OFFSET_BEGINNING) != -1)
  956.     return (rdstream(eo,buf,len));
  957.   return FALSE;
  958. }
  959.  
  960.  
  961. static void *readsection(struct ElfObject *eo,struct Elf32_Shdr *sh)
  962. /* allocate memory and read section contents */
  963. {
  964.   void *p;
  965.  
  966.   if( (p = AllocVec(sh->sh_size,MEMF_ANY)) != NULL )
  967.     if (prstream(eo,sh->sh_offset,p,sh->sh_size))
  968.       return (p);
  969.   return (NULL);
  970. }
  971.  
  972.  
  973. static struct ELFSection *progsection(struct ElfObject *eo,
  974.                                       struct Elf32_Shdr *sh)
  975. /* Create Section structure from Elf32_Shdr. The contents of these     */
  976. /* sections will be loaded and relocated on demand, e.g. if a new task */
  977. /* is created. */
  978. {
  979.   struct ELFSection *s;
  980.  
  981.   if( (s = AllocVec(sizeof(struct ELFSection),MEMF_ANY)) != NULL ) {
  982.     memset(s,sizeof(struct ELFSection),0);
  983.     s->name = eo->secnames + sh->sh_name;
  984.     s->flags = sh->sh_type==SHT_NOBITS ? ElfSecF_NOBITS:0;
  985.     s->alignment = (uint8)sh->sh_addralign;
  986.     s->offset = sh->sh_offset;
  987.     s->size = sh->sh_size;
  988.     return (s);
  989.   }
  990.   return (NULL);
  991. }
  992.  
  993.  
  994. static BOOL common_symbols(struct ElfObject *eo)
  995. /* Create a and initialize Section structure for Common symbols. */
  996. {
  997.   static const char *FN = "common_symbols(): ";
  998.   static const char *bssname = ".bss";
  999.   struct ELFSection *s;
  1000.   struct Elf32_Sym *sym;
  1001.   uint16 *relocp;
  1002.   uint32 offset,idx,cnt=0;
  1003.   unsigned int i;
  1004.  
  1005.   /* First try to find a .bss, where Common symbols could be appended */
  1006.   for (i=0; i<(eo->nsects-1); i++) {
  1007.     if( (s = eo->sections[i]) != NULL ) {
  1008.       if (!strcmp(s->name,bssname) && (s->flags & ElfSecF_NOBITS)) {
  1009.         idx = i;
  1010.         offset = s->size;
  1011.         kprintf("%sfound %s at index %ld with size=%ld\n",
  1012.                 FN,bssname,idx,offset);
  1013.         break;
  1014.       }
  1015.       else
  1016.         s = NULL;
  1017.     }
  1018.   }
  1019.  
  1020.   if (!s) {
  1021.     /* No .bss section present, allocate an own one */
  1022.     if( (s = AllocVec(sizeof(struct ELFSection),MEMF_ANY)) != NULL ) {
  1023.       memset(s,sizeof(struct ELFSection),0);
  1024.       s->name = allocstr((char *)bssname);
  1025.       s->flags = ElfSecF_NOBITS;
  1026.       s->alignment = 32;
  1027.       offset = 0;
  1028.       idx = eo->nsects-1;
  1029.       eo->sections[idx] = s;
  1030.       kprintf("%screated new %s at index %ld\n",FN,bssname,idx);
  1031.     }
  1032.     else
  1033.       return (FALSE);
  1034.   }
  1035.  
  1036.   /* Ok, search for COMMON symbols now */
  1037.   for (i=1,sym=&eo->symtab[1]; i<eo->nsyms; i++,sym++) {
  1038.     if (sym->st_shndx == SHN_COMMON) {
  1039.       offset = (offset + sym->st_value-1) & ~(sym->st_value-1);
  1040.       sym->st_value = offset;
  1041.       sym->st_shndx = idx;
  1042.       offset += sym->st_size;
  1043.       cnt++;
  1044.     }
  1045.   }
  1046.   kprintf("%sassigned %ld common symbols (%ld bytes)\n",
  1047.           FN,cnt,offset-s->size);
  1048.   s->size = offset;  /* set new .bss section size */
  1049.  
  1050.   return (TRUE);
  1051. }
  1052.  
  1053.  
  1054. static BOOL getrelocs(struct ElfObject *eo,struct Elf32_Shdr *sh)
  1055. /* read relocation entries for a section */
  1056. {
  1057.   uint32 rsize = sh->sh_entsize;
  1058.   int nrelocs = (int)(sh->sh_size/rsize);
  1059.   struct ELFSection *s = eo->sections[sh->sh_info];
  1060.  
  1061.  
  1062.   s->nrel = nrelocs;
  1063.   if (sh->sh_type == SHT_RELA) {
  1064.     s->flags |= ElfSecF_RELA;
  1065.     if( (s->relocs = readsection(eo,sh)) != NULL )
  1066.       return (TRUE);
  1067.   }
  1068.   else {
  1069.     struct Elf32_Rela *r;
  1070.  
  1071.     if ((r = s->relocs = AllocVec(nrelocs*sizeof(struct Elf32_Rela),
  1072.                                   MEMF_ANY)) &&
  1073.         (skstream(eo,sh->sh_offset,OFFSET_BEGINNING) != -1)) {
  1074.       while (nrelocs--) {
  1075.         r->r_addend = 0;
  1076.         if (!rdstream(eo,r,sizeof(struct Elf32_Rel)))
  1077.           return (FALSE);
  1078.         r++;
  1079.       }
  1080.       return (TRUE);
  1081.     }        
  1082.   }
  1083.   return (FALSE);
  1084. }
  1085.