home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 13 / MA_Cover_13.bin / source / c / ahisrc / device / elfloader.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-03  |  28.9 KB  |  1,092 lines

  1. /* $Id: elfloader.c,v 1.8 1999/10/03 15:44:54 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,0,sizeof(struct ElfObject));
  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.                   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);
  480.                 }
  481.               }
  482.               free32( shdrs );
  483.             }
  484.           }
  485.           else
  486.             kprintf( "Not an ELF32-PPC-BE\nrelocatable object.");
  487.         }
  488.       }
  489.       freeelfobj(elfobj);
  490.     }
  491.   }
  492.  
  493.   return (NULL);
  494. }
  495.  
  496.  
  497. void
  498. ELFUnLoadObject( void* obj )
  499. {
  500.   struct ElfObject* elfobj = (struct ElfObject*) obj;
  501.  
  502.   if(elfobj->sections != NULL && elfobj->nsects > 0 )
  503.   {
  504.     freeprogram(elfobj);
  505.   }
  506.  
  507.   freeelfobj(elfobj);
  508. }
  509.  
  510. BOOL
  511. ELFGetSymbol( void* obj,
  512.               const char* name, 
  513.               void** ptr )
  514. {
  515.   struct PPCObjectInfo oi =
  516.   {
  517.     0,
  518.     NULL,
  519.     PPCELFINFOTYPE_SYMBOL,
  520.     STT_SECTION,
  521.     STB_GLOBAL,
  522.     0
  523.   };
  524.  
  525.   BOOL rc;
  526.  
  527.   oi.Name = (char*) name;
  528.   rc = scanElfSymbols( (struct ElfObject*) obj, &oi, FALSE );
  529.  
  530.   if( rc )
  531.   {
  532.     *ptr = (void*) oi.Address;
  533.   }
  534.  
  535.   return rc;
  536. }
  537.  
  538.  
  539. static void freeelfobj(struct ElfObject *elfobj)
  540. /* free all memory connected to an ElfObject */
  541. {
  542.   if (elfobj) {
  543.     if (elfobj->handle)
  544.       clstream(elfobj);
  545.     free32(elfobj);
  546.   }
  547. }
  548.  
  549.  
  550. static BOOL loadelf32(struct ElfObject *eo,struct Elf32_Shdr *shdrs)
  551. /* parse ELF object, initialize ElfObject structure */
  552. {
  553.   struct Elf32_Ehdr *hdr = eo->header;
  554.   struct ELFSection *s;
  555.   uint16 i;
  556.  
  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;
  577.       }
  578.     }
  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;
  588.       }
  589.     }
  590.     /* allocate space for Common symbols */
  591.     return (common_symbols(eo));
  592.   }
  593.   return (FALSE);
  594. }
  595.  
  596.  
  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! */
  603. {
  604.   ULONG addr = info->Address;
  605.   char *name = info->Name;
  606. //kprintf( "scanElfSymbols( 0x%08lx, 0x%08lx, %ld\n", eo, info, relmode );
  607.   if (relmode) {
  608.     int i,j;
  609.     struct ELFSection *es;
  610.     struct Elf32_Rela *r;
  611.  
  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);
  623.               }
  624.               else
  625.                 return (TRUE);
  626.             }
  627.           }
  628.         }
  629.       }
  630.     }
  631.   }
  632.  
  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);
  643.           }
  644.           else {
  645.             if (addr == info->Address)
  646.               return (TRUE);
  647.           }
  648.         }
  649.         else {
  650. //kprintf( "comparing %s and %s\n", name,info->Name );
  651.           if (!strcmp(name,info->Name))
  652.             return (TRUE);
  653.         }
  654.       }
  655.     }
  656.   }
  657.   return (FALSE);
  658. }
  659.  
  660.  
  661. static BOOL getsyminfo(struct ElfObject *eo,struct PPCObjectInfo *info,
  662.                        struct Elf32_Sym *stab)
  663. {
  664.   struct ELFSection *es;
  665.   ULONG subtype;
  666.  
  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;
  688.     }
  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);
  694.   }
  695.   return (FALSE);
  696. }
  697.  
  698. static APTR loadprogram(struct ElfObject *eo)
  699. /* load all sections into memory and relocate them */
  700. {
  701.   static const char *FN = "loadprogram(): ";
  702.   struct ELFSection *s;
  703.   uint8 *p,*entry=NULL;
  704.   unsigned int i;
  705.  
  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;
  710.  
  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 */
  717.  
  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 */
  727.               }
  728.               /* copy kernel stubs */
  729. /*
  730.                kprintf("%sentry=0x%08lx, "
  731.                        "invoking dynamic linker\n",FN,entry);
  732.               if (!dynamic_linker(i,eo,p)) {
  733.                 entry = NULL;
  734.                 break;
  735.               }
  736. */
  737.             }
  738.           }
  739.           else {
  740.             entry = NULL;
  741.             break;
  742.           }
  743.         }
  744.       }
  745.       else {
  746.         kprintf("Failed to allocate %ld bytes\n"
  747.                "for PPC %s section.",size,s->name);
  748.         entry = NULL;
  749.         break;
  750.       }
  751.     }
  752.   }
  753.  
  754.   if (entry) {
  755.     if (!relocate(eo)) {  /* relocate sections */
  756.       entry = NULL;
  757.       freeprogram(eo);
  758.     }
  759.   }
  760.   else
  761.     freeprogram(eo);
  762.  
  763. //  kprintf("%sreturning with entry=0x%08lx\n",FN,entry);
  764.   return (entry);
  765. }
  766.  
  767.  
  768. static void freeprogram(struct ElfObject *eo)
  769. {
  770.   struct ELFSection *s;
  771.   unsigned int i;
  772.  
  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;
  778.       }
  779.     }
  780.   }
  781. }
  782.  
  783.  
  784. static BOOL relocate(struct ElfObject *eo)
  785. {
  786.   struct ELFSection *es;
  787.   unsigned int shndx;
  788.  
  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;
  794.  
  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;
  801.  
  802.         switch (ELF32_R_TYPE(r->r_info)) {
  803.           case R_PPC_NONE:
  804.             break;
  805.  
  806.           case R_PPC_ADDR32:
  807.             if (rela)
  808.               *(long *)p = s + r->r_addend;
  809.             else
  810.               *(long *)p += s;
  811.             break;
  812.  
  813.           case R_PPC_ADDR16:
  814.             if (rela)
  815.               *(short *)p = s + r->r_addend;
  816.             else
  817.               *(short *)p += s;
  818.             break;
  819.  
  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;
  826.  
  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;
  833.  
  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;
  841.  
  842.           case R_PPC_REL24:
  843.             if (rela) {
  844.               s = (s + r->r_addend) - (long)p;
  845.             }
  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;
  851.             }
  852.             *(unsigned long *)p = (*(unsigned long *)p & 0xfc000003) |
  853.                                   ((unsigned long)s & 0x03fffffc);
  854.             break;
  855.  
  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;
  862.  
  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);
  869.         }
  870.       }
  871.     }
  872.   }
  873.   return (TRUE);
  874. }
  875.  
  876. static void*
  877. alloc32( size_t size )
  878. {
  879.   return AHIAllocVec( size, MEMF_ANY );
  880. }
  881.  
  882. static void*
  883. alloc32c( size_t size )
  884. {
  885.   return AHIAllocVec( size, MEMF_ANY | MEMF_CLEAR );
  886. }
  887.  
  888. void
  889. free32( void* addr )
  890. {
  891.   AHIFreeVec( addr );
  892. }
  893.  
  894.  
  895. static void*
  896. allocstr( const char* string )
  897. {
  898.   void* mem;
  899.  
  900.   mem = AllocVec( strlen( string ) + 1, MEMF_ANY );
  901.  
  902.   if( mem != NULL )
  903.   {
  904.     strcpy( mem, string );
  905.   }
  906.  
  907.   return mem;
  908. }
  909.  
  910.  
  911. static BPTR
  912. opstream(struct ElfObject *eo, const char* name )
  913. {
  914.   BPTR handle;
  915.  
  916.   if( name != NULL )
  917.   {
  918.     handle = Open( name, MODE_OLDFILE );
  919.   }
  920.  
  921.   return (handle);
  922. }
  923.  
  924.  
  925. static BOOL
  926. clstream(struct ElfObject *eo)
  927. {
  928.   Close( eo->handle );
  929.   return TRUE;
  930. }
  931.  
  932.  
  933. static BOOL
  934. rdstream(struct ElfObject *eo,void *buf,long len)
  935. {
  936.   long r;
  937.   
  938.   r = Read( eo->handle, buf, len );
  939.  
  940.   if( r != len )
  941.   {
  942.     return (FALSE);
  943.   }
  944.   return (TRUE);
  945. }
  946.  
  947.  
  948. static long
  949. skstream(struct ElfObject *eo,long offs,long mode)
  950. {
  951.   long r;
  952.  
  953.   r = Seek( eo->handle, offs, mode );
  954.   return (r);
  955. }
  956.  
  957.  
  958. static BOOL
  959. prstream(struct ElfObject *eo,long offs,void *buf,long len)
  960. /* position and read stream */
  961. {
  962.   if (skstream(eo,offs,OFFSET_BEGINNING) != -1)
  963.     return (rdstream(eo,buf,len));
  964.   return FALSE;
  965. }
  966.  
  967.  
  968. static void *readsection(struct ElfObject *eo,struct Elf32_Shdr *sh)
  969. /* allocate memory and read section contents */
  970. {
  971.   void *p;
  972.  
  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);
  977. }
  978.  
  979.  
  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. */
  985. {
  986.   struct ELFSection *s;
  987.  
  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);
  996.   }
  997.   return (NULL);
  998. }
  999.  
  1000.  
  1001. static BOOL common_symbols(struct ElfObject *eo)
  1002. /* Create a and initialize Section structure for Common symbols. */
  1003. {
  1004.   static const char *FN = "common_symbols(): ";
  1005.   static const char *bssname = ".bss";
  1006.   struct ELFSection *s;
  1007.   struct Elf32_Sym *sym;
  1008.   uint16 *relocp;
  1009.   uint32 offset,idx,cnt=0;
  1010.   unsigned int i;
  1011.  
  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;
  1021.       }
  1022.       else
  1023.         s = NULL;
  1024.     }
  1025.   }
  1026.  
  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);
  1038.     }
  1039.     else
  1040.       return (FALSE);
  1041.   }
  1042.  
  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++;
  1051.     }
  1052.   }
  1053. //  kprintf("%sassigned %ld common symbols (%ld bytes)\n",
  1054. //          FN,cnt,offset-s->size);
  1055.   s->size = offset;  /* set new .bss section size */
  1056.  
  1057.   return (TRUE);
  1058. }
  1059.  
  1060.  
  1061. static BOOL getrelocs(struct ElfObject *eo,struct Elf32_Shdr *sh)
  1062. /* read relocation entries for a section */
  1063. {
  1064.   uint32 rsize = sh->sh_entsize;
  1065.   int nrelocs = (int)(sh->sh_size/rsize);
  1066.   struct ELFSection *s = eo->sections[sh->sh_info];
  1067.  
  1068.  
  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);
  1074.   }
  1075.   else {
  1076.     struct Elf32_Rela *r;
  1077.  
  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++;
  1086.       }
  1087.       return (TRUE);
  1088.     }        
  1089.   }
  1090.   return (FALSE);
  1091. }
  1092.