📄 outobj.c
字号:
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);
/* DAL start */
if (debuginfo && dbg_type == dbg_ls) {
for (fn = fnhead; fn; fn = fn->next) {
/* write out depslist file name */
orp->type = COMENT;
orp->ori = ori_null;
obj_byte (orp, 0x40);
obj_byte (orp, dDEPNAME);
obj_filetime(orp, fn->name);
obj_name( orp,fn->name);
obj_emit2 (orp);
}
}
/* DAL end */
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) {
if (seg->combine != CMB_BORLANDVIRTUAL) { /* DAL */
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) {
if (seg->combine != CMB_BORLANDVIRTUAL) { /* DAL */
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) {
if (seg->combine != CMB_BORLANDVIRTUAL) {
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);
}
obj_emit (orp);
/*
* Write the EXTDEF and COMDEF records, in order.
*/
orp->ori = ori_null;
for (ext = exthead; ext; ext = ext->next) {
if (ext->commonsize == 0 && !ext->virtual_parent_obj_index) { /* DAL */
if (orp->type != EXTDEF) {
obj_emit (orp);
orp->type = EXTDEF;
}
orp = obj_name (orp, ext->name);
orp = obj_index (orp, 0);
} else {
if (orp->type != COMDEF) {
obj_emit (orp);
orp->type = COMDEF;
}
orp = obj_name (orp, ext->name);
orp = obj_index (orp, 0);
/* DAL */
if (ext->virtual_parent_obj_index) {
int i = 1 ;
for (seg = seghead; seg; seg = seg->next, i++)
if (seg->combine != CMB_BORLANDVIRTUAL)
if (i == ext->virtual_parent_obj_index)
break ;
orp= obj_byte(orp, seg->obj_index) ;
orp = obj_value(orp, ext->defwrt_ptr.seg->currentpos) ;
} else {
/* END DAL */
if (ext->commonelem) {
orp = obj_byte (orp, 0x61);/* far communal */
orp = obj_value (orp, (ext->commonsize / ext->commonelem));
orp = obj_value (orp, ext->commonelem);
} else {
orp = obj_byte (orp, 0x62);/* near communal */
orp = obj_value (orp, ext->commonsize);
}
}
}
obj_commit (orp);
}
obj_emit (orp);
/*
* Write a COMENT record stating that the linker's first pass
* may stop processing at this point. Exception is if our
* MODEND record specifies a start point, in which case,
* according to some variants of the documentation, this COMENT
* should be omitted. So we'll omit it just in case.
* But, TASM puts it in all the time so if we are using
* TASM debug stuff we are putting it in
*/
if (debuginfo || obj_entry_seg == NO_SEG) {
orp->type = COMENT;
obj_byte (orp, 0x40);
obj_byte (orp, dLINKPASS);
obj_byte (orp, 1);
obj_emit2 (orp);
}
/*
* 1) put out the compiler type
* 2) Put out the type info. The only type we are using is near label #19
*/
if (debuginfo && dbg_type == dbg_bi) { /* DAL */
int i;
struct Array *arrtmp = arrhead;
orp->type = COMENT;
obj_byte (orp, 0x40);
obj_byte (orp, dCOMPDEF);
obj_byte (orp, 4);
obj_byte (orp, 0);
obj_emit2 (orp);
obj_byte (orp, 0x40);
obj_byte (orp, dTYPEDEF);
obj_word (orp, 0x18); /* type # for linking */
obj_word (orp, 6); /* size of type */
obj_byte (orp, 0x2a); /* absolute type for debugging */
obj_emit2 (orp);
obj_byte (orp, 0x40);
obj_byte (orp, dTYPEDEF);
obj_word (orp, 0x19); /* type # for linking */
obj_word (orp, 0); /* size of type */
obj_byte (orp, 0x24); /* absolute type for debugging */
obj_byte (orp, 0); /* near/far specifier */
obj_emit2 (orp);
obj_byte (orp, 0x40);
obj_byte (orp, dTYPEDEF);
obj_word (orp, 0x1A); /* type # for linking */
obj_word (orp, 0); /* size of type */
obj_byte (orp, 0x24); /* absolute type for debugging */
obj_byte (orp, 1); /* near/far specifier */
obj_emit2 (orp);
obj_byte (orp, 0x40);
obj_byte (orp, dTYPEDEF);
obj_word (orp, 0x1b); /* type # for linking */
obj_word (orp, 0); /* size of type */
obj_byte (orp, 0x23); /* absolute type for debugging */
obj_byte (orp, 0);
obj_byte (orp, 0);
obj_byte (orp, 0);
obj_emit2 (orp);
obj_byte (orp, 0x40);
obj_byte (orp, dTYPEDEF);
obj_word (orp, 0x1c); /* type # for linking */
obj_word (orp, 0); /* size of type */
obj_byte (orp, 0x23); /* absolute type for debugging */
obj_byte (orp, 0);
obj_byte (orp, 4);
obj_byte (orp, 0);
obj_emit2 (orp);
obj_byte (orp, 0x40);
obj_byte (orp, dTYPEDEF);
obj_word (orp, 0x1d); /* type # for linking */
obj_word (orp, 0); /* size of type */
obj_byte (orp, 0x23); /* absolute type for debugging */
obj_byte (orp, 0);
obj_byte (orp, 1);
obj_byte (orp, 0);
obj_emit2 (orp);
obj_byte (orp, 0x40);
obj_byte (orp, dTYPEDEF);
obj_word (orp, 0x1e); /* type # for linking */
obj_word (orp, 0); /* size of type */
obj_byte (orp, 0x23); /* absolute type for debugging */
obj_byte (orp, 0);
obj_byte (orp, 5);
obj_byte (orp, 0);
obj_emit2 (orp);
/* put out the array types */
for (i= ARRAYBOT; i < arrindex; i++) {
obj_byte (orp, 0x40);
obj_byte (orp, dTYPEDEF);
obj_word (orp, i ); /* type # for linking */
obj_word (orp, arrtmp->size); /* size of type */
obj_byte (orp, 0x1A); /* absolute type for debugging (array)*/
obj_byte (orp, arrtmp->basetype ); /* base type */
obj_emit2 (orp);
arrtmp = arrtmp->next ;
}
}
/*
* write out line number info with a LINNUM record
* switch records when we switch segments, and output the
* file in a pseudo-TASM fashion. The record switch is naive; that
* is that one file may have many records for the same segment
* if there are lots of segment switches
*/
if (fnhead && debuginfo) {
seg = fnhead->lnhead->segment;
for (fn = fnhead; fn; fn = fn->next) {
/* write out current file name */
orp->type = COMENT;
orp->ori = ori_null;
obj_byte (orp, 0x40);
obj_byte (orp, dFILNAME);
if (dbg_type == dbg_bi)
obj_byte( orp,0);
else
obj_byte(orp,seg->lsdebseg) ;
obj_name( orp,fn->name);
obj_filetime(orp, fn->name); /* DAL put in real time */
obj_emit2 (orp);
/* write out line numbers this file */
orp->type = LINNUM;
/* Begin DAL */
if (dbg_type == dbg_ls)
orp->type = LINN32 ;
/* End DAL */
orp->ori = ori_linnum;
for (ln = fn->lnhead; ln; ln = ln->next) {
if (
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -