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

编译器/解释器

开发平台:

C/C++

  1. /* outas86.c output routines for the Netwide Assembler to produce
  2.  * Linux as86 (bin86-0.3) object 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_AS86
  17. struct Piece {
  18.     struct Piece *next;
  19.     int type;        /* 0 = absolute, 1 = seg, 2 = sym */
  20.     long offset;        /* relative offset */
  21.     int number;        /* symbol/segment number (4=bss) */
  22.     long bytes;        /* size of reloc or of absolute data */
  23.     int relative;        /* TRUE or FALSE */
  24. };
  25. struct Symbol {
  26.     long strpos;        /* string table position of name */
  27.     int flags;        /* symbol flags */
  28.     int segment;        /* 4=bss at this point */
  29.     long value;        /* address, or COMMON variable size */
  30. };
  31. /*
  32.  * Section IDs - used in Piece.number and Symbol.segment.
  33.  */
  34. #define SECT_TEXT 0        /* text section */
  35. #define SECT_DATA 3        /* data section */
  36. #define SECT_BSS 4        /* bss section */
  37. /*
  38.  * Flags used in Symbol.flags.
  39.  */
  40. #define SYM_ENTRY (1<<8)
  41. #define SYM_EXPORT (1<<7)
  42. #define SYM_IMPORT (1<<6)
  43. #define SYM_ABSOLUTE (1<<4)
  44. struct Section {
  45.     struct SAA *data;
  46.     unsigned long datalen, size, len;
  47.     long index;
  48.     struct Piece *head, *last, **tail;
  49. };
  50. static char as86_module[FILENAME_MAX];
  51. static struct Section stext, sdata;
  52. static unsigned long bsslen;
  53. static long bssindex;
  54. static struct SAA *syms;
  55. static unsigned long nsyms;
  56. static struct RAA *bsym;
  57. static struct SAA *strs;
  58. static unsigned long strslen;
  59. static int as86_reloc_size;
  60. static FILE *as86fp;
  61. static efunc error;
  62. static void as86_write(void);
  63. static void as86_write_section (struct Section *, int);
  64. static int as86_add_string (char *name);
  65. static void as86_sect_write(struct Section *, unsigned char *, unsigned long);
  66. static void as86_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
  67. {
  68.     as86fp = fp;
  69.     error = errfunc;
  70.     (void) ldef;        /* placate optimisers */
  71.     stext.data = saa_init(1L); stext.datalen = 0L;
  72.     stext.head = stext.last = NULL;
  73.     stext.tail = &stext.head;
  74.     sdata.data = saa_init(1L); sdata.datalen = 0L;
  75.     sdata.head = sdata.last = NULL;
  76.     sdata.tail = &sdata.head;
  77.     bsslen =
  78. stext.len = stext.datalen = stext.size =
  79. sdata.len = sdata.datalen = sdata.size = 0;
  80.     stext.index = seg_alloc();
  81.     sdata.index = seg_alloc();
  82.     bssindex = seg_alloc();
  83.     syms = saa_init((long)sizeof(struct Symbol));
  84.     nsyms = 0;
  85.     bsym = raa_init();
  86.     strs = saa_init(1L);
  87.     strslen = 0;
  88.     as86_add_string (as86_module);
  89. }
  90. static void as86_cleanup(int debuginfo) 
  91. {
  92.     struct Piece *p;
  93.     (void) debuginfo;
  94.     as86_write();
  95.     fclose (as86fp);
  96.     saa_free (stext.data);
  97.     while (stext.head) {
  98. p = stext.head;
  99. stext.head = stext.head->next;
  100. nasm_free (p);
  101.     }
  102.     saa_free (sdata.data);
  103.     while (sdata.head) {
  104. p = sdata.head;
  105. sdata.head = sdata.head->next;
  106. nasm_free (p);
  107.     }
  108.     saa_free (syms);
  109.     raa_free (bsym);
  110.     saa_free (strs);
  111. }
  112. static long as86_section_names (char *name, int pass, int *bits) 
  113. {
  114.     /*
  115.      * Default is 16 bits.
  116.      */
  117.     if (!name)
  118. *bits = 16;
  119.     if (!name)
  120. return stext.index;
  121.     if (!strcmp(name, ".text"))
  122. return stext.index;
  123.     else if (!strcmp(name, ".data"))
  124. return sdata.index;
  125.     else if (!strcmp(name, ".bss"))
  126. return bssindex;
  127.     else
  128. return NO_SEG;
  129. }
  130. static int as86_add_string (char *name) 
  131. {
  132.     int pos = strslen;
  133.     int length = strlen(name);
  134.     saa_wbytes (strs, name, (long)(length+1));
  135.     strslen += 1+length;
  136.     return pos;
  137. }
  138. static void as86_deflabel (char *name, long segment, long offset,
  139.    int is_global, char *special) 
  140. {
  141.     struct Symbol *sym;
  142.     if (special)
  143. error (ERR_NONFATAL, "as86 format does not support any"
  144.        " special symbol types");
  145.     if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
  146. error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
  147. return;
  148.     }
  149.     sym = saa_wstruct (syms);
  150.     sym->strpos = as86_add_string (name);
  151.     sym->flags = 0;
  152.     if (segment == NO_SEG)
  153. sym->flags |= SYM_ABSOLUTE, sym->segment = 0;
  154.     else if (segment == stext.index)
  155. sym->segment = SECT_TEXT;
  156.     else if (segment == sdata.index)
  157. sym->segment = SECT_DATA;
  158.     else if (segment == bssindex)
  159. sym->segment = SECT_BSS;
  160.     else {
  161. sym->flags |= SYM_IMPORT;
  162. sym->segment = 15;
  163.     }
  164.     if (is_global == 2)
  165. sym->segment = 3;       /* already have IMPORT */
  166.     if (is_global && !(sym->flags & SYM_IMPORT))
  167. sym->flags |= SYM_EXPORT;
  168.     sym->value = offset;
  169.     /*
  170.      * define the references from external-symbol segment numbers
  171.      * to these symbol records.
  172.      */
  173.     if (segment != NO_SEG && segment != stext.index &&
  174. segment != sdata.index && segment != bssindex)
  175. bsym = raa_write (bsym, segment, nsyms);
  176.     nsyms++;
  177. }
  178. static void as86_add_piece (struct Section *sect, int type, long offset,
  179.     long segment, long bytes, int relative) 
  180. {
  181.     struct Piece *p;
  182.     sect->len += bytes;
  183.     if (type == 0 && sect->last && sect->last->type == 0) {
  184. sect->last->bytes += bytes;
  185. return;
  186.     }
  187.     p = sect->last = *sect->tail = nasm_malloc(sizeof(struct Piece));
  188.     sect->tail = &p->next;
  189.     p->next = NULL;
  190.     p->type = type;
  191.     p->offset = offset;
  192.     p->bytes = bytes;
  193.     p->relative = relative;
  194.     if (type == 1 && segment == stext.index)
  195. p->number = SECT_TEXT;
  196.     else if (type == 1 && segment == sdata.index)
  197. p->number = SECT_DATA;
  198.     else if (type == 1 && segment == bssindex)
  199. p->number = SECT_BSS;
  200.     else if (type == 1)
  201. p->number = raa_read (bsym, segment), p->type = 2;
  202. }
  203. static void as86_out (long segto, void *data, unsigned long type,
  204.       long segment, long wrt) 
  205. {
  206.     struct Section *s;
  207.     long realbytes = type & OUT_SIZMASK;
  208.     long offset;
  209.     unsigned char mydata[4], *p;
  210.     if (wrt != NO_SEG) {
  211. wrt = NO_SEG;        /* continue to do _something_ */
  212. error (ERR_NONFATAL, "WRT not supported by as86 output format");
  213.     }
  214.     type &= OUT_TYPMASK;
  215.     /*
  216.      * handle absolute-assembly (structure definitions)
  217.      */
  218.     if (segto == NO_SEG) {
  219. if (type != OUT_RESERVE)
  220.     error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
  221.    " space");
  222. return;
  223.     }
  224.     if (segto == stext.index)
  225. s = &stext;
  226.     else if (segto == sdata.index)
  227. s = &sdata;
  228.     else if (segto == bssindex)
  229. s = NULL;
  230.     else {
  231. error(ERR_WARNING, "attempt to assemble code in"
  232.       " segment %d: defaulting to `.text'", segto);
  233. s = &stext;
  234.     }
  235.     if (!s && type != OUT_RESERVE) {
  236. error(ERR_WARNING, "attempt to initialise memory in the"
  237.       " BSS section: ignored");
  238. if (type == OUT_REL2ADR)
  239.     realbytes = 2;
  240. else if (type == OUT_REL4ADR)
  241.     realbytes = 4;
  242. bsslen += realbytes;
  243. return;
  244.     }
  245.     if (type == OUT_RESERVE) {
  246. if (s) {
  247.     error(ERR_WARNING, "uninitialised space declared in"
  248.   " %s section: zeroing",
  249.   (segto == stext.index ? "code" : "data"));
  250.     as86_sect_write (s, NULL, realbytes);
  251.     as86_add_piece (s, 0, 0L, 0L, realbytes, 0);
  252. } else
  253.     bsslen += realbytes;
  254.     } else if (type == OUT_RAWDATA) {
  255. if (segment != NO_SEG)
  256.     error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
  257. as86_sect_write (s, data, realbytes);
  258. as86_add_piece (s, 0, 0L, 0L, realbytes, 0);
  259.     } else if (type == OUT_ADDRESS) {
  260. if (segment != NO_SEG) {
  261.     if (segment % 2) {
  262. error(ERR_NONFATAL, "as86 format does not support"
  263.       " segment base references");
  264.     } else{
  265. offset = * (long *) data;
  266. as86_add_piece (s, 1, offset, segment, realbytes, 0);
  267.     }
  268. } else {
  269.     p = mydata;
  270.     WRITELONG (p, * (long *) data);
  271.     as86_sect_write (s, data, realbytes);
  272.     as86_add_piece (s, 0, 0L, 0L, realbytes, 0);
  273. }
  274.     } else if (type == OUT_REL2ADR) {
  275. if (segment == segto)
  276.     error(ERR_PANIC, "intra-segment OUT_REL2ADR");
  277. if (segment != NO_SEG) {
  278.     if (segment % 2) {
  279. error(ERR_NONFATAL, "as86 format does not support"
  280.       " segment base references");
  281.     } else {
  282. offset = * (long *) data;
  283. as86_add_piece (s, 1, offset-realbytes+2, segment, 2L, 1);
  284.     }
  285. }
  286.     } else if (type == OUT_REL4ADR) {
  287. if (segment == segto)
  288.     error(ERR_PANIC, "intra-segment OUT_REL4ADR");
  289. if (segment != NO_SEG) {
  290.     if (segment % 2) {
  291. error(ERR_NONFATAL, "as86 format does not support"
  292.       " segment base references");
  293.     } else {
  294. offset = * (long *) data;
  295. as86_add_piece (s, 1, offset-realbytes+4, segment, 4L, 1);
  296.     }
  297. }
  298.     }
  299. }
  300. static void as86_write(void) 
  301. {
  302.     int i;
  303.     long symlen, seglen, segsize;
  304.     /*
  305.      * First, go through the symbol records working out how big
  306.      * each will be. Also fix up BSS references at this time, and
  307.      * set the flags words up completely.
  308.      */
  309.     symlen = 0;
  310.     saa_rewind (syms);
  311.     for (i = 0; i < nsyms; i++) {
  312. struct Symbol *sym = saa_rstruct (syms);
  313. if (sym->segment == SECT_BSS)
  314.     sym->segment = SECT_DATA, sym->value += sdata.len;
  315. sym->flags |= sym->segment;
  316. if (sym->value == 0)
  317.     sym->flags |= 0 << 14, symlen += 4;
  318. else if (sym->value >= 0 && sym->value <= 255)
  319.     sym->flags |= 1 << 14, symlen += 5;
  320. else if (sym->value >= 0 && sym->value <= 65535L)
  321.     sym->flags |= 2 << 14, symlen += 6;
  322. else
  323.     sym->flags |= 3 << 14, symlen += 8;
  324.     }
  325.     /*
  326.      * Now do the same for the segments, and get the segment size
  327.      * descriptor word at the same time.
  328.      */
  329.     seglen = segsize = 0;
  330.     if ((unsigned long) stext.len > 65535L)
  331. segsize |= 0x03000000L, seglen += 4;
  332.     else
  333. segsize |= 0x02000000L, seglen += 2;
  334.     if ((unsigned long) sdata.len > 65535L)
  335. segsize |= 0xC0000000L, seglen += 4;
  336.     else
  337. segsize |= 0x80000000L, seglen += 2;
  338.     /*
  339.      * Emit the as86 header.
  340.      */
  341.     fwritelong (0x000186A3L, as86fp);
  342.     fputc (0x2A, as86fp);
  343.     fwritelong (27+symlen+seglen+strslen, as86fp);   /* header length */
  344.     fwritelong (stext.len+sdata.len, as86fp);
  345.     fwriteshort (strslen, as86fp);
  346.     fwriteshort (0, as86fp);        /* class = revision = 0 */
  347.     fwritelong (0x55555555L, as86fp);   /* segment max sizes: always this */
  348.     fwritelong (segsize, as86fp);      /* segment size descriptors */
  349.     if (segsize & 0x01000000L)
  350. fwritelong (stext.len, as86fp);
  351.     else
  352. fwriteshort (stext.len, as86fp);
  353.     if (segsize & 0x40000000L)
  354. fwritelong (sdata.len, as86fp);
  355.     else
  356. fwriteshort (sdata.len, as86fp);
  357.     fwriteshort (nsyms, as86fp);
  358.     /*
  359.      * Write the symbol table.
  360.      */
  361.     saa_rewind (syms);
  362.     for (i = 0; i < nsyms; i++) {
  363. struct Symbol *sym = saa_rstruct (syms);
  364. fwriteshort (sym->strpos, as86fp);
  365. fwriteshort (sym->flags, as86fp);
  366. switch (sym->flags & (3<<14)) {
  367.   case 0<<14: break;
  368.   case 1<<14: fputc (sym->value, as86fp); break;
  369.   case 2<<14: fwriteshort (sym->value, as86fp); break;
  370.   case 3<<14: fwritelong (sym->value, as86fp); break;
  371. }
  372.     }
  373.     /*
  374.      * Write out the string table.
  375.      */
  376.     saa_fpwrite (strs, as86fp);
  377.     /*
  378.      * Write the program text.
  379.      */
  380.     as86_reloc_size = -1;
  381.     as86_write_section (&stext, SECT_TEXT);
  382.     as86_write_section (&sdata, SECT_DATA);
  383.     fputc (0, as86fp);        /* termination */
  384. }
  385. static void as86_set_rsize (int size) 
  386. {
  387.     if (as86_reloc_size != size) {
  388. switch (as86_reloc_size = size) {
  389.   case 1: fputc (0x01, as86fp); break;
  390.   case 2: fputc (0x02, as86fp); break;
  391.   case 4: fputc (0x03, as86fp); break;
  392.   default: error (ERR_PANIC, "bizarre relocation size %d", size);
  393. }
  394.     }
  395. }
  396. static void as86_write_section (struct Section *sect, int index) 
  397. {
  398.     struct Piece *p;
  399.     unsigned long s;
  400.     long length;
  401.     fputc (0x20+index, as86fp);        /* select the right section */
  402.     saa_rewind (sect->data);
  403.     for (p = sect->head; p; p = p->next)
  404. switch (p->type) {
  405.   case 0:
  406.     /*
  407.      * Absolute data. Emit it in chunks of at most 64
  408.      * bytes.
  409.      */
  410.     length = p->bytes;
  411.     do {
  412. char buf[64];
  413. long tmplen = (length > 64 ? 64 : length);
  414. fputc (0x40 | (tmplen & 0x3F), as86fp);
  415. saa_rnbytes (sect->data, buf, tmplen);
  416. fwrite (buf, 1, tmplen, as86fp);
  417. length -= tmplen;
  418.     } while (length > 0);
  419.     break;
  420.   case 1:
  421.     /*
  422.      * A segment-type relocation. First fix up the BSS.
  423.      */
  424.     if (p->number == SECT_BSS)
  425. p->number = SECT_DATA, p->offset += sdata.len;
  426.     as86_set_rsize (p->bytes);
  427.     fputc (0x80 | (p->relative ? 0x20 : 0) | p->number, as86fp);
  428.     if (as86_reloc_size == 2)
  429. fwriteshort (p->offset, as86fp);
  430.     else
  431. fwritelong (p->offset, as86fp);
  432.     break;
  433.   case 2:
  434.     /*
  435.      * A symbol-type relocation.
  436.      */
  437.     as86_set_rsize (p->bytes);
  438.     s = p->offset;
  439.     if (s > 65535L)
  440. s = 3;
  441.     else if (s > 255)
  442. s = 2;
  443.     else if (s > 0)
  444. s = 1;
  445.     else
  446. s = 0;
  447.     fputc (0xC0 |
  448.    (p->relative ? 0x20 : 0) |
  449.    (p->number > 255 ? 0x04 : 0) | s, as86fp);
  450.     if (p->number > 255)
  451. fwriteshort (p->number, as86fp);
  452.     else
  453. fputc (p->number, as86fp);
  454.     switch ((int)s) {
  455.       case 0: break;
  456.       case 1: fputc (p->offset, as86fp); break;
  457.       case 2: fwriteshort (p->offset, as86fp); break;
  458.       case 3: fwritelong (p->offset, as86fp); break;
  459.     }
  460.     break;
  461. }
  462. }
  463. static void as86_sect_write (struct Section *sect,
  464.      unsigned char *data, unsigned long len) 
  465. {
  466.     saa_wbytes (sect->data, data, len);
  467.     sect->datalen += len;
  468. }
  469. static long as86_segbase (long segment) 
  470. {
  471.     return segment;
  472. }
  473. static int as86_directive (char *directive, char *value, int pass) 
  474. {
  475.     return 0;
  476. }
  477. static void as86_filename (char *inname, char *outname, efunc error) 
  478. {
  479.     char *p;
  480.     if ( (p = strrchr (inname, '.')) != NULL) {
  481. strncpy (as86_module, inname, p-inname);
  482. as86_module[p-inname] = '';
  483.     } else
  484. strcpy (as86_module, inname);
  485.     standard_extension (inname, outname, ".o", error);
  486. }
  487. static char *as86_stdmac[] = {
  488.     "%define __SECT__ [section .text]",
  489.     "%macro __NASM_CDecl__ 1",
  490.     "%endmacro",
  491.     NULL
  492. };
  493. static int as86_set_info(enum geninfo type, char **val)
  494. {
  495.     return 0;
  496. }
  497. void as86_linenumber (char *name, long segment, long offset, int is_main,
  498.                     int lineno)
  499. {
  500. }
  501. struct ofmt of_as86 = {
  502.     "Linux as86 (bin86 version 0.3) object files",
  503.     "as86",
  504.     NULL,
  505.     null_debug_arr,
  506.     &null_debug_form,
  507.     as86_stdmac,
  508.     as86_init,
  509.     as86_set_info,
  510.     as86_out,
  511.     as86_deflabel, 
  512.     as86_section_names,
  513.     as86_segbase,
  514.     as86_directive,
  515.     as86_filename,
  516.     as86_cleanup
  517. };
  518. #endif /* OF_AS86 */