📄 outcoff.c
字号:
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,
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 + -