📄 outcoff.c
字号:
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,
const unsigned char *data, unsigned long len)
{
saa_wbytes (sect->data, data, len);
sect->len += len;
}
typedef struct tagString {
struct tagString *Next;
int len;
char *String;
} STRING;
#define EXPORT_SECTION_NAME ".drectve"
#define EXPORT_SECTION_FLAGS INFO_FLAGS
/*
#define EXPORT_SECTION_NAME ".text"
#define EXPORT_SECTION_FLAGS TEXT_FLAGS
*/
static STRING *Exports = NULL;
static struct Section *directive_sec;
void AddExport(char *name)
{
STRING *rvp = Exports,*newS;
newS = (STRING *)nasm_malloc(sizeof(STRING));
newS->len = strlen(name);
newS->Next = NULL;
newS->String = (char*)nasm_malloc( newS->len + 1 );
strcpy( newS->String, name );
if (rvp == NULL)
{
int i;
for (i=0; i<nsects; i++)
if (!strcmp( EXPORT_SECTION_NAME, sects[i]->name))
break;
if( i == nsects )
directive_sec = sects[coff_make_section( EXPORT_SECTION_NAME, EXPORT_SECTION_FLAGS )];
else
directive_sec = sects[i];
Exports = newS;
}
else {
while (rvp->Next) {
if (!strcmp(rvp->String,name))
return;
rvp = rvp->Next;
}
rvp->Next = newS;
}
}
void BuildExportTable(void)
{
STRING *rvp = Exports, *next;
unsigned char buf[256];
int len;
if (rvp == NULL) return;
while (rvp) {
len = sprintf( (char*)buf, "-export:%s ", rvp->String );
coff_sect_write( directive_sec, buf, len );
rvp = rvp->Next;
}
next = Exports;
while( ( rvp = next ) )
{
next = rvp->Next;
nasm_free( rvp->String );
nasm_free( rvp );
}
Exports = NULL;
}
static int coff_directives (char *directive, char *value, int pass)
{
if (!strcmp(directive, "export")) {
char *q, *name;
if (pass == 2)
return 1; /* ignore in pass two */
name = q = value;
while (*q && !isspace(*q))
q++;
if (isspace(*q)) {
*q++ = '\0';
while (*q && isspace(*q))
q++;
}
if (!*name) {
error(ERR_NONFATAL, "`export' directive requires export name");
return 1;
}
if(*q) {
error(ERR_NONFATAL, "unrecognised export qualifier `%s'", q);
return 1;
}
AddExport( name );
return 1;
}
return 0;
}
static void coff_write (void)
{
long pos, sympos, vsize;
int i;
BuildExportTable(); /* fill in the .drectve section with -export's */
/*
* 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];
unsigned long 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 const char *coff_stdmac[] = {
"%define __SECT__ [section .text]",
"%macro __NASM_CDecl__ 1",
"%endmacro",
"%imacro export 1+.nolist",
"[export %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 + -