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

编译器/解释器

开发平台:

C/C++

  1. /* outbin.c output routines for the Netwide Assembler to produce
  2.  * flat-form binary files
  3.  *
  4.  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  5.  * Julian Hall. All rights reserved. The software is
  6.  * redistributable under the licence given in the file "Licence"
  7.  * distributed in the NASM archive.
  8.  */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13. #include "nasm.h"
  14. #include "nasmlib.h"
  15. #include "outform.h"
  16. #ifdef OF_BIN
  17. static FILE *fp;
  18. static efunc error;
  19. static struct Section {
  20.     struct SAA *contents;
  21.     long length;
  22.     long index;
  23. } textsect, datasect;
  24. static long bsslen, bssindex;
  25. static struct Reloc {
  26.     struct Reloc *next;
  27.     long posn;
  28.     long bytes;
  29.     long secref;
  30.     long secrel;
  31.     struct Section *target;
  32. } *relocs, **reloctail;
  33. static long data_align, bss_align;
  34. static long start_point;
  35. static void add_reloc (struct Section *s, long bytes, long secref,
  36.        long secrel) 
  37. {
  38.     struct Reloc *r;
  39.     r = *reloctail = nasm_malloc(sizeof(struct Reloc));
  40.     reloctail = &r->next;
  41.     r->next = NULL;
  42.     r->posn = s->length;
  43.     r->bytes = bytes;
  44.     r->secref = secref;
  45.     r->secrel = secrel;
  46.     r->target = s;
  47. }
  48. static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval) 
  49. {
  50.     fp = afp;
  51.     (void) eval;   /* Don't warn that this parameter is unused */
  52.     error = errfunc;
  53.     (void) ldef;        /* placate optimisers */
  54.     start_point = 0L;        /* default */
  55.     textsect.contents = saa_init(1L);
  56.     datasect.contents = saa_init(1L);
  57.     textsect.length = datasect.length = 0;
  58.     textsect.index = seg_alloc();
  59.     datasect.index = seg_alloc();
  60.     bsslen = 0;
  61.     bssindex = seg_alloc();
  62.     relocs = NULL;
  63.     reloctail = &relocs;
  64.     data_align = bss_align = 4;
  65. }
  66. static void bin_cleanup (int debuginfo) 
  67. {
  68.     struct Reloc *r;
  69.     long datapos, datagap, bsspos;
  70.     (void) debuginfo;
  71.     datapos = start_point + textsect.length;
  72.     datapos = (datapos + data_align-1) & ~(data_align-1);
  73.     datagap = datapos - (start_point + textsect.length);
  74.     bsspos = datapos + datasect.length;
  75.     bsspos = (bsspos + bss_align-1) & ~(bss_align-1);
  76.     saa_rewind (textsect.contents);
  77.     saa_rewind (datasect.contents);
  78.     for (r = relocs; r; r = r->next) 
  79.     {
  80. unsigned char *p, *q, mydata[4];
  81. long l;
  82. saa_fread (r->target->contents, r->posn, mydata, r->bytes);
  83. p = q = mydata;
  84. l = *p++;
  85. if (r->bytes > 1) {
  86.     l += ((long)*p++) << 8;
  87.     if (r->bytes == 4) {
  88. l += ((long)*p++) << 16;
  89. l += ((long)*p++) << 24;
  90.     }
  91. }
  92. if (r->secref == textsect.index)
  93.     l += start_point;
  94. else if (r->secref == datasect.index)
  95.     l += datapos;
  96. else if (r->secref == bssindex)
  97.     l += bsspos;
  98. if (r->secrel == textsect.index)
  99.     l -= start_point;
  100. else if (r->secrel == datasect.index)
  101.     l -= datapos;
  102. else if (r->secrel == bssindex)
  103.     l -= bsspos;
  104. if (r->bytes == 4)
  105.     WRITELONG(q, l);
  106. else if (r->bytes == 2)
  107.     WRITESHORT(q, l);
  108. else
  109.     *q++ = l & 0xFF;
  110. saa_fwrite (r->target->contents, r->posn, mydata, r->bytes);
  111.     }
  112.     saa_fpwrite (textsect.contents, fp);
  113.     if (datasect.length > 0) {
  114. while (datagap--)
  115.     fputc('', fp);
  116. saa_fpwrite (datasect.contents, fp);
  117.     }
  118.     fclose (fp);
  119.     saa_free (textsect.contents);
  120.     saa_free (datasect.contents);
  121.     while (relocs) {
  122. r = relocs->next;
  123. nasm_free (relocs);
  124. relocs = r;
  125.     }
  126. }
  127. static void bin_out (long segto, void *data, unsigned long type,
  128.      long segment, long wrt) 
  129. {
  130.     unsigned char *p, mydata[4];
  131.     struct Section *s;
  132.     long realbytes;
  133.     if (wrt != NO_SEG) {
  134. wrt = NO_SEG;        /* continue to do _something_ */
  135. error (ERR_NONFATAL, "WRT not supported by binary output format");
  136.     }
  137.     /*
  138.      * handle absolute-assembly (structure definitions)
  139.      */
  140.     if (segto == NO_SEG) {
  141. if ((type & OUT_TYPMASK) != OUT_RESERVE)
  142.     error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
  143.    " space");
  144. return;
  145.     }
  146.     if (segto == bssindex) {        /* BSS */
  147. if ((type & OUT_TYPMASK) != OUT_RESERVE)
  148.     error(ERR_WARNING, "attempt to initialise memory in the"
  149.   " BSS section: ignored");
  150. s = NULL;
  151.     } else if (segto == textsect.index) {
  152. s = &textsect;
  153.     } else if (segto == datasect.index) {
  154. s = &datasect;
  155.     } else {
  156. error(ERR_WARNING, "attempt to assemble code in"
  157.       " segment %d: defaulting to `.text'", segto);
  158. s = &textsect;
  159.     }
  160.     if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
  161. if (segment != NO_SEG &&
  162.     segment != textsect.index &&
  163.     segment != datasect.index &&
  164.     segment != bssindex) {
  165.     if (segment % 2)
  166. error(ERR_NONFATAL, "binary output format does not support"
  167.       " segment base references");
  168.     else
  169. error(ERR_NONFATAL, "binary output format does not support"
  170.       " external references");
  171.     segment = NO_SEG;
  172. }
  173. if (s) {
  174.     if (segment != NO_SEG)
  175. add_reloc (s, type & OUT_SIZMASK, segment, -1L);
  176.     p = mydata;
  177.     if ((type & OUT_SIZMASK) == 4)
  178. WRITELONG (p, *(long *)data);
  179.     else
  180. WRITESHORT (p, *(long *)data);
  181.     saa_wbytes (s->contents, mydata, type & OUT_SIZMASK);
  182.     s->length += type & OUT_SIZMASK;
  183. } else
  184.     bsslen += type & OUT_SIZMASK;
  185.     } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
  186. type &= OUT_SIZMASK;
  187. p = data;
  188. if (s) {
  189.     saa_wbytes (s->contents, data, type);
  190.     s->length += type;
  191. } else
  192.     bsslen += type;
  193.     } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
  194. if (s) {
  195.     error(ERR_WARNING, "uninitialised space declared in"
  196.   " %s section: zeroing",
  197.   (segto == textsect.index ? "code" : "data"));
  198. }
  199. type &= OUT_SIZMASK;
  200. if (s) {
  201.     saa_wbytes (s->contents, NULL, type);
  202.     s->length += type;
  203. } else
  204.     bsslen += type;
  205.     } 
  206.     else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
  207.      (type & OUT_TYPMASK) == OUT_REL4ADR) 
  208.     {
  209. realbytes = ((type & OUT_TYPMASK) == OUT_REL4ADR ? 4 : 2);
  210. if (segment != NO_SEG &&
  211.     segment != textsect.index &&
  212.     segment != datasect.index &&
  213.     segment != bssindex) {
  214.     if (segment % 2)
  215. error(ERR_NONFATAL, "binary output format does not support"
  216.       " segment base references");
  217.     else
  218. error(ERR_NONFATAL, "binary output format does not support"
  219.       " external references");
  220.     segment = NO_SEG;
  221. }
  222. if (s) {
  223.     add_reloc (s, realbytes, segment, segto);
  224.     p = mydata;
  225.     if (realbytes == 4)
  226. WRITELONG (p, *(long*)data - realbytes - s->length);
  227.     else
  228. WRITESHORT (p, *(long*)data - realbytes - s->length);
  229.     saa_wbytes (s->contents, mydata, realbytes);
  230.     s->length += realbytes;
  231. } else
  232.     bsslen += realbytes;
  233.     }
  234. }
  235. static void bin_deflabel (char *name, long segment, long offset,
  236.   int is_global, char *special) 
  237. {
  238.     (void) segment;   /* Don't warn that this parameter is unused */
  239.     (void) offset;    /* Don't warn that this parameter is unused */
  240.     if (special)
  241. error (ERR_NONFATAL, "binary format does not support any"
  242.        " special symbol types");
  243.     if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
  244. error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
  245. return;
  246.     }
  247.     if (is_global == 2) {
  248. error (ERR_NONFATAL, "binary output format does not support common"
  249.        " variables");
  250.     }
  251. }
  252. static long bin_secname (char *name, int pass, int *bits) 
  253. {
  254.     int sec_index;
  255.     long *sec_align;
  256.     char *p;
  257.     (void) pass;   /* Don't warn that this parameter is unused */
  258.     /*
  259.      * Default is 16 bits.
  260.      */
  261.     if (!name)
  262. *bits = 16;
  263.     if (!name)
  264. return textsect.index;
  265.     p = name;
  266.     while (*p && !isspace(*p)) p++;
  267.     if (*p) *p++ = '';
  268.     if (!strcmp(name, ".text")) {
  269. sec_index = textsect.index;
  270. sec_align = NULL;
  271.     } else if (!strcmp(name, ".data")) {
  272. sec_index = datasect.index;
  273. sec_align = &data_align;
  274.     } else if (!strcmp(name, ".bss")) {
  275. sec_index = bssindex;
  276. sec_align = &bss_align;
  277.     } else
  278. return NO_SEG;
  279.     if (*p) {
  280. if (!nasm_strnicmp(p,"align=",6)) {
  281.     if (sec_align == NULL)
  282. error(ERR_NONFATAL, "cannot specify an alignment to"
  283.       " the `.text' section");
  284.     else if (p[6+strspn(p+6,"0123456789")])
  285. error(ERR_NONFATAL, "argument to `align' is not numeric");
  286.     else {
  287. unsigned int align = atoi(p+6);
  288. if (!align || ((align-1) & align))
  289.     error(ERR_NONFATAL, "argument to `align' is not a"
  290.   " power of two");
  291. else
  292.     *sec_align = align;
  293.     }
  294. }
  295.     }
  296.     return sec_index;
  297. }
  298. static long bin_segbase (long segment) 
  299. {
  300.     return segment;
  301. }
  302. static int bin_directive (char *directive, char *value, int pass) 
  303. {
  304.     int rn_error;
  305.     (void) pass;   /* Don't warn that this parameter is unused */
  306.     if (!strcmp(directive, "org")) {
  307. start_point = readnum (value, &rn_error);
  308. if (rn_error)
  309.     error (ERR_NONFATAL, "argument to ORG should be numeric");
  310. return 1;
  311.     } else
  312. return 0;
  313. }
  314. static void bin_filename (char *inname, char *outname, efunc error) 
  315. {
  316.     standard_extension (inname, outname, "", error);
  317. }
  318. static char *bin_stdmac[] = {
  319.     "%define __SECT__ [section .text]",
  320.     "%imacro org 1+.nolist",
  321.     "[org %1]",
  322.     "%endmacro",
  323.     "%macro __NASM_CDecl__ 1",
  324.     "%endmacro",
  325.     NULL
  326. };
  327. static int bin_set_info(enum geninfo type, char **val)
  328. {
  329.     return 0;
  330. }
  331. struct ofmt of_bin = {
  332.     "flat-form binary files (e.g. DOS .COM, .SYS)",
  333.     "bin",
  334.     NULL,
  335.     null_debug_arr,
  336.     &null_debug_form,
  337.     bin_stdmac,
  338.     bin_init,
  339.     bin_set_info,
  340.     bin_out,
  341.     bin_deflabel,
  342.     bin_secname,
  343.     bin_segbase,
  344.     bin_directive,
  345.     bin_filename,
  346.     bin_cleanup
  347. };
  348. #endif /* OF_BIN */