📄 outcoff.c
字号:
r->symbol = 0, r->symbase = ABS_SYMBOL;
else {
int i;
r->symbase = REAL_SYMBOLS;
for (i=0; i<nsects; i++)
if (segment == sects[i]->index) {
r->symbol = i*2;
r->symbase = SECT_SYMBOLS;
break;
}
if (r->symbase == REAL_SYMBOLS)
r->symbol = raa_read (bsym, segment);
}
r->relative = relative;
sect->nrelocs++;
/*
* Return the fixup for standard COFF common variables.
*/
if (r->symbase == REAL_SYMBOLS && !win32)
return raa_read (symval, segment);
else
return 0;
}
static void coff_out (long segto, void *data, unsigned long type,
long segment, long wrt)
{
struct Section *s;
long realbytes = type & OUT_SIZMASK;
unsigned char mydata[4], *p;
int i;
if (wrt != NO_SEG) {
wrt = NO_SEG; /* continue to do _something_ */
error (ERR_NONFATAL, "WRT not supported by COFF output formats");
}
type &= OUT_TYPMASK;
/*
* handle absolute-assembly (structure definitions)
*/
if (segto == NO_SEG) {
if (type != OUT_RESERVE)
error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
" space");
return;
}
s = NULL;
for (i=0; i<nsects; i++)
if (segto == sects[i]->index) {
s = sects[i];
break;
}
if (!s) {
int tempint; /* ignored */
if (segto != coff_section_names (".text", 2, &tempint))
error (ERR_PANIC, "strange segment conditions in COFF driver");
else
s = sects[nsects-1];
}
if (!s->data && type != OUT_RESERVE) {
error(ERR_WARNING, "attempt to initialise memory in"
" BSS section `%s': ignored", s->name);
if (type == OUT_REL2ADR)
realbytes = 2;
else if (type == OUT_REL4ADR)
realbytes = 4;
s->len += realbytes;
return;
}
if (type == OUT_RESERVE) {
if (s->data) {
error(ERR_WARNING, "uninitialised space declared in"
" non-BSS section `%s': zeroing", s->name);
coff_sect_write (s, NULL, realbytes);
} else
s->len += realbytes;
} else if (type == OUT_RAWDATA) {
if (segment != NO_SEG)
error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
coff_sect_write (s, data, realbytes);
} else if (type == OUT_ADDRESS) {
if (realbytes != 4 && (segment != NO_SEG || wrt != NO_SEG))
error(ERR_NONFATAL, "COFF format does not support non-32-bit"
" relocations");
else {
long fix = 0;
if (segment != NO_SEG || wrt != NO_SEG) {
if (wrt != NO_SEG) {
error(ERR_NONFATAL, "COFF format does not support"
" WRT types");
} else if (segment % 2) {
error(ERR_NONFATAL, "COFF format does not support"
" segment base references");
} else
fix = coff_add_reloc (s, segment, FALSE);
}
p = mydata;
WRITELONG (p, *(long *)data + fix);
coff_sect_write (s, mydata, realbytes);
}
} else if (type == OUT_REL2ADR) {
error(ERR_NONFATAL, "COFF format does not support 16-bit"
" relocations");
} else if (type == OUT_REL4ADR) {
if (segment == segto)
error(ERR_PANIC, "intra-segment OUT_REL4ADR");
else if (segment == NO_SEG && win32)
error(ERR_NONFATAL, "Win32 COFF does not correctly support"
" relative references to absolute addresses");
else {
long fix = 0;
if (segment != NO_SEG && segment % 2) {
error(ERR_NONFATAL, "COFF format does not support"
" segment base references");
} else
fix = coff_add_reloc (s, segment, TRUE);
p = mydata;
if (win32) {
WRITELONG (p, *(long*)data + 4 - realbytes + fix);
} else {
WRITELONG (p, *(long*)data-(realbytes + s->len) + fix);
}
coff_sect_write (s, mydata, 4L);
}
}
}
static void coff_sect_write (struct Section *sect,
unsigned char *data, unsigned long len)
{
saa_wbytes (sect->data, data, len);
sect->len += len;
}
static int coff_directives (char *directive, char *value, int pass)
{
return 0;
}
static void coff_write (void)
{
long pos, sympos, vsize;
int i;
/*
* Work out how big the file will get. Calculate the start of
* the `real' symbols at the same time.
*/
pos = 0x14 + 0x28 * nsects;
initsym = 3; /* two for the file, one absolute */
for (i=0; i<nsects; i++) {
if (sects[i]->data) {
sects[i]->pos = pos;
pos += sects[i]->len;
sects[i]->relpos = pos;
pos += 10 * sects[i]->nrelocs;
} else
sects[i]->pos = sects[i]->relpos = 0L;
initsym += 2; /* two for each section */
}
sympos = pos;
/*
* Output the COFF header.
*/
fwriteshort (0x14C, coffp); /* MACHINE_i386 */
fwriteshort (nsects, coffp); /* number of sections */
fwritelong (time(NULL), coffp); /* time stamp */
fwritelong (sympos, coffp);
fwritelong (nsyms + initsym, coffp);
fwriteshort (0, coffp); /* no optional header */
/* Flags: 32-bit, no line numbers. Win32 doesn't even bother with them. */
fwriteshort (win32 ? 0 : 0x104, coffp);
/*
* Output the section headers.
*/
vsize = 0L;
for (i=0; i<nsects; i++) {
coff_section_header (sects[i]->name, vsize, sects[i]->len,
sects[i]->pos, sects[i]->relpos,
sects[i]->nrelocs, sects[i]->flags);
vsize += sects[i]->len;
}
/*
* Output the sections and their relocations.
*/
for (i=0; i<nsects; i++)
if (sects[i]->data) {
saa_fpwrite (sects[i]->data, coffp);
coff_write_relocs (sects[i]);
}
/*
* Output the symbol and string tables.
*/
coff_write_symbols();
fwritelong (strslen+4, coffp); /* length includes length count */
saa_fpwrite (strs, coffp);
}
static void coff_section_header (char *name, long vsize,
long datalen, long datapos,
long relpos, int nrelocs, long flags)
{
char padname[8];
memset (padname, 0, 8);
strncpy (padname, name, 8);
fwrite (padname, 8, 1, coffp);
fwritelong (vsize, coffp);
fwritelong (0L, coffp); /* RVA/offset - we ignore */
fwritelong (datalen, coffp);
fwritelong (datapos, coffp);
fwritelong (relpos, coffp);
fwritelong (0L, coffp); /* no line numbers - we don't do 'em */
fwriteshort (nrelocs, coffp);
fwriteshort (0, coffp); /* again, no line numbers */
fwritelong (flags, coffp);
}
static void coff_write_relocs (struct Section *s)
{
struct Reloc *r;
for (r = s->head; r; r = r->next) {
fwritelong (r->address, coffp);
fwritelong (r->symbol + (r->symbase == REAL_SYMBOLS ? initsym :
r->symbase == ABS_SYMBOL ? initsym-1 :
r->symbase == SECT_SYMBOLS ? 2 : 0), coffp);
/*
* Strange: Microsoft's COFF documentation says 0x03 for an
* absolute relocation, but both Visual C++ and DJGPP agree
* that in fact it's 0x06. I'll use 0x06 until someone
* argues.
*/
fwriteshort (r->relative ? 0x14 : 0x06, coffp);
}
}
static void coff_symbol (char *name, long strpos, long value,
int section, int type, int aux)
{
char padname[8];
if (name) {
memset (padname, 0, 8);
strncpy (padname, name, 8);
fwrite (padname, 8, 1, coffp);
} else {
fwritelong (0L, coffp);
fwritelong (strpos, coffp);
}
fwritelong (value, coffp);
fwriteshort (section, coffp);
fwriteshort (0, coffp);
fputc (type, coffp);
fputc (aux, coffp);
}
static void coff_write_symbols (void)
{
char filename[18];
int i;
/*
* The `.file' record, and the file name auxiliary record.
*/
coff_symbol (".file", 0L, 0L, -2, 0x67, 1);
memset (filename, 0, 18);
strncpy (filename, coff_infile, 18);
fwrite (filename, 18, 1, coffp);
/*
* The section records, with their auxiliaries.
*/
memset (filename, 0, 18); /* useful zeroed buffer */
for (i=0; i<nsects; i++) {
coff_symbol (sects[i]->name, 0L, 0L, i+1, 3, 1);
fwritelong (sects[i]->len, coffp);
fwriteshort (sects[i]->nrelocs, coffp);
fwrite (filename, 12, 1, coffp);
}
/*
* The absolute symbol, for relative-to-absolute relocations.
*/
coff_symbol (".absolut", 0L, 0L, -1, 3, 0);
/*
* The real symbols.
*/
saa_rewind (syms);
for (i=0; i<nsyms; i++) {
struct Symbol *sym = saa_rstruct (syms);
coff_symbol (sym->strpos == -1 ? sym->name : NULL,
sym->strpos, sym->value, sym->section,
sym->is_global ? 2 : 3, 0);
}
}
static long coff_segbase (long segment)
{
return segment;
}
static void coff_std_filename (char *inname, char *outname, efunc error)
{
strcpy(coff_infile, inname);
standard_extension (inname, outname, ".o", error);
}
static void coff_win32_filename (char *inname, char *outname, efunc error)
{
strcpy(coff_infile, inname);
standard_extension (inname, outname, ".obj", error);
}
static char *coff_stdmac[] = {
"%define __SECT__ [section .text]",
"%macro __NASM_CDecl__ 1",
"%endmacro",
NULL
};
static int coff_set_info(enum geninfo type, char **val)
{
return 0;
}
#endif /* defined(OF_COFF) || defined(OF_WIN32) */
#ifdef OF_COFF
struct ofmt of_coff = {
"COFF (i386) object files (e.g. DJGPP for DOS)",
"coff",
NULL,
null_debug_arr,
&null_debug_form,
coff_stdmac,
coff_std_init,
coff_set_info,
coff_out,
coff_deflabel,
coff_section_names,
coff_segbase,
coff_directives,
coff_std_filename,
coff_cleanup
};
#endif
#ifdef OF_WIN32
struct ofmt of_win32 = {
"Microsoft Win32 (i386) object files",
"win32",
NULL,
null_debug_arr,
&null_debug_form,
coff_stdmac,
coff_win32_init,
coff_set_info,
coff_out,
coff_deflabel,
coff_section_names,
coff_segbase,
coff_directives,
coff_win32_filename,
coff_cleanup
};
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -