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. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include "rdfload.h"
  15. #include "symtab.h"
  16. #include "rdoff.h"
  17. #include "collectn.h"
  18. extern int rdf_errno;
  19. rdfmodule * rdfload(const char *filename)
  20. {
  21.     rdfmodule  * f = malloc(sizeof(rdfmodule));
  22.     long  bsslength = 0;
  23.     char * hdr;
  24.     rdfheaderrec *r;
  25.     if (f == NULL) 
  26.     {
  27. rdf_errno = 6; /* out of memory */
  28. return NULL;
  29.     }
  30.     f->symtab = symtabNew();
  31.     if (!f->symtab)
  32.     {
  33. free(f);
  34. rdf_errno = 6;
  35. return NULL;
  36.     }
  37.     /* open the file */
  38.     if ( rdfopen( &(f->f), filename ) ) {
  39. free(f);
  40. return NULL;
  41.     }
  42.     /* read in text and data segments, and header */
  43.     
  44.     f->t = malloc (f->f.code_len);
  45.     f->d = malloc (f->f.data_len); /* BSS seg allocated later */
  46.     hdr = malloc (f->f.header_len);
  47.     if (! f->t || ! f->d || !hdr) {
  48. rdf_errno = 6;
  49. rdfclose(&f->f);
  50. if (f->t) free(f->t);
  51. if (f->d) free(f->d);
  52. free(f);
  53. return NULL;
  54.     }
  55.     if ( rdfloadseg (&f->f,RDOFF_HEADER,hdr) ||
  56.  rdfloadseg (&f->f,RDOFF_CODE,f->t) ||
  57.  rdfloadseg (&f->f,RDOFF_DATA,f->d) )
  58.     {
  59. rdfclose(&f->f);
  60. free(f->t);
  61. free(f->d);
  62. free(f);
  63. free(hdr);
  64. return NULL;
  65.     }
  66.     rdfclose(&f->f);
  67.     /* Allocate BSS segment; step through header and count BSS records */
  68.     while ( ( r = rdfgetheaderrec (&f->f) ) )
  69.     {
  70. if (r->type == 5)
  71.     bsslength += r->b.amount;
  72.     }
  73.     f->b = malloc ( bsslength );
  74.     if (! f->b )
  75.     {
  76. free(f->t);
  77. free(f->d);
  78. free(f);
  79. free(hdr);
  80. rdf_errno = 6;
  81. return NULL;
  82.     }
  83.     rdfheaderrewind (&f->f);
  84.     f->textrel = (long)f->t;
  85.     f->datarel = (long)f->d;
  86.     f->bssrel  = (long)f->b;
  87.     return f;
  88. }
  89. int rdf_relocate(rdfmodule * m)
  90. {
  91.     rdfheaderrec * r;
  92.     Collection imports;    
  93.     symtabEnt e;
  94.     long rel;
  95.     unsigned char * seg;
  96.     
  97.     rdfheaderrewind ( & m->f );
  98.     collection_init(&imports);
  99.     while ( (r = rdfgetheaderrec ( & m->f ) ) )
  100.     {
  101. switch (r->type)
  102. {
  103. case 1: /* Relocation record */
  104.     /* calculate relocation factor */
  105.     if (r->r.refseg == 0) rel = m->textrel;
  106.     else if (r->r.refseg == 1) rel = m->datarel;
  107.     else if (r->r.refseg == 2) rel = m->bssrel;
  108.     else
  109. /* We currently do not support load-time linkage.
  110.    This should be added some time soon... */
  111. return 1; /* return error code */
  112.     if ((r->r.segment & 63) == 0) seg = m->t;
  113.     else if ((r->r.segment & 63) == 1) seg = m->d;
  114.     else
  115. return 1;
  116.     /* it doesn't matter in this case that the code is non-portable,
  117.        as the entire concept of executing a module like this is
  118.        non-portable */
  119.     switch(r->r.length) {
  120.     case 1:
  121. seg[r->r.offset] += (char) rel;
  122. break;
  123.     case 2:
  124. *(int16 *)(seg + r->r.offset) += (int16) rel;
  125. break;
  126.     case 4:
  127. *(long *)(seg + r->r.offset) += rel;
  128. break;
  129.     }
  130.     break;
  131. case 3: /* export record - add to symtab */
  132.     e.segment = r->e.segment;
  133.     e.offset = r->e.offset + 
  134.                (e.segment == 0 ? m->textrel : /* 0 -> code */
  135. e.segment == 1 ? m->datarel : /* 1 -> data */
  136.                  m->bssrel) ; /* 2 -> bss  */
  137.     e.flags = 0;
  138.     e.name = malloc(strlen(r->e.label) + 1);
  139.     if (! e.name)
  140. return 1;
  141.     strcpy(e.name,r->e.label);
  142.     symtabInsert(m->symtab,&e);
  143.     break;
  144. }
  145.     }    
  146.     return 0;
  147. }