📄 outobj.c
字号:
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 = MODEND;
orp->ori = ori_null;
if (entry_seg_ptr) {
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 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)
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->lntail = & fn->lnhead;
fn->next = NULL;
*fntail = fn;
fntail = &fn->next;
}
ln = nasm_malloc ( sizeof( *ln));
ln->segment = seg;
ln->offset = seg->currentpos;
ln->lineno = lineno;
ln->next = NULL;
*fn->lntail = ln;
fn->lntail = &ln->next;
}
static void dbgbi_deflabel (char *name, long segment,
long offset, int is_global, char *special)
{
struct Segment *seg;
(void) special;
/*
* 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] != '@') {
return;
}
/*
* Case (i):
*/
if (obj_seg_needs_update) {
return;
} else if (obj_grp_needs_update) {
return;
}
if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
return;
if (segment >= SEG_ABS || segment == NO_SEG) {
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'. But the label should exist due to a prior
* call to obj_deflabel so we can skip that.
*/
for (seg = seghead; seg; seg = seg->next)
if (seg->index == segment) {
struct Public *loc = nasm_malloc (sizeof(*loc));
/*
* Case (ii). Maybe MODPUB someday?
*/
last_defined = *seg->loctail = loc;
seg->loctail = &loc->next;
loc->next = NULL;
loc->name = nasm_strdup(name);
loc->offset = offset;
}
}
static void dbgbi_typevalue (long type)
{
int vsize;
int elem = TYM_ELEMENTS(type);
type = TYM_TYPE(type);
if (!last_defined)
return;
switch (type) {
case TY_BYTE:
last_defined->type = 8; /* unsigned char */
vsize = 1;
break;
case TY_WORD:
last_defined->type = 10; /* unsigned word */
vsize = 2;
break;
case TY_DWORD:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -