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

📄 outobj.c

📁 开源的nasm编译器源码,研究编译器原理很有帮且
💻 C
📖 第 1 页 / 共 5 页
字号:
    }}static int obj_directive (char *directive, char *value, int pass) {    if (!strcmp(directive, "group")) {	char *p, *q, *v;	if (pass == 1) {	    struct Group *grp;	    struct Segment *seg;	    struct External **extp;	    int obj_idx;	    q = value;	    while (*q == '.')		q++;		       /* hack, but a documented one */	    v = q;	    while (*q && !isspace(*q))		q++;	    if (isspace(*q)) {		*q++ = '\0';		while (*q && isspace(*q))		    q++;	    }	    /*	     * Here we used to sanity-check the group directive to	     * ensure nobody tried to declare a group containing no	     * segments. However, OS/2 does this as standard	     * practice, so the sanity check has been removed.	     *	     * if (!*q) {	     *     error(ERR_NONFATAL,"GROUP directive contains no segments");	     *     return 1;	     * }	     */	    obj_idx = 1;	    for (grp = grphead; grp; grp = grp->next) {		obj_idx++;		if (!strcmp(grp->name, v)) {		    error(ERR_NONFATAL, "group `%s' defined twice", v);		    return 1;		}	    }	    *grptail = grp = nasm_malloc(sizeof(*grp));	    grp->next = NULL;	    grptail = &grp->next;	    grp->index = seg_alloc();	    grp->obj_index = obj_idx;	    grp->nindices = grp->nentries = 0;	    grp->name = NULL;	    obj_grp_needs_update = grp;	    deflabel (v, grp->index+1, 0L,		      NULL, FALSE, FALSE, &of_obj, error);	    obj_grp_needs_update = NULL;	    while (*q) {		p = q;		while (*q && !isspace(*q))		    q++;		if (isspace(*q)) {		    *q++ = '\0';		    while (*q && isspace(*q))			q++;		}		/*		 * Now p contains a segment name. Find it.		 */		for (seg = seghead; seg; seg = seg->next)		    if (!strcmp(seg->name, p))			break;		if (seg) {		    /*		     * We have a segment index. Shift a name entry		     * to the end of the array to make room.		     */		    grp->segs[grp->nentries++] = grp->segs[grp->nindices];		    grp->segs[grp->nindices++].index = seg->obj_index;		    if (seg->grp)			error(ERR_WARNING, "segment `%s' is already part of"			      " a group: first one takes precedence",			      seg->name);		    else			seg->grp = grp;		} else {		    /*		     * We have an as-yet undefined segment.		     * Remember its name, for later.		     */		    grp->segs[grp->nentries++].name = nasm_strdup(p);		}	    }	    /*	     * Walk through the list of externals with unresolved	     * default-WRT clauses, and resolve any that point at	     * this group.	     */	    extp = &dws;	    while (*extp) {		if ((*extp)->defwrt_type == DEFWRT_STRING &&		    !strcmp((*extp)->defwrt_ptr.string, grp->name)) {		    nasm_free((*extp)->defwrt_ptr.string);		    (*extp)->defwrt_type = DEFWRT_GROUP;		    (*extp)->defwrt_ptr.grp = grp;		    *extp = (*extp)->next_dws;	    } else		    extp = &(*extp)->next_dws;	    }	}	return 1;    }    if (!strcmp(directive, "uppercase")) {	obj_uppercase = TRUE;	return 1;    }    if (!strcmp(directive, "import")) {	char *q, *extname, *libname, *impname;	if (pass == 2)	    return 1;		       /* ignore in pass two */	extname = q = value;	while (*q && !isspace(*q))	    q++;	if (isspace(*q)) {	    *q++ = '\0';	    while (*q && isspace(*q))		q++;	}	libname = q;	while (*q && !isspace(*q))	    q++;	if (isspace(*q)) {	    *q++ = '\0';	    while (*q && isspace(*q))		q++;	}	impname = q;	if (!*extname || !*libname)	    error(ERR_NONFATAL, "`import' directive requires symbol name"		  " and library name");	else {	    struct ImpDef *imp;	    int err = FALSE;	    imp = *imptail = nasm_malloc(sizeof(struct ImpDef));	    imptail = &imp->next;	    imp->next = NULL;	    imp->extname = nasm_strdup(extname);	    imp->libname = nasm_strdup(libname);	    imp->impindex = readnum(impname, &err);	    if (!*impname || err)		imp->impname = nasm_strdup(impname);	    else		imp->impname = NULL;	}	return 1;    }    if (!strcmp(directive, "export")) {	char *q, *extname, *intname, *v;	struct ExpDef *export;	int flags = 0;	unsigned int ordinal = 0;	if (pass == 2)	    return 1;		       /* ignore in pass two */	intname = q = value;	while (*q && !isspace(*q))	    q++;	if (isspace(*q)) {	    *q++ = '\0';	    while (*q && isspace(*q))		q++;	}	extname = q;	while (*q && !isspace(*q))	    q++;	if (isspace(*q)) {	    *q++ = '\0';	    while (*q && isspace(*q))		q++;	}	if (!*intname) {	    error(ERR_NONFATAL, "`export' directive requires export name");	    return 1;	}	if (!*extname) {	    extname = intname;	    intname = "";	}	while (*q) {	    v = q;	    while (*q && !isspace(*q))		q++;	    if (isspace(*q)) {		*q++ = '\0';		while (*q && isspace(*q))		    q++;	    }	    if (!nasm_stricmp(v, "resident"))		flags |= EXPDEF_FLAG_RESIDENT;	    else if (!nasm_stricmp(v, "nodata"))		flags |= EXPDEF_FLAG_NODATA;	    else if (!nasm_strnicmp(v, "parm=", 5)) {		int err = FALSE;		flags |= EXPDEF_MASK_PARMCNT & readnum(v+5, &err);		if (err) {		    error(ERR_NONFATAL,			  "value `%s' for `parm' is non-numeric", v+5);		    return 1;		}	    } else {		int err = FALSE;		ordinal = readnum(v, &err);		if (err) {		    error(ERR_NONFATAL, "unrecognised export qualifier `%s'",			  v);		    return 1;		}		flags |= EXPDEF_FLAG_ORDINAL;	    }	}	export = *exptail = nasm_malloc(sizeof(struct ExpDef));	exptail = &export->next;	export->next = NULL;	export->extname = nasm_strdup(extname);	export->intname = nasm_strdup(intname);	export->ordinal = ordinal;	export->flags = flags;	return 1;    }    return 0;}static long obj_segbase (long segment) {    struct Segment *seg;    /*     * Find the segment in our list.     */    for (seg = seghead; seg; seg = seg->next)	if (seg->index == segment-1)	    break;    if (!seg) {	/*	 * Might be an external with a default WRT.	 */	long i = segment/2;	struct ExtBack *eb = ebhead;	struct External *e;	while (i > EXT_BLKSIZ) {	    if (eb)		eb = eb->next;	    else		break;	    i -= EXT_BLKSIZ;	}	if (eb) {	    e = eb->exts[i];	    if (e->defwrt_type == DEFWRT_NONE)		return segment;	       /* fine */	    else if (e->defwrt_type == DEFWRT_SEGMENT)		return e->defwrt_ptr.seg->index+1;	    else if (e->defwrt_type == DEFWRT_GROUP)		return e->defwrt_ptr.grp->index+1;	    else		return NO_SEG;	       /* can't tell what it is */	}	return segment;		       /* not one of ours - leave it alone */    }    if (seg->align >= SEG_ABS)	return seg->align;	       /* absolute segment */    if (seg->grp)	return seg->grp->index+1;      /* grouped segment */    return segment;		       /* no special treatment */}static void obj_filename (char *inname, char *outname, efunc lerror) {    strcpy(obj_infile, inname);    standard_extension (inname, outname, ".obj", lerror);}static void obj_write_file (int debuginfo) {    struct Segment *seg, *entry_seg_ptr = 0;    struct FileName *fn;    struct LineNumber *ln;    struct Group *grp;    struct Public *pub, *loc;    struct External *ext;    struct ImpDef *imp;    struct ExpDef *export;    static char boast[] = "The Netwide Assembler " NASM_VER;    int lname_idx;    ObjRecord *orp;    /*     * Write the THEADR module header.     */    orp = obj_new();    orp->type = THEADR;    obj_name (orp, obj_infile);    obj_emit2 (orp);    /*     * Write the NASM boast comment.     */    orp->type = COMENT;    obj_rword (orp, 0);   /* comment type zero */    obj_name (orp, boast);    obj_emit2 (orp);    orp->type = COMENT;    /*     * Write the IMPDEF records, if any.     */    for (imp = imphead; imp; imp = imp->next) {	obj_rword (orp, 0xA0);   /* comment class A0 */	obj_byte (orp, 1);   /* subfunction 1: IMPDEF */	if (imp->impname)	    obj_byte (orp, 0);   /* import by name */	else	    obj_byte (orp, 1);   /* import by ordinal */	obj_name (orp, imp->extname);	obj_name (orp, imp->libname);	if (imp->impname)	    obj_name (orp, imp->impname);	else	    obj_word (orp, imp->impindex);	obj_emit2 (orp);    }    /*     * Write the EXPDEF records, if any.     */    for (export = exphead; export; export = export->next) {	obj_rword (orp, 0xA0);   /* comment class A0 */	obj_byte (orp, 2);   /* subfunction 2: EXPDEF */	obj_byte (orp, export->flags);	obj_name (orp, export->extname);	obj_name (orp, export->intname);	if (export->flags & EXPDEF_FLAG_ORDINAL)	    obj_word (orp, export->ordinal);	obj_emit2 (orp);    }    /* we're using extended OMF if we put in debug info*/    if (debuginfo) {      orp->type = COMENT;      obj_byte (orp, 0x40);      obj_byte (orp, dEXTENDED);      obj_emit2 (orp);    }    /*     * Write the first LNAMES record, containing LNAME one, which     * is null. Also initialise the LNAME counter.     */    orp->type = LNAMES;    obj_byte (orp, 0);    lname_idx = 1;    /*     * Write some LNAMES for the segment names     */    for (seg = seghead; seg; seg = seg->next) {	orp = obj_name (orp, seg->name);	if (seg->segclass)	    orp = obj_name (orp, seg->segclass);	if (seg->overlay)	    orp = obj_name (orp, seg->overlay);	obj_commit (orp);    }    /*     * Write some LNAMES for the group names     */    for (grp = grphead; grp; grp = grp->next) {	orp = obj_name (orp, grp->name);	obj_commit (orp);    }    obj_emit (orp);    /*     * Write the SEGDEF records.     */    orp->type = SEGDEF;    for (seg = seghead; seg; seg = seg->next) {	int acbp;	unsigned long seglen = seg->currentpos;	acbp = (seg->combine << 2);    /* C field */	if (seg->use32)	    acbp |= 0x01;	       /* P bit is Use32 flag */	else if (seglen == 0x10000L) {	    seglen = 0;                /* This special case may be needed for old linkers */	    acbp |= 0x02;	       /* B bit */	}	/* A field */	if (seg->align >= SEG_ABS)	    /* acbp |= 0x00 */;	else if (seg->align >= 4096) {	    if (seg->align > 4096)		error(ERR_NONFATAL, "segment `%s' requires more alignment"		      " than OBJ format supports", seg->name);	    acbp |= 0xC0;	       /* PharLap extension */	} else if (seg->align >= 256) {	    acbp |= 0x80;	} else if (seg->align >= 16) {	    acbp |= 0x60;	} else if (seg->align >= 4) {	    acbp |= 0xA0;	} else if (seg->align >= 2) {	    acbp |= 0x40;	} else	    acbp |= 0x20;	obj_byte (orp, acbp);	if (seg->align & SEG_ABS) {	    obj_x (orp, seg->align - SEG_ABS);  /* Frame */	    obj_byte (orp, 0);  /* Offset */	}	obj_x (orp, seglen);	obj_index (orp, ++lname_idx);	obj_index (orp, seg->segclass ? ++lname_idx : 1);	obj_index (orp, seg->overlay ? ++lname_idx : 1);	obj_emit2 (orp);    }    /*     * Write the GRPDEF records.     */    orp->type = GRPDEF;    for (grp = grphead; grp; grp = grp->next) {	int i;	if (grp->nindices != grp->nentries) {	    for (i = grp->nindices; i < grp->nentries; i++) {		error(ERR_NONFATAL, "group `%s' contains undefined segment"		      " `%s'", grp->name, grp->segs[i].name);		nasm_free (grp->segs[i].name);		grp->segs[i].name = NULL;	    }	}	obj_index (orp, ++lname_idx);	for (i = 0; i < grp->nindices; i++) {	    obj_byte (orp, 0xFF);	    obj_index (orp, grp->segs[i].index);	}	obj_emit2 (orp);    }    /*     * Write the PUBDEF records: first the ones in the segments,     * then the far-absolutes.     */    orp->type = PUBDEF;    orp->ori = ori_pubdef;    for (seg = seghead; seg; seg = seg->next) {	orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;	orp->parm[1] = seg->obj_index;	for (pub = seg->pubhead; pub; pub = pub->next) {	    orp = obj_name (orp, pub->name);	    orp = obj_x (orp, pub->offset);	    orp = obj_byte (orp, 0);  /* type index */	    obj_commit (orp);	}	obj_emit (orp);    }    orp->parm[0] = 0;    orp->parm[1] = 0;    for (pub = fpubhead; pub; pub = pub->next) {   /* pub-crawl :-) */	if (orp->parm[2] != pub->segment) {	    obj_emit (orp);	    orp->parm[2] = pub->segment;	}	orp = obj_name (orp, pub->name);	orp = obj_x (orp, pub->offset);	orp = obj_byte (orp, 0);  /* type index */	obj_commit (orp);

⌨️ 快捷键说明

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