📄 outobj.c
字号:
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);
}
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) {
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);
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) {
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);
obj_byte( orp,0);
obj_name( orp,fn->name);
obj_dword(orp, 0);
obj_emit2 (orp);
/* write out line numbers this file */
orp->type = LINNUM;
orp->ori = ori_linnum;
for (ln = fn->lnhead; ln; ln = ln->next) {
if (seg != ln->segment) {
/* if we get here have to flush the buffer and start
* a new record for a new segment
*/
seg = ln->segment;
obj_emit ( orp );
}
orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
orp->parm[1] = seg->obj_index;
orp = obj_word(orp, ln->lineno);
orp = obj_x(orp, ln->offset);
obj_commit (orp);
}
obj_emit (orp);
}
}
/*
* we are going to locate the entry point segment now
* rather than wait until the MODEND record, because,
* then we can output a special symbol to tell where the
* entry point is.
*
*/
if (obj_entry_seg != NO_SEG) {
for (seg = seghead; seg; seg = seg->next) {
if (seg->index == obj_entry_seg) {
entry_seg_ptr = seg;
break;
}
}
if (!seg)
error(ERR_NONFATAL, "entry point is not in this module");
}
/*
* get ready to put out symbol records
*/
orp->type = COMENT;
orp->ori = ori_local;
/*
* put out a symbol for the entry point
* no dots in this symbol, because, borland does
* not (officially) support dots in label names
* and I don't know what various versions of TLINK will do
*/
if (debuginfo && obj_entry_seg != NO_SEG) {
orp = obj_name (orp,"start_of_program");
orp = obj_word (orp,0x19); /* type: near label */
orp = obj_index (orp, seg->grp ? seg->grp->obj_index : 0);
orp = obj_index (orp, seg->obj_index);
orp = obj_x (orp, obj_entry_ofs);
obj_commit (orp);
}
/*
* put out the local labels
*/
for (seg = seghead; seg && debuginfo; seg = seg->next) {
/* labels this seg */
for (loc = seg->lochead; loc; loc = loc->next) {
orp = obj_name (orp,loc->name);
orp = obj_word (orp, loc->type);
orp = obj_index (orp, seg->grp ? seg->grp->obj_index : 0);
orp = obj_index (orp, seg->obj_index);
orp = obj_x (orp,loc->offset);
obj_commit (orp);
}
}
if (orp->used)
obj_emit (orp);
/*
* Write the LEDATA/FIXUPP pairs.
*/
for (seg = seghead; seg; seg = seg->next) {
obj_emit (seg->orp);
nasm_free (seg->orp);
}
/*
* Write the MODEND module end marker.
*/
orp->type = obj_use32 ? MODE32 : MODEND;
orp->ori = ori_null;
if (entry_seg_ptr) {
orp->type = entry_seg_ptr->use32 ? MODE32 : MODEND;
obj_byte (orp, 0xC1);
seg = entry_seg_ptr;
if (seg->grp) {
obj_byte (orp, 0x10);
obj_index (orp, seg->grp->obj_index);
} else {
/*
* the below changed to prevent TLINK crashing.
* Previous more efficient version read:
*
* obj_byte (orp, 0x50);
*/
obj_byte (orp, 0x00);
obj_index (orp, seg->obj_index);
}
obj_index (orp, seg->obj_index);
obj_x (orp, obj_entry_ofs);
} else
obj_byte (orp, 0);
obj_emit2 (orp);
nasm_free (orp);
}
void obj_fwrite(ObjRecord *orp)
{
unsigned int cksum, len;
unsigned char *ptr;
cksum = orp->type;
if (orp->x_size == 32)
cksum |= 1;
fputc (cksum, ofp);
len = orp->committed+1;
cksum += (len & 0xFF) + ((len>>8) & 0xFF);
fwriteshort (len, ofp);
fwrite (orp->buf, 1, len-1, ofp);
for (ptr=orp->buf; --len; ptr++)
cksum += *ptr;
fputc ( (-cksum) & 0xFF, ofp);
}
static const char *obj_stdmac[] = {
"%define __SECT__ [section .text]",
"%imacro group 1+.nolist",
"[group %1]",
"%endmacro",
"%imacro uppercase 0+.nolist",
"[uppercase %1]",
"%endmacro",
"%imacro export 1+.nolist",
"[export %1]",
"%endmacro",
"%imacro import 1+.nolist",
"[import %1]",
"%endmacro",
"%macro __NASM_CDecl__ 1",
"%endmacro",
NULL
};
void dbgbi_init(struct ofmt * of, void * id, FILE * fp, efunc error)
{
(void) of;
(void) id;
(void) fp;
(void) error;
fnhead = NULL;
fntail = &fnhead;
arrindex = ARRAYBOT ;
arrhead = NULL;
arrtail = &arrhead;
}
static void dbgbi_cleanup(void)
{
struct Segment *segtmp;
while (fnhead) {
struct FileName *fntemp = fnhead;
while (fnhead->lnhead) {
struct LineNumber *lntemp = fnhead->lnhead;
fnhead->lnhead = lntemp->next;
nasm_free( lntemp);
}
fnhead = fnhead->next;
nasm_free (fntemp->name);
nasm_free (fntemp);
}
for (segtmp=seghead; segtmp; segtmp=segtmp->next) {
while (segtmp->lochead) {
struct Public *loctmp = segtmp->lochead;
segtmp->lochead = loctmp->next;
nasm_free (loctmp->name);
nasm_free (loctmp);
}
}
while (arrhead) {
struct Array *arrtmp = arrhead;
arrhead = arrhead->next;
nasm_free (arrtmp);
}
}
static void dbgbi_linnum (const char *lnfname, long lineno, long segto)
{
struct FileName *fn;
struct LineNumber *ln;
struct Segment *seg;
if (segto == NO_SEG)
return;
/*
* If `any_segs' is still FALSE, we must define a default
* segment.
*/
if (!any_segs) {
int tempint; /* ignored */
if (segto != obj_segment("__NASMDEFSEG", 2, &tempint))
error (ERR_PANIC, "strange segment conditions in OBJ driver");
}
/*
* Find the segment we are targetting.
*/
for (seg = seghead; seg; seg = seg->next)
if (seg->index == segto)
break;
if (!seg)
error (ERR_PANIC, "lineno directed to nonexistent segment?");
/* for (fn = fnhead; fn; fn = fnhead->next) */
for (fn = fnhead; fn; fn = fn->next) /* fbk - Austin Lunnen - John Fine*/
if (!nasm_stricmp(lnfname,fn->name))
break;
if (!fn) {
fn = nasm_malloc ( sizeof( *fn));
fn->name = nasm_malloc ( strlen(lnfname) + 1) ;
strcpy (fn->name,lnfname);
fn->lnhead = NULL;
fn->ln
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -