📄 outobj.c
字号:
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 0x1Fstatic 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>2fprintf(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 != ':') special++; if (*special == ':') special++; } } } i = segment/2; eb = ebhead; if (!eb) { eb = *ebtail = nasm_malloc(sizeof(*eb)); eb->next = NULL; ebtail = &eb->next; } while (i >= EXT_BLKSIZ) { if (eb && eb->next) eb = eb->next; else { eb = *ebtail = nasm_malloc(sizeof(*eb)); eb->next = NULL; ebtail = &eb->next; } i -= EXT_BLKSIZ; } eb->exts[i] = ext; ext->index = ++externals; if (special && !used_special) error(ERR_NONFATAL, "OBJ supports no special symbol features" " for this symbol type");}/* forward declaration */static void obj_write_fixup (ObjRecord *orp, int bytes, int segrel, long seg, long wrt, struct Segment *segto);static void obj_out (long segto, const void *data, unsigned long type, long segment, long wrt) { unsigned long size, realtype; const unsigned char *ucdata; long ldata; struct Segment *seg; ObjRecord *orp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -