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

编译器/解释器

开发平台:

C/C++

  1. /* rdoff.c    library of routines for manipulating rdoff files
  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. /* TODO: The functions in this module assume they are running
  13.  * on a little-endian machine. This should be fixed to
  14.  * make it portable.
  15.  *
  16.  * This module no longer supports RDOFF1. If anybody *really*
  17.  * needs the functionality of supporting both types at the
  18.  * same time, I'll add it back in.
  19.  */
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <errno.h>
  24. #include "rdoff.h"
  25. #define newstr(str) strcpy(malloc(strlen(str) + 1),str)
  26. #define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1) + strlen(s2) + 1), 
  27.                                        s1),s2)
  28. /*
  29.  * Comment this out to allow the module to read & write header record types
  30.  * that it isn't aware of. With this defined, unrecognised header records
  31.  * will generate error number 8, reported as 'unknown extended header record'.
  32.  */
  33. #define STRICT_ERRORS
  34. /* ========================================================================
  35.  * Code for memory buffers (for delayed writing of header until we know
  36.  * how long it is).
  37.  * ======================================================================== */
  38. memorybuffer * newmembuf()
  39. {
  40.     memorybuffer * t;
  41.     t = malloc(sizeof(memorybuffer));
  42.     t->length = 0;
  43.     t->next = NULL;
  44.     return t;
  45. }
  46. void membufwrite(memorybuffer *b, void *data, int bytes) 
  47. {
  48.     int16 w;
  49.     long l;
  50.     if (b->next) {        /* memory buffer full - use next buffer */
  51. membufwrite(b->next,data,bytes);
  52. return;
  53.     }
  54.     if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
  55. || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) 
  56.     {
  57.     
  58. /* buffer full and no next allocated... allocate and initialise next
  59.  * buffer */
  60. b->next = newmembuf();
  61. membufwrite(b->next,data,bytes);
  62. return;
  63.     }
  64.     switch(bytes) {
  65.     case -4:              /* convert to little-endian */
  66. l = * (long *) data ;
  67. b->buffer[b->length++] = l & 0xFF;
  68. l >>= 8 ;
  69. b->buffer[b->length++] = l & 0xFF;
  70. l >>= 8 ;
  71. b->buffer[b->length++] = l & 0xFF;
  72. l >>= 8 ;
  73. b->buffer[b->length++] = l & 0xFF;
  74. break;
  75.     case -2:
  76. w = * (int16 *) data ;
  77. b->buffer[b->length++] = w & 0xFF;
  78. w >>= 8 ;
  79. b->buffer[b->length++] = w & 0xFF;
  80. break;
  81.     default:
  82. while(bytes--) {
  83.     b->buffer[b->length++] = *(* (unsigned char **) &data);
  84.     
  85.     (* (unsigned char **) &data)++ ;
  86. }
  87. break;
  88.     }
  89. }
  90. void membufdump(memorybuffer *b,FILE *fp)
  91. {
  92.     if (!b) return;
  93.     fwrite (b->buffer, 1, b->length, fp);
  94.   
  95.     membufdump(b->next,fp);
  96. }
  97. int membuflength(memorybuffer *b)
  98. {
  99.     if (!b) return 0;
  100.     return b->length + membuflength(b->next);
  101. }
  102. void freemembuf(memorybuffer *b)
  103. {
  104.     if (!b) return;
  105.     freemembuf(b->next);
  106.     free(b);
  107. }
  108. /* =========================================================================
  109.    General purpose routines and variables used by the library functions
  110.    ========================================================================= */
  111. /* 
  112.  * translatelong() and translateshort()
  113.  *
  114.  * translate from little endian to local representation 
  115.  */
  116. long translatelong(long in) 
  117. {
  118.     long r;
  119.     unsigned char *i;
  120.     i = (unsigned char *)&in;
  121.     r = i[3];
  122.     r = (r << 8) + i[2];
  123.     r = (r << 8) + i[1];
  124.     r = (r << 8) + *i;
  125.     return r;
  126. }
  127. int16 translateshort(int16 in) 
  128. {
  129.     int16 r;
  130.     unsigned char * i;
  131.     
  132.     i = (unsigned char *)&in;
  133.     r = (i[1] << 8) + i[0];
  134.     return r;
  135. }
  136. const char *RDOFFId = "RDOFF2"; /* written to the start of RDOFF files */
  137. const char *rdf_errors[11] = {
  138.   "no error occurred","could not open file","invalid file format",
  139.   "error reading file","unknown error","header not read",
  140.   "out of memory", "RDOFF v1 not supported",
  141.   "unknown extended header record", 
  142.   "header record of known type but unknown length",
  143.   "no such segment"};
  144. int rdf_errno = 0;
  145. /* ========================================================================
  146.    The library functions
  147.    ======================================================================== */
  148. int rdfopen(rdffile *f, const char *name)
  149. {
  150.     FILE * fp;
  151.     fp = fopen(name,"rb");
  152.     if (!fp) return rdf_errno = 1; /* error 1: file open error */
  153.     return rdfopenhere(f,fp,NULL,name);
  154. }
  155. int rdfopenhere(rdffile *f, FILE *fp, int *refcount, const char *name)
  156. {
  157.   char buf[8];
  158.   long initpos;
  159.   long l;
  160.   int16 s;
  161.   if (translatelong(0x01020304) != 0x01020304)
  162.   { /* fix this to be portable! */
  163.     fputs("*** this program requires a little endian machinen",stderr);
  164.     fprintf(stderr,"01020304h = %08lxhn",translatelong(0x01020304));
  165.     exit(3);
  166.   }
  167.   f->fp = fp;
  168.   initpos = ftell(fp);
  169.   fread(buf,6,1,f->fp); /* read header */
  170.   buf[6] = 0;
  171.   if (strcmp(buf,RDOFFId)) {
  172.     fclose(f->fp);
  173.     if (!strcmp(buf,"RDOFF1"))
  174. return rdf_errno = 7; /* error 7: RDOFF 1 not supported */
  175.     return rdf_errno = 2;  /* error 2: invalid file format */
  176.   }
  177.   if (fread(&l,1,4,f->fp) != 4 ||
  178.       fread(&f->header_len,1,4,f->fp) != 4) {
  179.     fclose(f->fp);
  180.     return rdf_errno = 3; /* error 3: file read error */
  181.   }
  182.   f->header_ofs = ftell(f->fp);
  183.   f->eof_offset = f->header_ofs + translatelong(l) - 4;
  184.   if (fseek(f->fp,f->header_len,SEEK_CUR)) {
  185.     fclose(f->fp);
  186.     return rdf_errno = 2; /* seek past end of file...? */
  187.   }
  188.   if (fread(&s,1,2,f->fp) != 2) {
  189.       fclose(f->fp);
  190.       return rdf_errno = 3;
  191.   }
  192.   f->nsegs = 0;
  193.   while (s != 0)
  194.   {
  195.       f->seg[f->nsegs].type = s;
  196.       if (fread(&f->seg[f->nsegs].number,1,2,f->fp) != 2 ||
  197.   fread(&f->seg[f->nsegs].reserved,1,2,f->fp) != 2 ||
  198.   fread(&f->seg[f->nsegs].length,1,4,f->fp) != 4)
  199.       {
  200.   fclose(f->fp);
  201.   return rdf_errno = 3;
  202.       }
  203.       f->seg[f->nsegs].offset = ftell(f->fp);
  204.       if (fseek(f->fp,f->seg[f->nsegs].length,SEEK_CUR)) {
  205.   fclose(f->fp);
  206.   return rdf_errno = 2;
  207.       }
  208.       f->nsegs++;
  209.       if (fread(&s,1,2,f->fp) != 2) {
  210.   fclose(f->fp);
  211.   return rdf_errno = 3;
  212.       }
  213.   }
  214.   if (f->eof_offset != ftell(f->fp) + 8)  /* +8 = skip null segment header */
  215.   {
  216.       fprintf(stderr, "warning: eof_offset [%ld] and actual eof offset "
  217.       "[%ld] don't matchn", f->eof_offset, ftell(f->fp) + 8);
  218.   }
  219.   fseek(f->fp,initpos,SEEK_SET);
  220.   f->header_loc = NULL;
  221.   f->name = newstr(name);
  222.   f->refcount = refcount;
  223.   if (refcount) (*refcount)++;
  224.   return 0;
  225. }
  226. int rdfclose(rdffile *f)
  227. {
  228.     if (! f->refcount || ! --(*f->refcount))
  229. fclose(f->fp);
  230.     free(f->name);
  231.     return 0;
  232. }
  233. void rdfperror(const char *app,const char *name)
  234. {
  235.   fprintf(stderr,"%s:%s: %sn",app,name,rdf_errors[rdf_errno]);
  236.   if (rdf_errno == 1 || rdf_errno == 3)
  237.   {
  238.       perror(app);
  239.   }
  240. }
  241. int rdffindsegment(rdffile * f, int segno)
  242. {
  243.     int i;
  244.     for (i = 0; i < f->nsegs; i++)
  245. if (f->seg[i].number == segno) return i;
  246.     return -1;
  247. }
  248. int rdfloadseg(rdffile *f,int segment,void *buffer)
  249. {
  250.   long fpos;
  251.   long slen;
  252.   switch(segment) {
  253.   case RDOFF_HEADER:
  254.       fpos = f->header_ofs;
  255.       slen = f->header_len;
  256.       f->header_loc = (byte *)buffer;
  257.       f->header_fp = 0;
  258.       break;
  259.   default:
  260.       if (segment < f->nsegs) {
  261.   fpos = f->seg[segment].offset;
  262.   slen = f->seg[segment].length;
  263.   f->seg[segment].data = (byte *)buffer;
  264.       }
  265.       else {
  266.   return rdf_errno = 10; /* no such segment */
  267.       }
  268.   }
  269.   if (fseek(f->fp,fpos,SEEK_SET))
  270.     return rdf_errno = 4;
  271.     
  272.   if (fread(buffer,1,slen,f->fp) != slen)
  273.     return rdf_errno = 3;
  274.   return 0;
  275. }
  276. /* Macros for reading integers from header in memory */
  277. #define RI8(v) v = f->header_loc[f->header_fp++]
  278. #define RI16(v) { v = (f->header_loc[f->header_fp] + 
  279.        (f->header_loc[f->header_fp+1] << 8)); 
  280.   f->header_fp += 2; }
  281. #define RI32(v) { v = (f->header_loc[f->header_fp] + 
  282.        (f->header_loc[f->header_fp+1] << 8) + 
  283.        (f->header_loc[f->header_fp+2] << 16) + 
  284.        (f->header_loc[f->header_fp+3] << 24)); 
  285.   f->header_fp += 4; }
  286. #define RS(str,max) { for(i=0;i<max;i++){
  287.   RI8(str[i]); if (!str[i]) break;} str[i]=0; }
  288. rdfheaderrec *rdfgetheaderrec(rdffile *f)
  289. {
  290.   static rdfheaderrec r;
  291.   int i;
  292.   if (!f->header_loc) {
  293.     rdf_errno = 5;
  294.     return NULL;
  295.   }
  296.   if (f->header_fp >= f->header_len) return 0;
  297.   RI8(r.type);
  298.   RI8(r.g.reclen);
  299.   switch(r.type) {
  300.   case 1: /* Relocation record */
  301.   case 6:
  302.       if (r.r.reclen != 8) {
  303.   rdf_errno = 9;
  304.   return NULL;
  305.       }
  306.     RI8(r.r.segment);
  307.     RI32(r.r.offset);
  308.     RI8(r.r.length);
  309.     RI16(r.r.refseg);
  310.     break;
  311.   case 2: /* Imported symbol record */
  312.   case 7:
  313.     RI16(r.i.segment);
  314.     RS(r.i.label,32);
  315.     break;
  316.   case 3: /* Exported symbol record */
  317.     RI8(r.e.segment);
  318.     RI32(r.e.offset);
  319.     RS(r.e.label,32);
  320.     break;
  321.   case 4: /* DLL record */
  322.     RS(r.d.libname,127);
  323.     break;
  324.   case 5: /* BSS reservation record */
  325.       if (r.r.reclen != 4) {
  326.   rdf_errno = 9;
  327.   return NULL;
  328.       }
  329.     RI32(r.b.amount);
  330.     break;
  331.   default:
  332. #ifdef STRICT_ERRORS
  333.     rdf_errno = 8; /* unknown header record */
  334.     return NULL;
  335. #else
  336.     for (i = 0; i < r.g.reclen; i++)
  337. RI8(r.g.data[i]);
  338. #endif
  339.   }
  340.   return &r;
  341. }
  342.     
  343. void rdfheaderrewind(rdffile *f)
  344. {
  345.   f->header_fp = 0;
  346. }
  347. rdf_headerbuf * rdfnewheader(void)
  348. {
  349.     rdf_headerbuf * hb = malloc(sizeof(hb));
  350.     if (hb == NULL) return NULL;
  351.     hb->buf = newmembuf();
  352.     hb->nsegments = 0;
  353.     hb->seglength = 0;
  354.     return hb;
  355. }
  356. int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
  357. {
  358. #ifndef STRICT_ERRORS
  359.     int i;
  360. #endif
  361.     membufwrite(h->buf,&r->type,1);
  362.     membufwrite(h->buf,&r->g.reclen,1);
  363.     switch (r->type)
  364.     {
  365.     case 1:
  366.     case 6:
  367. membufwrite(h->buf,&r->r.segment,1);
  368. membufwrite(h->buf,&r->r.offset,-4);
  369. membufwrite(h->buf,&r->r.length,1);
  370. membufwrite(h->buf,&r->r.refseg,-2);    /* 9 bytes written */
  371. break;
  372.     case 2: /* import */
  373.     case 7:
  374. membufwrite(h->buf,&r->i.segment,-2);
  375. membufwrite(h->buf,&r->i.label,strlen(r->i.label) + 1);
  376. break ;
  377.     case 3: /* export */
  378. membufwrite(h->buf,&r->e.segment,1);
  379. membufwrite(h->buf,&r->e.offset,-4);
  380. membufwrite(h->buf,&r->e.label,strlen(r->e.label) + 1);
  381. break ;
  382.     case 4: /* DLL */
  383. membufwrite(h->buf,&r->d.libname,strlen(r->d.libname) + 1);
  384. break ;
  385.     case 5: /* BSS */
  386. membufwrite(h->buf,&r->b.amount,-4);
  387. break ;
  388.     default:
  389. #ifdef STRICT_ERRORS
  390. return (rdf_errno = 8);
  391. #else
  392. for (i = 0; i < r->g.reclen; i++)
  393.     membufwrite(h->buf, r->g.data[i], 1);
  394. #endif
  395.     }
  396.     return 0;
  397. }
  398. int rdfaddsegment(rdf_headerbuf *h, long seglength)
  399. {
  400.     h->nsegments ++;
  401.     h->seglength += seglength;
  402.     return 0;
  403. }
  404. int rdfwriteheader(FILE * fp, rdf_headerbuf * h)
  405. {
  406.     long l, l2;
  407.     fwrite (RDOFFId, 1, strlen(RDOFFId), fp) ;
  408.     l = membuflength (h->buf);
  409.     l2 = l + 14 + 10*h->nsegments + h->seglength;
  410.     l = translatelong(l);
  411.     l2 = translatelong(l2);
  412.     fwrite (&l2, 4, 1, fp); /* object length */
  413.     fwrite (&l, 4, 1, fp); /* header length */
  414.     membufdump(h->buf, fp);
  415.     return 0; /* no error handling in here... CHANGE THIS! */
  416. }
  417. void rdfdoneheader(rdf_headerbuf * h)
  418. {
  419.     freemembuf(h->buf);
  420.     free(h);
  421. }