summaryrefslogtreecommitdiff
path: root/outcoff.c
diff options
context:
space:
mode:
Diffstat (limited to 'outcoff.c')
-rw-r--r--outcoff.c92
1 files changed, 64 insertions, 28 deletions
diff --git a/outcoff.c b/outcoff.c
index 21b9bac4..09e886ce 100644
--- a/outcoff.c
+++ b/outcoff.c
@@ -37,14 +37,11 @@
* (2) Win32 doesn't bother putting any flags in the header flags
* field (at offset 0x12 into the file).
*
- * (3) Win32 puts some weird flags into the section header table.
- * It uses flags 0x80000000 (writable), 0x40000000 (readable) and
- * 0x20000000 (executable) in the expected combinations, which
- * standard COFF doesn't seem to bother with, but it also does
- * something else strange: it also flags code sections as
- * 0x00500000 and data/bss as 0x00300000. Even Microsoft's
- * documentation doesn't explain what these things mean. I just go
- * ahead and use them anyway - it seems to work.
+ * (3) Win32 uses some extra flags into the section header table:
+ * it defines flags 0x80000000 (writable), 0x40000000 (readable)
+ * and 0x20000000 (executable), and uses them in the expected
+ * combinations. It also defines 0x00100000 through 0x00700000 for
+ * section alignments of 1 through 64 bytes.
*
* (4) Both standard COFF and Win32 COFF seem to use the DWORD
* field directly after the section name in the section header
@@ -53,8 +50,7 @@
* to end starting at zero. Dunno why. Microsoft's documentation
* lists this field as "Virtual Size of Section", which doesn't
* seem to fit at all. In fact, Win32 even includes non-linked
- * sections such as .drectve in this calculation. Not that I can be
- * bothered with those things anyway.
+ * sections such as .drectve in this calculation.
*
* (5) Standard COFF does something very strange to common
* variables: the relocation point for a common variable is as far
@@ -131,13 +127,15 @@ static void coff_section_header (char *, long, long, long, long, int, long);
static void coff_write_relocs (struct Section *);
static void coff_write_symbols (void);
-static void coff_win32_init(FILE *fp, efunc errfunc, ldfunc ldef) {
+static void coff_win32_init(FILE *fp, efunc errfunc,
+ ldfunc ldef, evalfunc eval) {
win32 = TRUE;
(void) ldef; /* placate optimisers */
coff_gen_init(fp, errfunc);
}
-static void coff_std_init(FILE *fp, efunc errfunc, ldfunc ldef) {
+static void coff_std_init(FILE *fp, efunc errfunc,
+ ldfunc ldef, evalfunc eval) {
win32 = FALSE;
(void) ldef; /* placate optimisers */
coff_gen_init(fp, errfunc);
@@ -209,7 +207,7 @@ static int coff_make_section (char *name, unsigned long flags) {
static long coff_section_names (char *name, int pass, int *bits) {
char *p;
- unsigned long flags;
+ unsigned long flags, align_and = ~0L, align_or = 0L;
int i;
/*
@@ -224,7 +222,7 @@ static long coff_section_names (char *name, int pass, int *bits) {
p = name;
while (*p && !isspace(*p)) p++;
if (*p) *p++ = '\0';
- if (strlen(p) > 8) {
+ if (strlen(name) > 8) {
error (ERR_WARNING, "COFF section names limited to 8 characters:"
" truncating");
p[8] = '\0';
@@ -237,7 +235,7 @@ static long coff_section_names (char *name, int pass, int *bits) {
while (*p && !isspace(*p)) p++;
if (*p) *p++ = '\0';
while (*p && isspace(*p)) p++;
-
+
if (!nasm_stricmp(q, "code") || !nasm_stricmp(q, "text")) {
flags = TEXT_FLAGS;
} else if (!nasm_stricmp(q, "data")) {
@@ -252,6 +250,32 @@ static long coff_section_names (char *name, int pass, int *bits) {
error (ERR_NONFATAL, "standard COFF does not support"
" informational sections");
}
+ } else if (!nasm_strnicmp(q,"align=",6)) {
+ if (!win32)
+ error (ERR_NONFATAL, "standard COFF does not support"
+ " section alignment specification");
+ else {
+ if (q[6+strspn(q+6,"0123456789")])
+ error(ERR_NONFATAL, "argument to `align' is not numeric");
+ else {
+ unsigned int align = atoi(q+6);
+ if (!align || ((align-1) & align))
+ error(ERR_NONFATAL, "argument to `align' is not a"
+ " power of two");
+ else if (align > 64)
+ error(ERR_NONFATAL, "Win32 cannot align sections"
+ " to better than 64-byte boundaries");
+ else {
+ align_and = ~0x00F00000L;
+ align_or = (align == 1 ? 0x00100000L :
+ align == 2 ? 0x00200000L :
+ align == 4 ? 0x00300000L :
+ align == 8 ? 0x00400000L :
+ align == 16 ? 0x00500000L :
+ align == 32 ? 0x00600000L : 0x00700000L);
+ }
+ }
+ }
}
}
@@ -259,18 +283,19 @@ static long coff_section_names (char *name, int pass, int *bits) {
if (!strcmp(name, sects[i]->name))
break;
if (i == nsects) {
- if (!strcmp(name, ".text") && !flags)
- i = coff_make_section (name, TEXT_FLAGS);
- else if (!strcmp(name, ".data") && !flags)
- i = coff_make_section (name, DATA_FLAGS);
- else if (!strcmp(name, ".bss") && !flags)
- i = coff_make_section (name, BSS_FLAGS);
- else if (flags)
- i = coff_make_section (name, flags);
- else
- i = coff_make_section (name, TEXT_FLAGS);
+ if (!flags) {
+ if (!strcmp(name, ".data"))
+ flags = DATA_FLAGS;
+ else if (!strcmp(name, ".bss"))
+ flags = BSS_FLAGS;
+ else
+ flags = TEXT_FLAGS;
+ }
+ i = coff_make_section (name, flags);
if (flags)
sects[i]->flags = flags;
+ sects[i]->flags &= align_and;
+ sects[i]->flags |= align_or;
} else if (pass == 1) {
if (flags)
error (ERR_WARNING, "section attributes ignored on"
@@ -281,10 +306,14 @@ static long coff_section_names (char *name, int pass, int *bits) {
}
static void coff_deflabel (char *name, long segment, long offset,
- int is_global) {
+ int is_global, char *special) {
int pos = strslen+4;
struct Symbol *sym;
+ if (special)
+ error (ERR_NONFATAL, "binary format does not support any"
+ " special symbol types");
+
if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
return;
@@ -430,8 +459,8 @@ static void coff_out (long segto, void *data, unsigned long type,
error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
coff_sect_write (s, data, realbytes);
} else if (type == OUT_ADDRESS) {
- if (realbytes == 2 && (segment != NO_SEG || wrt != NO_SEG))
- error(ERR_NONFATAL, "COFF format does not support 16-bit"
+ 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;
@@ -661,11 +690,17 @@ static void coff_win32_filename (char *inname, char *outname, efunc error) {
#endif /* defined(OF_COFF) || defined(OF_WIN32) */
+static char *coff_stdmac[] = {
+ "%define __SECT__ [section .text]",
+ NULL
+};
+
#ifdef OF_COFF
struct ofmt of_coff = {
"COFF (i386) object files (e.g. DJGPP for DOS)",
"coff",
+ coff_stdmac,
coff_std_init,
coff_out,
coff_deflabel,
@@ -683,6 +718,7 @@ struct ofmt of_coff = {
struct ofmt of_win32 = {
"Microsoft Win32 (i386) object files",
"win32",
+ coff_stdmac,
coff_win32_init,
coff_out,
coff_deflabel,