rdfload.c
上传用户:yuppie_zhu
上传日期:2007-01-08
资源大小:535k
文件大小:4k
源码类别:

编译器/解释器

开发平台:

C/C++

  1. /* rdfload.c RDOFF Object File loader library
  2.  *
  3.  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  4.  * Julian Hall. All rights reserved. The software is
  5.  * redistributable under the licence given in the file "Licence"
  6.  * distributed in the NASM archive.
  7.  *
  8.  * Permission to use this file in your own projects is granted, as long
  9.  * as acknowledgement is given in an appropriate manner to its authors,
  10.  * with instructions of how to obtain a copy via ftp.
  11.  */
  12. /*
  13.  * TODO: this has been modified from previous version only in very
  14.  * simplistic ways. Needs to be improved drastically, especially:
  15.  *   - support for more than the 2 standard segments
  16.  *   - support for segment relocations (hard to do in ANSI C)
  17.  */
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include "rdfload.h"
  21. #include "symtab.h"
  22. #include "rdoff.h"
  23. #include "collectn.h"
  24. extern int rdf_errno;
  25. rdfmodule * rdfload(const char *filename)
  26. {
  27.     rdfmodule  * f = malloc(sizeof(rdfmodule));
  28.     long  bsslength = 0;
  29.     char * hdr;
  30.     rdfheaderrec *r;
  31.     if (f == NULL) 
  32.     {
  33. rdf_errno = 6; /* out of memory */
  34. return NULL;
  35.     }
  36.     f->symtab = symtabNew();
  37.     if (!f->symtab)
  38.     {
  39. free(f);
  40. rdf_errno = 6;
  41. return NULL;
  42.     }
  43.     /* open the file */
  44.     if ( rdfopen( &(f->f), filename ) ) {
  45. free(f);
  46. return NULL;
  47.     }
  48.     /* read in text and data segments, and header */
  49.     
  50.     f->t = malloc (f->f.seg[0].length);
  51.     f->d = malloc (f->f.seg[1].length); /* BSS seg allocated later */
  52.     hdr = malloc (f->f.header_len);
  53.     if (! f->t || ! f->d || !hdr) {
  54. rdf_errno = 6;
  55. rdfclose(&f->f);
  56. if (f->t) free(f->t);
  57. if (f->d) free(f->d);
  58. free(f);
  59. return NULL;
  60.     }
  61.     if ( rdfloadseg (&f->f,RDOFF_HEADER,hdr) ||
  62.  rdfloadseg (&f->f,RDOFF_CODE,f->t) ||
  63.  rdfloadseg (&f->f,RDOFF_DATA,f->d) )
  64.     {
  65. rdfclose(&f->f);
  66. free(f->t);
  67. free(f->d);
  68. free(f);
  69. free(hdr);
  70. return NULL;
  71.     }
  72.     rdfclose(&f->f);
  73.     /* Allocate BSS segment; step through header and count BSS records */
  74.     while ( ( r = rdfgetheaderrec (&f->f) ) )
  75.     {
  76. if (r->type == 5)
  77.     bsslength += r->b.amount;
  78.     }
  79.     f->b = malloc ( bsslength );
  80.     if (! f->b )
  81.     {
  82. free(f->t);
  83. free(f->d);
  84. free(f);
  85. free(hdr);
  86. rdf_errno = 6;
  87. return NULL;
  88.     }
  89.     rdfheaderrewind (&f->f);
  90.     f->textrel = (long)f->t;
  91.     f->datarel = (long)f->d;
  92.     f->bssrel  = (long)f->b;
  93.     return f;
  94. }
  95. int rdf_relocate(rdfmodule * m)
  96. {
  97.     rdfheaderrec * r;
  98.     Collection imports;    
  99.     symtabEnt e;
  100.     long rel;
  101.     unsigned char * seg;
  102.     
  103.     rdfheaderrewind ( & m->f );
  104.     collection_init(&imports);
  105.     while ( (r = rdfgetheaderrec ( & m->f ) ) )
  106.     {
  107. switch (r->type)
  108. {
  109. case 1: /* Relocation record */
  110.     /* calculate relocation factor */
  111.     if (r->r.refseg == 0) rel = m->textrel;
  112.     else if (r->r.refseg == 1) rel = m->datarel;
  113.     else if (r->r.refseg == 2) rel = m->bssrel;
  114.     else
  115. /* We currently do not support load-time linkage.
  116.    This should be added some time soon... */
  117. return 1; /* return error code */
  118.     if ((r->r.segment & 63) == 0) seg = m->t;
  119.     else if ((r->r.segment & 63) == 1) seg = m->d;
  120.     else
  121. continue; /* relocation not in a loaded segment */
  122.     /* it doesn't matter in this case that the code is non-portable,
  123.        as the entire concept of executing a module like this is
  124.        non-portable */
  125.     switch(r->r.length) {
  126.     case 1:
  127. seg[r->r.offset] += (char) rel;
  128. break;
  129.     case 2:
  130. *(int16 *)(seg + r->r.offset) += (int16) rel;
  131. break;
  132.     case 4:
  133. *(long *)(seg + r->r.offset) += rel;
  134. break;
  135.     }
  136.     break;
  137. case 3: /* export record - add to symtab */
  138.     e.segment = r->e.segment;
  139.     e.offset = r->e.offset + 
  140.                (e.segment == 0 ? m->textrel : /* 0 -> code */
  141. e.segment == 1 ? m->datarel : /* 1 -> data */
  142.                  m->bssrel) ; /* 2 -> bss  */
  143.     e.flags = 0;
  144.     e.name = malloc(strlen(r->e.label) + 1);
  145.     if (! e.name)
  146. return 1;
  147.     strcpy(e.name,r->e.label);
  148.     symtabInsert(m->symtab,&e);
  149.     break;
  150. case 6: /* segment relocation */
  151.     fprintf(stderr, "%s: segment relocation not supported by this "
  152.     "loadern", m->f.name);
  153.     return 1;
  154. }
  155.     }    
  156.     return 0;
  157. }