📄 outcoff.c
字号:
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 initialize 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 (!(win64)) {
if (realbytes != 4 && (segment != NO_SEG || wrt != NO_SEG))
error(ERR_NONFATAL, "COFF format does not support non-32-bit"
" relocations");
else {
int32_t 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, false);
}
p = mydata;
WRITELONG(p, *(int32_t *)data + fix);
coff_sect_write(s, mydata, realbytes);
}
} else {
int32_t fix = 0;
p = mydata;
if (realbytes == 8) {
/* 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);
} */
fix = coff_add_reloc(s, segment, false, true);
WRITEDLONG(p, *(int64_t *)data + fix);
coff_sect_write(s, mydata, realbytes);
} else {
fix = coff_add_reloc(s, segment, false, false);
WRITELONG(p, *(int32_t *)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 && !(win64)) /* Acceptable for RIP-relative */
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 {
int32_t 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, false);
p = mydata;
if (win32 | win64) {
WRITELONG(p, *(int32_t *)data + 4 - realbytes + fix);
} else {
WRITELONG(p, *(int32_t *)data - (realbytes + s->len) + fix);
}
coff_sect_write(s, mydata, 4L);
}
}
}
static void coff_sect_write(struct Section *sect,
const uint8_t *data, uint32_t 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;
uint8_t 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, "unrecognized export qualifier `%s'", q);
return 1;
}
AddExport(name);
return 1;
}
return 0;
}
static void coff_write(void)
{
int32_t 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.
*/
if (win64)
fwriteint16_t(0x8664, coffp); /* MACHINE_x86-64 */
else
fwriteint16_t(0x014C, coffp); /* MACHINE_i386 */
fwriteint16_t(nsects, coffp); /* number of sections */
fwriteint32_t(time(NULL), coffp); /* time stamp */
fwriteint32_t(sympos, coffp);
fwriteint32_t(nsyms + initsym, coffp);
fwriteint16_t(0, coffp); /* no optional header */
/* Flags: 32-bit, no line numbers. Win32 doesn't even bother with them. */
fwriteint16_t((win32 | win64) ? 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();
fwriteint32_t(strslen + 4, coffp); /* length includes length count */
saa_fpwrite(strs, coffp);
}
static void coff_section_header(char *name, int32_t vsize,
int32_t datalen, int32_t datapos,
int32_t relpos, int nrelocs, int32_t flags)
{
char padname[8];
(void)vsize;
memset(padname, 0, 8);
strncpy(padname, name, 8);
fwrite(padname, 8, 1, coffp);
fwriteint32_t(0, coffp); /* Virtual size field - set to 0 or vsize */
fwriteint32_t(0L, coffp); /* RVA/offset - we ignore */
fwriteint32_t(datalen, coffp);
fwriteint32_t(datapos, coffp);
fwriteint32_t(relpos, coffp);
fwriteint32_t(0L, coffp); /* no line numbers - we don't do 'em */
fwriteint16_t(nrelocs, coffp);
fwriteint16_t(0, coffp); /* again, no line numbers */
fwriteint32_t(flags, coffp);
}
static void coff_write_relocs(struct Section *s)
{
struct Reloc *r;
for (r = s->head; r; r = r->next) {
fwriteint32_t(r->address, coffp);
fwriteint32_t(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. ***** UPDATE: PE/COFF Ver.8 docs confirm this -kkanios *****
*/
if (win64)
fwriteint16_t(r->relative ? 0x04 : r->size64 ? 0x01 : 0x02, coffp);
else
fwriteint16_t(r->relative ? 0x14 : 0x06, coffp);
}
}
static void coff_symbol(char *name, int32_t strpos, int32_t 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 {
fwriteint32_t(0L, coffp);
fwriteint32_t(strpos, coffp);
}
fwriteint32_t(value, coffp);
fwriteint16_t(section, coffp);
fwriteint16_t(0, coffp);
fputc(type, coffp);
fputc(aux, coffp);
}
static void coff_write_symbols(void)
{
char filename[18];
uint32_t 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);
fwriteint32_t(sects[i]->len, coffp);
fwriteint16_t(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 int32_t coff_segbase(int32_t 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)
{
(void)type;
(void)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
#ifdef OF_WIN64
struct ofmt of_win64 = {
"Microsoft Win64 (x86-64) object files",
"win64",
NULL,
null_debug_arr,
&null_debug_form,
coff_stdmac,
coff_win64_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 + -