📄 outobj.c
字号:
}}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 + -