home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / C / SASC6571.LZX / extras / abslink / load.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-24  |  6.2 KB  |  321 lines

  1. #include <proto/dos.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "load.h"
  6.  
  7. int myprintf(char *ctl, ...);
  8.  
  9. void UnLoad(MODULE *p)
  10. {
  11.    int i;
  12.    HUNK *h;
  13.    for(i=0, h=p->hunks; i<p->hnum; i++, h++)
  14.    {
  15.       if(h->size)
  16.          free(h->data);
  17.    }
  18.  
  19.    memset(p, 0, sizeof(p));
  20. }
  21.  
  22. static int GetLong(BPTR fp, long *res)
  23. {
  24.    long l;
  25.    int rc;
  26.  
  27.    if(res == NULL) res = &l;
  28.  
  29.    rc = FRead(fp, res, 4, 1);
  30.  
  31.    if(rc < 0) return(99);
  32.  
  33.    if(rc == 0) return(-1);
  34.  
  35.    return(0);
  36. }
  37.  
  38. static int Skip(BPTR fp, long count)
  39. {
  40.    char buf[256];
  41.    long amt;
  42.    while(count)
  43.    {
  44.       amt = count > sizeof(buf) ? sizeof(buf) : count;
  45.       if(FRead(fp, buf, 1, amt) <= 0) return(-1);
  46.       count -= amt;
  47.    }
  48.    return(0);
  49. }
  50.  
  51. static int SkipNBlock(BPTR fp)
  52. {
  53.    int rc;
  54.    int count;
  55.  
  56.    if(FRead(fp, &count, 4, 1) <= 0) return(-1);
  57.  
  58.    if(rc=Skip(fp, count*4))
  59.       return(rc);
  60.  
  61.    return(count);
  62. }
  63.  
  64. static int SkipSymbolInfo(BPTR fp)
  65. {
  66.    long namelen;
  67.    int nsymbols = 0;
  68.  
  69.    while(1)
  70.    {
  71.       if(GetLong(fp, &namelen))
  72.          return(-1);
  73.  
  74.       if(namelen == 0)
  75.          return(nsymbols);
  76.  
  77.       if(namelen & 0xff000000)
  78.       {
  79.          myprintf("ERROR: Bad symbol hunk header 0x%08lx\n", namelen);
  80.          return(-1);
  81.       }
  82.  
  83.       nsymbols++;
  84.  
  85.       if(Skip(fp, namelen*4))
  86.          return(-1);
  87.  
  88.       if(GetLong(fp, NULL))   /* Symbol location */
  89.          return(-1);
  90.    }
  91. }
  92.  
  93. static int GetHunkHeader(MODULE *p, BPTR fp, unsigned long addr)
  94. {
  95.    long l;
  96.    int i;
  97.    char *reason = NULL;
  98.  
  99.    if(GetLong(fp, &l) || l != HUNK_HEADER)
  100.    {
  101.       reason = "No HUNK_HEADER";
  102.       goto badfile;
  103.    }
  104.  
  105.    while(SkipNBlock(fp) > 0);
  106.  
  107.    if(GetLong(fp, &p->hnum) || p->hnum<=0)
  108.    {
  109.       reason = "Can't read hunk table size";
  110.       goto badfile;
  111.    }
  112.  
  113.    GetLong(fp, NULL);
  114.    GetLong(fp, NULL);  // First and last hunks
  115.  
  116.    if(!(p->hunks = malloc(p->hnum*sizeof(HUNK))))
  117.    {
  118.       reason = "Out of memory\n";
  119.       goto badfile;
  120.    }
  121.  
  122.    memset(p->hunks, 0, p->hnum*sizeof(HUNK));
  123.  
  124.    for(i=0; i<p->hnum; i++)
  125.    {
  126.       if(GetLong(fp, &p->hunks[i].size))
  127.       {
  128.          reason = "Can't read hunk size table";
  129.          goto badfile;
  130.       }
  131.       if(!(p->hunks[i].data = malloc(p->hunks[i].size*4)))
  132.       {
  133.          reason = "Out of memory";
  134.          goto badfile;
  135.       }
  136.       p->hunks[i].addr = addr;
  137.       addr += p->hunks[i].size*4;
  138.    }
  139.  
  140.    return(0);
  141.  
  142.    badfile:
  143.    myprintf("ERROR: File could not be loaded\n");
  144.    if(reason) myprintf("       %s\n", reason);
  145.  
  146.    return(99);
  147. }
  148.  
  149. static int DoRelocs(MODULE *p, BPTR fp)
  150. {
  151.    long count, ocount;
  152.    long offset, loc;
  153.    char *data;
  154.  
  155.    if(GetLong(fp, &ocount)) return(-1);
  156.  
  157.    if(ocount != 0)
  158.    {
  159.       if(GetLong(fp, &offset)) return(-1);
  160.  
  161.       offset = (long)p->hunks[offset].addr;
  162.  
  163.       count = ocount;
  164.  
  165.       data = p->hunks[p->hcur-1].data;
  166.  
  167.       while(count--)
  168.       {
  169.          if(GetLong(fp, &loc)) return(-1);
  170.          *(long *)(data+loc) += offset;
  171.       }
  172.    }
  173.  
  174.    return(ocount);
  175. }
  176.  
  177. int Load(MODULE *p, char *file, unsigned long addr)
  178. {
  179.    BPTR fp;
  180.    long l;
  181.    int rc, i;
  182.    HUNK *h;
  183.    int dataread;
  184.  
  185.    if(!(fp = Open(file, MODE_OLDFILE)))
  186.    {
  187.       myprintf("ERROR: Can't open file \"%s\"\n", file);
  188.       return(99);
  189.    }
  190.  
  191.    if(GetHunkHeader(p, fp, addr))
  192.       return(99);
  193.  
  194.    while(!(rc=GetLong(fp, &l)))
  195.    {
  196.       switch(l)
  197.       {
  198.          case HUNK_UNIT:
  199.          case HUNK_NAME:
  200.             SkipNBlock(fp);
  201.             break;
  202.  
  203.          case HUNK_CODE:
  204.             if(GetLong(fp, &l) || l < 0)
  205.             {
  206.                myprintf("Error reading Code hunk\n");
  207.                goto badfile;
  208.             }
  209.             h = p->hunks + p->hcur++;
  210.             h->type = HUNK_CODE;
  211.             dataread = l*4;
  212.             if(p->entry == NULL) p->entry = (int (*)(void))h->data;
  213.             goto dohunk;
  214.  
  215.          case HUNK_DATA:
  216.             if(GetLong(fp, &l) || l < 0)
  217.             {
  218.                myprintf("Error reading Data hunk\n");
  219.                goto badfile;
  220.             }
  221.             h = p->hunks + p->hcur++;
  222.             h->type = HUNK_DATA;
  223.             dataread = l*4;
  224.  
  225.             dohunk:
  226.             if(h->size < l)
  227.             {
  228.                myprintf("Invalid hunk size for hunk #%d\n",
  229.                   p->hcur-1);
  230.                goto badfile;
  231.             }
  232.             if(dataread && FRead(fp, h->data, dataread, 1) <= 0)
  233.             {
  234.                myprintf("I/O error or unexpected EOF\n");
  235.                goto badfile;
  236.             }
  237.             if(h->size > l)
  238.             {
  239.                l *= 4;
  240.                memset(((char *)h->data) + l, 0, h->size*4 -l);
  241.             }
  242.             break;
  243.  
  244.          case HUNK_BSS:
  245.             if(GetLong(fp, &l) || l < 0)
  246.             {
  247.                myprintf("Error reading BSS hunk\n");
  248.                goto badfile;
  249.             }
  250.             h = p->hunks + p->hcur++;
  251.             h->type = HUNK_BSS;
  252.             dataread = 0;
  253.             memset(h->data, 0, l*4);
  254.             break;
  255.  
  256.          case HUNK_RELOC32:
  257.             while(rc=DoRelocs(p, fp));
  258.             if(rc<0) goto badfile;
  259.             break;
  260.  
  261.          case HUNK_RELOC16:
  262.          case HUNK_RELOC8:
  263.          case HUNK_EXT:
  264.             goto unimp;
  265.  
  266.          case HUNK_SYMBOL:
  267.             if(SkipSymbolInfo(fp) < 0)
  268.             {
  269.                myprintf("Error reading HUNK_SYMBOL\n");
  270.                goto badfile;
  271.             }
  272.             break;
  273.          
  274.          case HUNK_DEBUG:
  275.             SkipNBlock(fp);
  276.             break;
  277.  
  278.          case HUNK_END:
  279.             break;
  280.  
  281.          case HUNK_HEADER:
  282.             myprintf("Error: Unexpected HUNK_HEADER\n");
  283.             goto badfile;
  284.  
  285.          case HUNK_OVERLAY:
  286.          case HUNK_BREAK:
  287.          case HUNK_DREL32:
  288.          case HUNK_DREL16:
  289.          case HUNK_DREL8:
  290.          case HUNK_LIB:
  291.          case HUNK_INDEX:
  292.          unimp:
  293.             myprintf("Error: Unimplemented hunk type %d\n", l);
  294.             goto badfile;
  295.  
  296.          default:
  297.             myprintf("Error: Unrecognized hunk type %d\n", l);
  298.             goto badfile;
  299.       }
  300.    }
  301.    if(rc > 0)
  302.    {
  303.       poserr("ERROR: I/O error loading program file: ");
  304.       goto badfile;
  305.    }
  306.  
  307.    // Set any uninitialized hunks to zeroes
  308.    for(i=0, h=p->hunks; i<p->hnum; i++, h++)
  309.    {
  310.       if(h->type == 0 && h->size)
  311.          memset(h->data, 0, h->size*4);
  312.    }
  313.  
  314.    Close(fp);
  315.    return(0);
  316.  
  317. badfile:
  318.    Close(fp);
  319.    return(99);
  320. }
  321.