⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 outrdf2.c

📁 开源的nasm编译器源码,研究编译器原理很有帮且
💻 C
📖 第 1 页 / 共 2 页
字号:
/* outrdf2.c	output routines for the Netwide Assembler to produce *		RDOFF version 2 format object files (which are intended *		mainly for use in proprietary projects, as the code to  *		load and execute them is very simple). They will also be  *		used for device drivers and possibly some executable files *		in the MOSCOW operating system. See Rdoff.txt for *		details. * * The Netwide Assembler is copyright (C) 1996-1998 Simon Tatham and * Julian Hall. All rights reserved. The software is * redistributable under the licence given in the file "Licence" * distributed in the NASM archive. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <assert.h>#include "nasm.h"#include "nasmlib.h"#include "outform.h"/* VERBOSE_WARNINGS: define this to add some extra warnings... */#define VERBOSE_WARNINGS     #ifdef OF_RDF2#define RDF_MAXSEGS 64	/* maximum number of segments - user configurable */typedef unsigned short int16;typedef unsigned char byte;static const char *RDOFF2Id = "RDOFF2";	/* written to start of RDOFF files *//* the records that can be found in the RDOFF header *//* Note that whenever a segment is referred to in the RDOFF file, its number * is always half of the segment number that NASM uses to refer to it; this * is because NASM only allocates even numbered segments, so as to not * waste any of the 16 bits of segment number written to the file - this * allows up to 65533 external labels to be defined; otherwise it would be * 32764. */ #define RDFREC_RELOC		1#define RDFREC_IMPORT		2#define RDFREC_GLOBAL		3#define RDFREC_DLL		4#define RDFREC_BSS		5#define RDFREC_SEGRELOC		6#define RDFREC_FARIMPORT	7#define RDFREC_MODNAME		8#define RDFREC_COMMON		10#define RDFREC_GENERIC		0struct RelocRec {  byte	type;		/* must be 1, or 6 for segment base ref */  byte	reclen;		/* set to 8 */  byte	segment;	/* only 0 for code, or 1 for data supported,			 * but add 64 for relative refs (ie do not require			 * reloc @ loadtime, only linkage) */  long	offset;		/* from start of segment in which reference is loc'd */  byte	length;		/* 1 2 or 4 bytes */  int16	refseg;		/* segment to which reference refers to */};struct ImportRec {  byte 	type;		/* must be 2, or 7 for FAR import */  byte	reclen;		/* equals 3+label length */  int16	segment;	/* segment number allocated to the label for reloc			 * records - label is assumed to be at offset zero			 * in this segment, so linker must fix up with offset			 * of segment and of offset within segment */  char	label[33];	/* zero terminated... should be written to file until			 * the zero, but not after it - max len = 32 chars */};struct ExportRec {  byte	type;		/* must be 3 */  byte  reclen;		/* equals 7+label length */  byte  flags;          /* SYM_* flags (see below) */  byte	segment;	/* segment referred to (0/1) */  long	offset;		/* offset within segment */  char	label[33];	/* zero terminated as above. max len = 32 chars */};struct BSSRec {  byte	type;		/* must be 5 */  byte  reclen;		/* equals 4 */  long	amount;		/* number of bytes BSS to reserve */};struct DLLModRec {  byte type;		/* 4 for DLLRec, 8 for ModRec */  byte reclen;		/* 1+lib name length for DLLRec, 1+mod name length */  char name[128];	/* library to link at load time or module name */};struct CommonRec {  byte	type;		/* must be 10 */  byte  reclen;		/* equals 9+label length */  int16 segment;	/* segment number */  long	size;		/* size of common variable */  int16 align;		/* alignment (power of two) */  char	label[33];	/* zero terminated as above. max len = 32 chars */};/* Flags for ExportRec */#define SYM_DATA	0x01#define SYM_FUNCTION	0x02#define SYM_GLOBAL	0x04#define COUNT_SEGTYPES 9static char * segmenttypes[COUNT_SEGTYPES] = {  "null", "text", "code", "data", "comment", "lcomment", "pcomment",  "symdebug", "linedebug" };static int segmenttypenumbers[COUNT_SEGTYPES] = {  0, 1, 1, 2, 3, 4, 5, 6, 7};/* code for managing buffers needed to seperate code and data into individual * sections until they are ready to be written to the file. * We'd better hope that it all fits in memory else we're buggered... */#define BUF_BLOCK_LEN 4088		/* selected to match page size (4096)                                         * on 80x86 machines for efficiency *//*********************************************************************** * Actual code to deal with RDOFF2 ouput format begins here... *//* global variables set during the initialisation phase */static struct SAA *seg[RDF_MAXSEGS];	/* seg 0 = code, seg 1 = data */static struct SAA *header;	/* relocation/import/export records */static FILE *ofile;static efunc error;static struct seginfo {  char *segname;  int   segnumber;  int16 segtype;  int16 segreserved;  long  seglength;} segments[RDF_MAXSEGS];static int nsegments;static long bsslength;static long headerlength;static void rdf2_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval){  int segtext, segdata, segbss;  /* set up the initial segments */  segments[0].segname = ".text";   segments[0].segnumber = 0;  segments[0].segtype = 1;  segments[0].segreserved = 0;  segments[0].seglength = 0;  segments[1].segname = ".data";  segments[1].segnumber = 1;  segments[1].segtype = 2;  segments[1].segreserved = 0;  segments[1].seglength = 0;  segments[2].segname = ".bss";  segments[2].segnumber = 2;  segments[2].segtype = 0xFFFF;	/* reserved - should never be produced */  segments[2].segreserved = 0;  segments[2].seglength = 0;  nsegments = 3;  ofile = fp;  error = errfunc;  seg[0] = saa_init(1L);  seg[1] = saa_init(1L);  seg[2] = NULL;		/* special case! */  header = saa_init(1L);  segtext = seg_alloc();  segdata = seg_alloc();  segbss = seg_alloc();  if (segtext != 0 || segdata != 2 || segbss != 4)    error(ERR_PANIC,"rdf segment numbers not allocated as expected (%d,%d,%d)",	  segtext,segdata,segbss);  bsslength=0;  headerlength = 0;}static long rdf2_section_names(char *name, int pass, int *bits){  int 	i;  char 	* p, * q;  int	code = -1;  int 	reserved = 0;  /*   * Default is 32 bits, in the text segment.   */  if (!name) {    *bits = 32;    return 0;  }  /* look for segment type code following segment name */  p = name;  while (*p && !isspace(*p)) p++;  if (*p) {	/* we're now in whitespace */    *p++ = '\0';    while (*p && isspace(80)) *p++ = '\0';  }  if (*p) {	/* we're now in an attribute value */    /*     * see if we have an optional ',number' following the type code     */    if ((q = strchr(p, ','))) {      *q++ = '\0';      reserved = readnum(q, &i);      if (i) {	  error(ERR_NONFATAL, "value following comma must be numeric");	  reserved = 0;      }    }    /*     * check it against the text strings in segmenttypes      */    for (i = 0; i < COUNT_SEGTYPES; i++)      if (!nasm_stricmp(p, segmenttypes[i])) {	code = segmenttypenumbers[i];	break;      }    if (code == -1) {	/* didn't find anything */      code = readnum(p, &i);      if (i) {	error(ERR_NONFATAL, "unrecognised RDF segment type (%s)",p);	code = 3;      }    }  }      for (i = 0; i < nsegments; i++) {    if (!strcmp(name, segments[i].segname)) {      if (code != -1 || reserved != 0) 	error(ERR_NONFATAL, "segment attributes specified on"	      " redeclaration of segment");      return segments[i].segnumber * 2;    }  }  /* declaring a new segment! */  if (code == -1) {    error(ERR_NONFATAL, "new segment declared without type code");    code = 3;  }  if (nsegments == RDF_MAXSEGS) {    error(ERR_FATAL, "reached compiled-in maximum segment limit (%d)",	  RDF_MAXSEGS);    return NO_SEG;  }  segments[nsegments].segname = nasm_strdup(name);  i = seg_alloc();  if (i % 2 != 0)    error(ERR_PANIC, "seg_alloc() returned odd number");  segments[nsegments].segnumber = i >> 1;  segments[nsegments].segtype = code;  segments[nsegments].segreserved = reserved;  segments[nsegments].seglength = 0;  seg[nsegments] = saa_init(1L);  return i;}static void write_reloc_rec(struct RelocRec *r){  char buf[4],*b;  if (r->refseg != (int16)NO_SEG && (r->refseg & 1)) /* segment base ref */      r->type = RDFREC_SEGRELOC;  r->refseg >>= 1;    /* adjust segment nos to RDF rather than NASM */  saa_wbytes(header,&r->type,1);  saa_wbytes(header,&r->reclen,1);  saa_wbytes(header,&r->segment,1);  b = buf; WRITELONG(b,r->offset);  saa_wbytes(header,buf,4);  saa_wbytes(header,&r->length,1);  b = buf; WRITESHORT(b,r->refseg);  saa_wbytes(header,buf,2);  headerlength += r->reclen + 2;}static void write_export_rec(struct ExportRec *r){  char buf[4], *b;  r->segment >>= 1;  saa_wbytes(header,&r->type,1);  saa_wbytes(header,&r->reclen,1);  saa_wbytes(header,&r->flags,1);  saa_wbytes(header,&r->segment,1);  b = buf; WRITELONG(b,r->offset);  saa_wbytes(header,buf,4);  saa_wbytes(header,r->label,strlen(r->label) + 1);  headerlength += r->reclen + 2;}static void write_import_rec(struct ImportRec *r){  char buf[4], *b;  r->segment >>= 1;  saa_wbytes(header,&r->type,1);  saa_wbytes(header,&r->reclen,1);  b = buf; WRITESHORT(b,r->segment);  saa_wbytes(header,buf,2);  saa_wbytes(header,r->label,strlen(r->label) + 1);  headerlength += r->reclen + 2;}static void write_bss_rec(struct BSSRec *r){    char buf[4], *b;    saa_wbytes(header,&r->type,1);    saa_wbytes(header,&r->reclen,1);    b = buf; WRITELONG(b,r->amount);    saa_wbytes(header,buf,4);    headerlength += r->reclen + 2;}/* * Write common variable record. */static void write_common_rec(struct CommonRec *r){  char buf[4], *b;  r->segment >>= 1;  saa_wbytes(header,&r->type,1);  saa_wbytes(header,&r->reclen,1);  b = buf; WRITESHORT(b,r->segment);  saa_wbytes(header,buf,2);  b = buf; WRITELONG(b,r->size);  saa_wbytes(header,buf,4);  b = buf; WRITESHORT(b,r->align);  saa_wbytes(header,buf,2);  saa_wbytes(header,r->label,strlen(r->label) + 1);  headerlength += r->reclen + 2;}/* * Write library record. Also used for module name records. */static void write_dllmod_rec(struct DLLModRec *r){    saa_wbytes(header,&r->type,1);    saa_wbytes(header,&r->reclen,1);    saa_wbytes(header,r->name,strlen(r->name) + 1);    headerlength += r->reclen + 2;}static void rdf2_deflabel(char *name, long segment, long offset,			 int is_global, char *special){  struct ExportRec r;  struct ImportRec ri;  struct CommonRec ci;  static int farsym = 0;  static int i;  byte export_flags = 0;  if (is_global == 2) {    /* Common variable */    ci.type = RDFREC_COMMON;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -