home *** CD-ROM | disk | FTP | other *** search
/ MACD 4 / MACD4.iso / Emulatory / AROS / dos / loadseg_elf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1978-03-06  |  6.7 KB  |  311 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: loadseg_elf.c,v 1.9 1996/10/24 15:50:32 aros Exp $
  4.     $Log: loadseg_elf.c,v $
  5.     Revision 1.9  1996/10/24 15:50:32  aros
  6.     Use the official AROS macros over the __AROS versions.
  7.  
  8.     Revision 1.8  1996/10/23 14:23:54  aros
  9.     Added some more debug code
  10.  
  11.     Revision 1.7  1996/09/13 17:50:07  digulla
  12.     Use IPTR
  13.  
  14.     Revision 1.6  1996/08/15 13:18:21  digulla
  15.     First attempt to allow debugging in shared code but the strings are not
  16.     loaded correctly yet
  17.  
  18.     Revision 1.5  1996/08/13 13:52:48  digulla
  19.     Replaced <dos/dosextens.h> by "dos_intern.h" or added "dos_intern.h"
  20.     Replaced AROS_LA by AROS_LHA
  21.  
  22.     Revision 1.4  1996/08/03 18:21:10  digulla
  23.     Added support for linked files !
  24.  
  25.     Revision 1.3  1996/08/01 17:40:54  digulla
  26.     Added standard header for all files
  27.  
  28.     Desc:
  29.     Lang:
  30. */
  31. #include <exec/memory.h>
  32. #include <clib/exec_protos.h>
  33. #include <dos/dosasl.h>
  34. #include <clib/dos_protos.h>
  35. #include <clib/aros_protos.h>
  36. #include "dos_intern.h"
  37. #include <aros/debug.h>
  38.  
  39. extern struct DosLibrary * DOSBase;
  40.  
  41. #define SHT_PROGBITS    1
  42. #define SHT_SYMTAB    2
  43. #define SHT_STRTAB    3
  44. #define SHT_NOBITS    8
  45. #define SHT_REL     9
  46.  
  47. #define RELO_32     1
  48. #define RELO_PC32    2
  49.  
  50. struct elfheader
  51. {
  52.     UBYTE ident[16];
  53.     UWORD type;
  54.     UWORD machine;
  55.     ULONG version;
  56.     APTR entry;
  57.     ULONG phoff;
  58.     ULONG shoff;
  59.     ULONG flags;
  60.     UWORD ehsize;
  61.     UWORD phentsize;
  62.     UWORD phnum;
  63.     UWORD shentsize;
  64.     UWORD shnum;
  65.     UWORD shstrndx;
  66. };
  67.  
  68. struct sheader
  69. {
  70.     ULONG name;
  71.     ULONG type;
  72.     ULONG flags;
  73.     APTR addr;
  74.     ULONG offset;
  75.     ULONG size;
  76.     ULONG link;
  77.     ULONG info;
  78.     ULONG addralign;
  79.     ULONG entsize;
  80. };
  81.  
  82. struct symbol
  83. {
  84.     ULONG name;
  85.     ULONG value;
  86.     ULONG size;
  87.     UBYTE info;
  88.     UBYTE other;
  89.     WORD shindex;
  90. };
  91.  
  92. struct relo
  93. {
  94.     ULONG addr;
  95.     ULONG info;
  96. };
  97.  
  98. struct hunk
  99. {
  100.     ULONG size;
  101.     UBYTE *memory;
  102. };
  103.  
  104. int read_block(BPTR file, ULONG offset, APTR buffer, ULONG size)
  105. {
  106.     LONG subsize;
  107.     UBYTE *buf=(UBYTE *)buffer;
  108.     if(Seek(file,offset,OFFSET_BEGINNING)<0)
  109.     return 1;
  110.     while(size)
  111.     {
  112.     subsize=Read(file,buf,size);
  113.     if(subsize==0)
  114.     {
  115.         ((struct Process *)FindTask(NULL))->pr_Result2=ERROR_BAD_HUNK;
  116.         return 1;
  117.     }
  118.     if(subsize<0)
  119.         return 1;
  120.     buf+=subsize;
  121.     size-=subsize;
  122.     }
  123.     return 0;
  124. }
  125.  
  126. BPTR LoadSeg_ELF(BPTR file)
  127. {
  128.     UBYTE *shtab=NULL;
  129.     UBYTE *strtab=NULL;
  130.     struct symbol *symtab=NULL;
  131.     struct hunk *hunks=NULL;
  132.     struct relo *reltab=NULL;
  133.  
  134.     ULONG numsym, numrel, i;
  135.     WORD t, mint=0, maxt=0;
  136.     struct elfheader eh;
  137.     struct sheader *sh;
  138.     UBYTE *loaded;
  139.     struct symbol *symbol;
  140.     BPTR last=0;
  141.  
  142. #define ERROR(a)    { *error=a; goto end; }
  143.     LONG *error=&((struct Process *)FindTask(NULL))->pr_Result2;
  144.  
  145.     if(read_block(file,0,&eh,sizeof(eh)))
  146.     goto end;
  147.  
  148.     if(eh.ident[0]!=0x7f||eh.ident[1]!='E'||eh.ident[2]!='L'||eh.ident[3]!='F')
  149.     ERROR(ERROR_NOT_EXECUTABLE);
  150.  
  151.     if(eh.type!=1||eh.machine!=3)
  152.     ERROR(ERROR_OBJECT_WRONG_TYPE);
  153.  
  154.     shtab=(UBYTE *)AllocVec(eh.shentsize*eh.shnum,MEMF_ANY);
  155.  
  156.     if(shtab==NULL)
  157.     ERROR(ERROR_NO_FREE_STORE);
  158.  
  159.     if(read_block(file,eh.shoff,shtab,eh.shentsize*eh.shnum))
  160.     goto end;
  161.  
  162.     for(t=0;;t++)
  163.     {
  164.     if(t==eh.shnum)
  165.         ERROR(ERROR_OBJECT_WRONG_TYPE);
  166.  
  167.     sh=(struct sheader *)(shtab+t*eh.shentsize);
  168.  
  169.     if(sh->type==SHT_SYMTAB)
  170.         break;
  171.     }
  172.  
  173.     symtab=(struct symbol *)AllocVec(sh->size,MEMF_ANY);
  174.  
  175.     if(symtab==NULL)
  176.     ERROR(ERROR_NO_FREE_STORE);
  177.  
  178.     if(read_block(file,sh->offset,symtab,sh->size))
  179.     goto end;
  180.  
  181.     numsym=sh->size/sizeof(struct symbol);
  182.     mint=maxt=symtab[0].shindex;
  183.     for(i=1;i<numsym;i++)
  184.     {
  185.     if(symtab[i].shindex<mint)
  186.         mint=symtab[i].shindex;
  187.     if(symtab[i].shindex>maxt)
  188.         maxt=symtab[i].shindex;
  189.     }
  190.     hunks=(struct hunk *)AllocVec(sizeof(struct hunk)*((LONG)maxt-mint+1),MEMF_CLEAR);
  191.     if(hunks==NULL)
  192.     ERROR(ERROR_NO_FREE_STORE);
  193.     hunks-=mint;
  194.     for(t=0;t<eh.shnum;t++)
  195.     {
  196.     sh=(struct sheader *)(shtab+t*eh.shentsize);
  197.     if(sh->type==SHT_PROGBITS||sh->type==SHT_NOBITS)
  198.         hunks[t].size=sh->size;
  199.     }
  200.  
  201. #if 0 /* doesn't work :( */
  202.     if (eh.shstrndx)
  203.     {
  204.     sh = (struct sheader *)(shtab + eh.shstrndx*eh.shentsize);
  205.  
  206. kprintf ("StrTab-Section: name=%d type=%d flags=%d\n",
  207.     sh->name, sh->type,sh->flags);
  208.  
  209.     strtab=AllocVec(sh->size,MEMF_ANY);
  210.     if(symtab==NULL)
  211.         ERROR(ERROR_NO_FREE_STORE);
  212.     kprintf ("Reading StrTab at %d (offset=%ld, size=%ld)\n", eh.shstrndx, sh->offset, sh->size);
  213.     if(read_block(file,sh->offset,strtab,sh->size))
  214.         goto end;
  215.     }
  216. #endif
  217.  
  218.     for(i=0;i<numsym;i++)
  219.     if(symtab[i].shindex<0)
  220.     {
  221.         symtab[i].value=hunks[symtab[i].shindex].size;
  222.         hunks[symtab[i].shindex].size+=symtab[i].size;
  223.  
  224.         if (strtab && symtab[i].name)
  225.         kprintf ("sym %s: %ld\n", &strtab[symtab[i].name], symtab[i].value);
  226.     }
  227.     for(t=mint;t<=maxt;t++)
  228.     if(hunks[t].size)
  229.     {
  230.         hunks[t].memory=(UBYTE *)AllocVec(hunks[t].size+sizeof(BPTR),MEMF_CLEAR);
  231.         if(hunks[t].memory==NULL)
  232.         ERROR(ERROR_NO_FREE_STORE);
  233.         hunks[t].memory+=sizeof(BPTR);
  234. D(bug("   Hunk %3d: 0x%p - 0x%p\n", t, hunks[t].memory, hunks[t].memory+hunks[t].size));
  235.     }
  236.     loaded=NULL;
  237.     for(t=0;t<eh.shnum;t++)
  238.     {
  239.     sh=(struct sheader *)(shtab+t*eh.shentsize);
  240.     switch(sh->type)
  241.     {
  242.     case SHT_PROGBITS:
  243.         if(read_block(file,sh->offset,hunks[t].memory,sh->size))
  244.         goto end;
  245.         loaded=hunks[t].memory;
  246.         /* VPrintf ("Loaded PROGBITS at %08lx\n", (ULONG*)&loaded); */
  247.         break;
  248.     case SHT_REL:
  249.         if(loaded==NULL)
  250.         ERROR(ERROR_OBJECT_WRONG_TYPE);
  251.         reltab=AllocVec(sh->size,MEMF_ANY);
  252.         if(reltab==NULL)
  253.         ERROR(ERROR_NO_FREE_STORE);
  254.         if(read_block(file,sh->offset,reltab,sh->size))
  255.         goto end;
  256.         numrel=sh->size/sizeof(struct relo);
  257.         for(i=0;i<numrel;i++)
  258.         {
  259.         symbol=&symtab[reltab[i].info>>8];
  260.         switch(reltab[i].info&0xff)
  261.         {
  262.         case RELO_32:
  263.             *(ULONG *)&loaded[reltab[i].addr]+=
  264.             (IPTR)hunks[symbol->shindex].memory+symbol->value;
  265.             break;
  266.         case RELO_PC32:
  267.             *(ULONG *)&loaded[reltab[i].addr]+=
  268.             (IPTR)hunks[symbol->shindex].memory +
  269.             symbol->value - (IPTR)&loaded[reltab[i].addr];
  270.             break;
  271.         default:
  272.             ERROR(ERROR_BAD_HUNK);
  273.         }
  274.         }
  275.         FreeVec(reltab);
  276.         reltab=NULL;
  277.         loaded=NULL;
  278.         break;
  279.     }
  280.     }
  281.     for(t=mint;t<0;t++)
  282.     if(hunks[t].size)
  283.     {
  284.         ((BPTR *)hunks[t].memory)[-1]=last;
  285.         last=MKBADDR((BPTR *)hunks[t].memory-1);
  286.     }
  287.     for(t=maxt;t>=0;t--)
  288.     if(hunks[t].size)
  289.     {
  290.         ((BPTR *)hunks[t].memory)[-1]=last;
  291.         last=MKBADDR((BPTR *)hunks[t].memory-1);
  292.     }
  293.     FreeVec(hunks+mint);
  294.     hunks=NULL;
  295.  
  296. end:
  297.     FreeVec(reltab);
  298.     if(hunks!=NULL)
  299.     {
  300.     for(t=mint;t<=maxt;t++)
  301.         if(hunks[t].memory!=NULL)
  302.         FreeVec(hunks[t].memory-sizeof(BPTR));
  303.     FreeVec(hunks+mint);
  304.     }
  305.     if (strtab)
  306.     FreeVec (strtab);
  307.     FreeVec(symtab);
  308.     FreeVec(shtab);
  309.     return last;
  310. }
  311.