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

📄 outobj.c

📁 一个免费的汇编语言编译器的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:

struct LineNumber {
    struct LineNumber *next;
    struct Segment *segment;
    long offset;
    long lineno;
};

static struct FileName {
    struct FileName *next;
    char *name;
    struct LineNumber *lnhead, **lntail;
    int index;
} *fnhead, **fntail;

static struct Array {
    struct Array *next;
    unsigned size;
    int basetype;
} *arrhead, **arrtail;

#define ARRAYBOT 31 /* magic number  for first array index */


static struct Public {
    struct Public *next;
    char *name;
    long offset;
    long segment;		       /* only if it's far-absolute */
    int type;                          /* only for local debug syms */
} *fpubhead, **fpubtail, *last_defined;

static struct External {
    struct External *next;
    char *name;
    long commonsize;
    long commonelem;		       /* element size if FAR, else zero */
    int index;			       /* OBJ-file external index */
    enum {
	DEFWRT_NONE,		       /* no unusual default-WRT */
	DEFWRT_STRING,		       /* a string we don't yet understand */
	DEFWRT_SEGMENT,		       /* a segment */
	DEFWRT_GROUP		       /* a group */
    } defwrt_type;
    union {
	char *string;
	struct Segment *seg;
	struct Group *grp;
    } defwrt_ptr;
    struct External *next_dws;	       /* next with DEFWRT_STRING */
} *exthead, **exttail, *dws;

static int externals;

static struct ExtBack {
    struct ExtBack *next;
    struct External *exts[EXT_BLKSIZ];
} *ebhead, **ebtail;

static struct Segment {
    struct Segment *next;
    long index;			       /* the NASM segment id */
    long obj_index;		       /* the OBJ-file segment index */
    struct Group *grp;		       /* the group it belongs to */
    unsigned long currentpos;
    long align;			       /* can be SEG_ABS + absolute addr */
    enum {
	CMB_PRIVATE = 0,
	CMB_PUBLIC = 2,
	CMB_STACK = 5,
	CMB_COMMON = 6
    } combine;
    long use32;			       /* is this segment 32-bit? */
    struct Public *pubhead, **pubtail, *lochead, **loctail;
    char *name;
    char *segclass, *overlay;	       /* `class' is a C++ keyword :-) */
    ObjRecord *orp;
} *seghead, **segtail, *obj_seg_needs_update;

static struct Group {
    struct Group *next;
    char *name;
    long index;			       /* NASM segment id */
    long obj_index;		       /* OBJ-file group index */
    long nentries;		       /* number of elements... */
    long nindices;		       /* ...and number of index elts... */
    union {
	long index;
	char *name;
    } segs[GROUP_MAX];		       /* ...in this */
} *grphead, **grptail, *obj_grp_needs_update;

static struct ImpDef {
    struct ImpDef *next;
    char *extname;
    char *libname;
    unsigned int impindex;
    char *impname;
} *imphead, **imptail;

static struct ExpDef {
    struct ExpDef *next;
    char *intname;
    char *extname;
    unsigned int ordinal;
    int flags;
} *exphead, **exptail;

#define EXPDEF_FLAG_ORDINAL  0x80
#define EXPDEF_FLAG_RESIDENT 0x40
#define EXPDEF_FLAG_NODATA   0x20
#define EXPDEF_MASK_PARMCNT  0x1F

static long obj_entry_seg, obj_entry_ofs;

struct ofmt of_obj;

/* The current segment */
static struct Segment *current_seg;

static long obj_segment (char *, int, int *);
static void obj_write_file(int debuginfo);
static int obj_directive (char *, char *, int);

static void obj_init (FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
{
    ofp = fp;
    error = errfunc;
    evaluate = eval;
    deflabel = ldef;
    first_seg = seg_alloc();
    any_segs = FALSE;
    fpubhead = NULL;
    fpubtail = &fpubhead;
    exthead = NULL;
    exttail = &exthead;
    imphead = NULL;
    imptail = &imphead;
    exphead = NULL;
    exptail = &exphead;
    dws = NULL;
    externals = 0;
    ebhead = NULL;
    ebtail = &ebhead;
    seghead = obj_seg_needs_update = NULL;
    segtail = &seghead;
    grphead = obj_grp_needs_update = NULL;
    grptail = &grphead;
    obj_entry_seg = NO_SEG;
    obj_uppercase = FALSE;
    obj_use32 = FALSE;
    passtwo = 0;
    current_seg = NULL;

    of_obj.current_dfmt->init (&of_obj,NULL,fp,errfunc);
}

static int obj_set_info(enum geninfo type, char **val)
{
    (void) type;
    (void) val;

    return 0;
}
static void obj_cleanup (int debuginfo) 
{
    obj_write_file(debuginfo);
    of_obj.current_dfmt->cleanup();
    fclose (ofp);
    while (seghead) {
	struct Segment *segtmp = seghead;
	seghead = seghead->next;
	while (segtmp->pubhead) {
	    struct Public *pubtmp = segtmp->pubhead;
	    segtmp->pubhead = pubtmp->next;
	    nasm_free (pubtmp->name);
	    nasm_free (pubtmp);
	}
	nasm_free (segtmp->segclass);
	nasm_free (segtmp->overlay);
	nasm_free (segtmp);
    }
    while (fpubhead) {
	struct Public *pubtmp = fpubhead;
	fpubhead = fpubhead->next;
	nasm_free (pubtmp->name);
	nasm_free (pubtmp);
    }
    while (exthead) {
	struct External *exttmp = exthead;
	exthead = exthead->next;
	nasm_free (exttmp);
    }
    while (imphead) {
	struct ImpDef *imptmp = imphead;
	imphead = imphead->next;
	nasm_free (imptmp->extname);
	nasm_free (imptmp->libname);
	nasm_free (imptmp->impname);   /* nasm_free won't mind if it's NULL */
	nasm_free (imptmp);
    }
    while (exphead) {
	struct ExpDef *exptmp = exphead;
	exphead = exphead->next;
	nasm_free (exptmp->extname);
	nasm_free (exptmp->intname);
	nasm_free (exptmp);
    }
    while (ebhead) {
	struct ExtBack *ebtmp = ebhead;
	ebhead = ebhead->next;
	nasm_free (ebtmp);
    }
    while (grphead) {
	struct Group *grptmp = grphead;
	grphead = grphead->next;
	nasm_free (grptmp);
    }
}

static void obj_ext_set_defwrt (struct External *ext, char *id) 
{
    struct Segment *seg;
    struct Group *grp;

    for (seg = seghead; seg; seg = seg->next)
	if (!strcmp(seg->name, id)) {
	    ext->defwrt_type = DEFWRT_SEGMENT;
	    ext->defwrt_ptr.seg = seg;
	    nasm_free (id);
	    return;
	}

    for (grp = grphead; grp; grp = grp->next)
	if (!strcmp(grp->name, id)) {
	    ext->defwrt_type = DEFWRT_GROUP;
	    ext->defwrt_ptr.grp = grp;
	    nasm_free (id);
	    return;
	}

    ext->defwrt_type = DEFWRT_STRING;
    ext->defwrt_ptr.string = id;
    ext->next_dws = dws;
    dws = ext;
}

static void obj_deflabel (char *name, long segment,
			  long offset, int is_global, char *special) 
{
    /*
     * We have three cases:
     *
     * (i) `segment' is a segment-base. If so, set the name field
     * for the segment or group structure it refers to, and then
     * return.
     *
     * (ii) `segment' is one of our segments, or a SEG_ABS segment.
     * Save the label position for later output of a PUBDEF record.
     * (Or a MODPUB, if we work out how.)
     *
     * (iii) `segment' is not one of our segments. Save the label
     * position for later output of an EXTDEF, and also store a
     * back-reference so that we can map later references to this
     * segment number to the external index.
     */
    struct External *ext;
    struct ExtBack *eb;
    struct Segment *seg;
    int i;
    int used_special = FALSE;	       /* have we used the special text? */

#if defined(DEBUG) && DEBUG>2
fprintf(stderr, " obj_deflabel: %s, seg=%ld, off=%ld, is_global=%d, %s\n",
      name, segment, offset, is_global, special);
#endif

    /*
     * If it's a special-retry from pass two, discard it.
     */
    if (is_global == 3)
	return;

    /*
     * First check for the double-period, signifying something
     * unusual.
     */
    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
	if (!strcmp(name, "..start")) {
	    obj_entry_seg = segment;
	    obj_entry_ofs = offset;
	    return;
	}
	error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
    }

    /*
     * Case (i):
     */
    if (obj_seg_needs_update) {
	obj_seg_needs_update->name = name;
	return;
    } else if (obj_grp_needs_update) {
	obj_grp_needs_update->name = name;
	return;
    }
    if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
	return;

    if (segment >= SEG_ABS || segment == NO_SEG) {
	/*
	 * SEG_ABS subcase of (ii).
	 */
	if (is_global) {
	    struct Public *pub;

	    pub = *fpubtail = nasm_malloc(sizeof(*pub));
	    fpubtail = &pub->next;
	    pub->next = NULL;
	    pub->name = nasm_strdup(name);
	    pub->offset = offset;
	    pub->segment = (segment == NO_SEG ? 0 : segment & ~SEG_ABS);
	}
	if (special)
	    error(ERR_NONFATAL, "OBJ supports no special symbol features"
		  " for this symbol type");
	return;
    }

    /*
     * If `any_segs' is still FALSE, we might need to define a
     * default segment, if they're trying to declare a label in
     * `first_seg'.
     */
    if (!any_segs && segment == first_seg) {
	int tempint;		       /* ignored */
	if (segment != obj_segment("__NASMDEFSEG", 2, &tempint))
	    error (ERR_PANIC, "strange segment conditions in OBJ driver");
    }

    for (seg = seghead; seg && is_global; seg = seg->next)
	if (seg->index == segment) {
	    struct Public *loc = nasm_malloc (sizeof(*loc));
	    /*
	     * Case (ii). Maybe MODPUB someday?
	     */
	    *seg->pubtail = loc;
	    seg->pubtail = &loc->next;
	    loc->next = NULL;
	    loc->name = nasm_strdup(name);
	    loc->offset = offset;
                  
	    if (special)
		error(ERR_NONFATAL, "OBJ supports no special symbol features"
		      " for this symbol type");
	    return;
	}

    /*
     * Case (iii).
     */
    if (is_global) {
        ext = *exttail = nasm_malloc(sizeof(*ext));
        ext->next = NULL;
        exttail = &ext->next;
        ext->name = name;
	/* Place by default all externs into the current segment */
        ext->defwrt_type = DEFWRT_NONE;

/* 28-Apr-2002 - John Coffman
  The following code was introduced on 12-Aug-2000, and breaks fixups
  on code passed thru the MSC 5.1 linker (3.66) and MSC 6.00A linker
  (5.10).  It was introduced after FIXUP32 was added, and may be needed
  for 32-bit segments.  The following will get 16-bit segments working
  again, and maybe someone can correct the 'if' condition which is
  actually needed.
*/
#if 0
	if (current_seg) {
#else
	if (current_seg && current_seg->use32) {
	    if (current_seg->grp) {
		ext->defwrt_type = DEFWRT_GROUP;
		ext->defwrt_ptr.grp = current_seg->grp;
	    } else {
		ext->defwrt_type = DEFWRT_SEGMENT;
		ext->defwrt_ptr.seg = current_seg;
	    }
	}
#endif

        if (is_global == 2) {
	    ext->commonsize = offset;
	    ext->commonelem = 1;	       /* default FAR */
        } else
	    ext->commonsize = 0;
    }
    else
	return;

    /*
     * Now process the special text, if any, to find default-WRT
     * specifications and common-variable element-size and near/far
     * specifications.
     */
    while (special && *special) {
	used_special = TRUE;

	/*
	 * We might have a default-WRT specification.
	 */
	if (!nasm_strnicmp(special, "wrt", 3)) {
	    char *p;
	    int len;
	    special += 3;
	    special += strspn(special, " \t");
	    p = nasm_strndup(special, len = strcspn(special, ":"));
	    obj_ext_set_defwrt (ext, p);
	    special += len;
	    if (*special && *special != ':')
		error(ERR_NONFATAL, "`:' expected in special symbol"
		      " text for `%s'", ext->name);
	    else if (*special == ':')
		special++;
	}

	/*
	 * The NEAR or FAR keywords specify nearness or
	 * farness. FAR gives default element size 1.
	 */
	if (!nasm_strnicmp(special, "far", 3)) {
	    if (ext->commonsize)
		ext->commonelem = 1;
	    else
		error(ERR_NONFATAL, "`%s': `far' keyword may only be applied"
		      " to common variables\n", ext->name);
	    special += 3;
	    special += strspn(special, " \t");
	} else if (!nasm_strnicmp(special, "near", 4)) {
	    if (ext->commonsize)
		ext->commonelem = 0;
	    else
		error(ERR_NONFATAL, "`%s': `far' keyword may only be applied"
		      " to common variables\n", ext->name);
	    special += 4;
	    special += strspn(special, " \t");
	}

	/*
	 * If it's a common, and anything else remains on the line
	 * before a further colon, evaluate it as an expression and
	 * use that as the element size. Forward references aren't
	 * allowed.
	 */
	if (*special == ':')
	    special++;
	else if (*special) {
	    if (ext->commonsize) {
		expr *e;
		struct tokenval tokval;

		stdscan_reset();
		stdscan_bufptr = special;
		tokval.t_type = TOKEN_INVALID;
		e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
		if (e) {
		    if (!is_simple(e))
			error (ERR_NONFATAL, "cannot use relocatable"
			       " expression as common-variable element size");
		    else
			ext->commonelem = reloc_value(e);
		}
		special = stdscan_bufptr;
	    } else {
		error (ERR_NONFATAL, "`%s': element-size specifications only"
		       " apply to common variables", ext->name);
		while (*special && *special != ':')

⌨️ 快捷键说明

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