Fixed c99 support for RDOFF Tools
[nasm.git] / output / outcoff.c
blobbdcc4ce0230ba640621627b19f4e62c62c5aa024
1 /* outcoff.c output routines for the Netwide Assembler to produce
2 * COFF object files (for DJGPP and Win32)
4 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
5 * Julian Hall. All rights reserved. The software is
6 * redistributable under the licence given in the file "Licence"
7 * distributed in the NASM archive.
8 */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <time.h>
15 #include <inttypes.h>
17 #include "nasm.h"
18 #include "nasmlib.h"
19 #include "outform.h"
21 #if defined(OF_COFF) || defined(OF_WIN32) || defined(OF_WIN64)
24 * Notes on COFF:
26 * (0) When I say `standard COFF' below, I mean `COFF as output and
27 * used by DJGPP'. I assume DJGPP gets it right.
29 * (1) Win32 appears to interpret the term `relative relocation'
30 * differently from standard COFF. Standard COFF understands a
31 * relative relocation to mean that during relocation you add the
32 * address of the symbol you're referencing, and subtract the base
33 * address of the section you're in. Win32 COFF, by contrast, seems
34 * to add the address of the symbol and then subtract the address
35 * of THE BYTE AFTER THE RELOCATED DWORD. Hence the two formats are
36 * subtly incompatible.
38 * (2) Win32 doesn't bother putting any flags in the header flags
39 * field (at offset 0x12 into the file).
41 * (3) Win32 uses some extra flags into the section header table:
42 * it defines flags 0x80000000 (writable), 0x40000000 (readable)
43 * and 0x20000000 (executable), and uses them in the expected
44 * combinations. It also defines 0x00100000 through 0x00700000 for
45 * section alignments of 1 through 64 bytes.
47 * (4) Both standard COFF and Win32 COFF seem to use the DWORD
48 * field directly after the section name in the section header
49 * table for something strange: they store what the address of the
50 * section start point _would_ be, if you laid all the sections end
51 * to end starting at zero. Dunno why. Microsoft's documentation
52 * lists this field as "Virtual Size of Section", which doesn't
53 * seem to fit at all. In fact, Win32 even includes non-linked
54 * sections such as .drectve in this calculation.
56 * (5) Standard COFF does something very strange to common
57 * variables: the relocation point for a common variable is as far
58 * _before_ the variable as its size stretches out _after_ it. So
59 * we must fix up common variable references. Win32 seems to be
60 * sensible on this one.
63 /* Flag which version of COFF we are currently outputting. */
64 static int win32, win64;
66 struct Reloc {
67 struct Reloc *next;
68 int32_t address; /* relative to _start_ of section */
69 int32_t symbol; /* symbol number */
70 enum {
71 SECT_SYMBOLS,
72 ABS_SYMBOL,
73 REAL_SYMBOLS
74 } symbase; /* relocation for symbol number :) */
75 int relative; /* TRUE or FALSE */
76 int size64; /* TRUE or FALSE */
79 struct Symbol {
80 int8_t name[9];
81 int32_t strpos; /* string table position of name */
82 int section; /* section number where it's defined
83 * - in COFF codes, not NASM codes */
84 int is_global; /* is it a global symbol or not? */
85 int32_t value; /* address, or COMMON variable size */
88 static FILE *coffp;
89 static efunc error;
90 static int8_t coff_infile[FILENAME_MAX];
92 struct Section {
93 struct SAA *data;
94 uint32_t len;
95 int nrelocs;
96 int32_t index;
97 struct Reloc *head, **tail;
98 uint32_t flags; /* section flags */
99 int8_t name[9];
100 int32_t pos, relpos;
103 #define TEXT_FLAGS ((win32 | win64) ? 0x60500020L : 0x20L)
104 #define DATA_FLAGS ((win32 | win64) ? 0xC0300040L : 0x40L)
105 #define BSS_FLAGS ((win32 | win64) ? 0xC0300080L : 0x80L)
106 #define INFO_FLAGS 0x00100A00L
107 #define RDATA_FLAGS ((win32 | win64) ? 0x40400040L : 0x40L)
109 #define SECT_DELTA 32
110 static struct Section **sects;
111 static int nsects, sectlen;
113 static struct SAA *syms;
114 static uint32_t nsyms;
116 static int32_t def_seg;
118 static int initsym;
120 static struct RAA *bsym, *symval;
122 static struct SAA *strs;
123 static uint32_t strslen;
125 static void coff_gen_init(FILE *, efunc);
126 static void coff_sect_write(struct Section *, const uint8_t *,
127 uint32_t);
128 static void coff_write(void);
129 static void coff_section_header(int8_t *, int32_t, int32_t, int32_t, int32_t, int, int32_t);
130 static void coff_write_relocs(struct Section *);
131 static void coff_write_symbols(void);
133 static void coff_win32_init(FILE * fp, efunc errfunc,
134 ldfunc ldef, evalfunc eval)
136 win32 = TRUE; win64 = FALSE;
137 (void)ldef; /* placate optimizers */
138 coff_gen_init(fp, errfunc);
141 static void coff_win64_init(FILE * fp, efunc errfunc,
142 ldfunc ldef, evalfunc eval)
144 maxbits = 64;
145 win32 = FALSE; win64 = TRUE;
146 (void)ldef; /* placate optimizers */
147 coff_gen_init(fp, errfunc);
150 static void coff_std_init(FILE * fp, efunc errfunc, ldfunc ldef,
151 evalfunc eval)
153 win32 = win64 = FALSE;
154 (void)ldef; /* placate optimizers */
155 coff_gen_init(fp, errfunc);
158 static void coff_gen_init(FILE * fp, efunc errfunc)
161 coffp = fp;
162 error = errfunc;
163 sects = NULL;
164 nsects = sectlen = 0;
165 syms = saa_init((int32_t)sizeof(struct Symbol));
166 nsyms = 0;
167 bsym = raa_init();
168 symval = raa_init();
169 strs = saa_init(1L);
170 strslen = 0;
171 def_seg = seg_alloc();
174 static void coff_cleanup(int debuginfo)
176 struct Reloc *r;
177 int i;
179 (void)debuginfo;
181 coff_write();
182 fclose(coffp);
183 for (i = 0; i < nsects; i++) {
184 if (sects[i]->data)
185 saa_free(sects[i]->data);
186 while (sects[i]->head) {
187 r = sects[i]->head;
188 sects[i]->head = sects[i]->head->next;
189 nasm_free(r);
191 nasm_free(sects[i]);
193 nasm_free(sects);
194 saa_free(syms);
195 raa_free(bsym);
196 raa_free(symval);
197 saa_free(strs);
200 static int coff_make_section(int8_t *name, uint32_t flags)
202 struct Section *s;
204 s = nasm_malloc(sizeof(*s));
206 if (flags != BSS_FLAGS)
207 s->data = saa_init(1L);
208 else
209 s->data = NULL;
210 s->head = NULL;
211 s->tail = &s->head;
212 s->len = 0;
213 s->nrelocs = 0;
214 if (!strcmp(name, ".text"))
215 s->index = def_seg;
216 else
217 s->index = seg_alloc();
218 strncpy(s->name, name, 8);
219 s->name[8] = '\0';
220 s->flags = flags;
222 if (nsects >= sectlen)
223 sects =
224 nasm_realloc(sects, (sectlen += SECT_DELTA) * sizeof(*sects));
225 sects[nsects++] = s;
227 return nsects - 1;
230 static int32_t coff_section_names(int8_t *name, int pass, int *bits)
232 int8_t *p;
233 uint32_t flags, align_and = ~0L, align_or = 0L;
234 int i;
237 * Set default bits.
239 if (!name) {
240 if(win64)
241 *bits = 64;
242 else
243 *bits = 32;
246 if (!name)
247 return def_seg;
249 p = name;
250 while (*p && !isspace(*p))
251 p++;
252 if (*p)
253 *p++ = '\0';
254 if (strlen(name) > 8) {
255 error(ERR_WARNING, "COFF section names limited to 8 characters:"
256 " truncating");
257 name[8] = '\0';
259 flags = 0;
261 while (*p && isspace(*p))
262 p++;
263 while (*p) {
264 int8_t *q = p;
265 while (*p && !isspace(*p))
266 p++;
267 if (*p)
268 *p++ = '\0';
269 while (*p && isspace(*p))
270 p++;
272 if (!nasm_stricmp(q, "code") || !nasm_stricmp(q, "text")) {
273 flags = TEXT_FLAGS;
274 } else if (!nasm_stricmp(q, "data")) {
275 flags = DATA_FLAGS;
276 } else if (!nasm_stricmp(q, "rdata")) {
277 if (win32 | win64)
278 flags = RDATA_FLAGS;
279 else {
280 flags = DATA_FLAGS; /* gotta do something */
281 error(ERR_NONFATAL, "standard COFF does not support"
282 " read-only data sections");
284 } else if (!nasm_stricmp(q, "bss")) {
285 flags = BSS_FLAGS;
286 } else if (!nasm_stricmp(q, "info")) {
287 if (win32 | win64)
288 flags = INFO_FLAGS;
289 else {
290 flags = DATA_FLAGS; /* gotta do something */
291 error(ERR_NONFATAL, "standard COFF does not support"
292 " informational sections");
294 } else if (!nasm_strnicmp(q, "align=", 6)) {
295 if (!(win32 | win64))
296 error(ERR_NONFATAL, "standard COFF does not support"
297 " section alignment specification");
298 else {
299 if (q[6 + strspn(q + 6, "0123456789")])
300 error(ERR_NONFATAL,
301 "argument to `align' is not numeric");
302 else {
303 unsigned int align = atoi(q + 6);
304 if (!align || ((align - 1) & align))
305 error(ERR_NONFATAL, "argument to `align' is not a"
306 " power of two");
307 else if (align > 64)
308 error(ERR_NONFATAL, "Win32 cannot align sections"
309 " to better than 64-byte boundaries");
310 else {
311 align_and = ~0x00F00000L;
312 align_or = (align == 1 ? 0x00100000L :
313 align == 2 ? 0x00200000L :
314 align == 4 ? 0x00300000L :
315 align == 8 ? 0x00400000L :
316 align == 16 ? 0x00500000L :
317 align ==
318 32 ? 0x00600000L : 0x00700000L);
325 for (i = 0; i < nsects; i++)
326 if (!strcmp(name, sects[i]->name))
327 break;
328 if (i == nsects) {
329 if (!flags) {
330 if (!strcmp(name, ".data"))
331 flags = DATA_FLAGS;
332 else if (!strcmp(name, ".rdata"))
333 flags = RDATA_FLAGS;
334 else if (!strcmp(name, ".bss"))
335 flags = BSS_FLAGS;
336 else
337 flags = TEXT_FLAGS;
339 i = coff_make_section(name, flags);
340 if (flags)
341 sects[i]->flags = flags;
342 sects[i]->flags &= align_and;
343 sects[i]->flags |= align_or;
344 } else if (pass == 1) {
345 if (flags)
346 error(ERR_WARNING, "section attributes ignored on"
347 " redeclaration of section `%s'", name);
350 return sects[i]->index;
353 static void coff_deflabel(int8_t *name, int32_t segment, int32_t offset,
354 int is_global, int8_t *special)
356 int pos = strslen + 4;
357 struct Symbol *sym;
359 if (special)
360 error(ERR_NONFATAL, "binary format does not support any"
361 " special symbol types");
363 if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
364 error(ERR_NONFATAL, "unrecognized special symbol `%s'", name);
365 return;
368 if (strlen(name) > 8) {
369 saa_wbytes(strs, name, (int32_t)(1 + strlen(name)));
370 strslen += 1 + strlen(name);
371 } else
372 pos = -1;
374 sym = saa_wstruct(syms);
376 sym->strpos = pos;
377 if (pos == -1)
378 strcpy(sym->name, name);
379 sym->is_global = !!is_global;
380 if (segment == NO_SEG)
381 sym->section = -1; /* absolute symbol */
382 else {
383 int i;
384 sym->section = 0;
385 for (i = 0; i < nsects; i++)
386 if (segment == sects[i]->index) {
387 sym->section = i + 1;
388 break;
390 if (!sym->section)
391 sym->is_global = TRUE;
393 if (is_global == 2)
394 sym->value = offset;
395 else
396 sym->value = (sym->section == 0 ? 0 : offset);
399 * define the references from external-symbol segment numbers
400 * to these symbol records.
402 if (sym->section == 0) {
403 bsym = raa_write(bsym, segment, nsyms);
406 if (segment != NO_SEG)
407 symval = raa_write(symval, segment, sym->section ? 0 : sym->value);
409 nsyms++;
412 static int32_t coff_add_reloc(struct Section *sect, int32_t segment,
413 int relative, int size64)
415 struct Reloc *r;
417 r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
418 sect->tail = &r->next;
419 r->next = NULL;
421 r->address = sect->len;
422 if (segment == NO_SEG)
423 r->symbol = 0, r->symbase = ABS_SYMBOL;
424 else {
425 int i;
426 r->symbase = REAL_SYMBOLS;
427 for (i = 0; i < nsects; i++)
428 if (segment == sects[i]->index) {
429 r->symbol = i * 2;
430 r->symbase = SECT_SYMBOLS;
431 break;
433 if (r->symbase == REAL_SYMBOLS)
434 r->symbol = raa_read(bsym, segment);
436 r->relative = relative;
438 sect->nrelocs++;
441 * Return the fixup for standard COFF common variables.
443 if (r->symbase == REAL_SYMBOLS && !(win32 | win64))
444 return raa_read(symval, segment);
445 else
446 return 0;
449 static void coff_out(int32_t segto, const void *data, uint32_t type,
450 int32_t segment, int32_t wrt)
452 struct Section *s;
453 int32_t realbytes = type & OUT_SIZMASK;
454 uint8_t mydata[8], *p;
455 int i;
457 if (wrt != NO_SEG) {
458 wrt = NO_SEG; /* continue to do _something_ */
459 error(ERR_NONFATAL, "WRT not supported by COFF output formats");
462 type &= OUT_TYPMASK;
465 * handle absolute-assembly (structure definitions)
467 if (segto == NO_SEG) {
468 if (type != OUT_RESERVE)
469 error(ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
470 " space");
471 return;
474 s = NULL;
475 for (i = 0; i < nsects; i++)
476 if (segto == sects[i]->index) {
477 s = sects[i];
478 break;
480 if (!s) {
481 int tempint; /* ignored */
482 if (segto != coff_section_names(".text", 2, &tempint))
483 error(ERR_PANIC, "strange segment conditions in COFF driver");
484 else
485 s = sects[nsects - 1];
488 if (!s->data && type != OUT_RESERVE) {
489 error(ERR_WARNING, "attempt to initialize memory in"
490 " BSS section `%s': ignored", s->name);
491 if (type == OUT_REL2ADR)
492 realbytes = 2;
493 else if (type == OUT_REL4ADR)
494 realbytes = 4;
495 s->len += realbytes;
496 return;
499 if (type == OUT_RESERVE) {
500 if (s->data) {
501 error(ERR_WARNING, "uninitialised space declared in"
502 " non-BSS section `%s': zeroing", s->name);
503 coff_sect_write(s, NULL, realbytes);
504 } else
505 s->len += realbytes;
506 } else if (type == OUT_RAWDATA) {
507 if (segment != NO_SEG)
508 error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
509 coff_sect_write(s, data, realbytes);
510 } else if (type == OUT_ADDRESS) {
511 if (!(win64)) {
512 if (realbytes != 4 && (segment != NO_SEG || wrt != NO_SEG))
513 error(ERR_NONFATAL, "COFF format does not support non-32-bit"
514 " relocations");
515 else {
516 int32_t fix = 0;
517 if (segment != NO_SEG || wrt != NO_SEG) {
518 if (wrt != NO_SEG) {
519 error(ERR_NONFATAL, "COFF format does not support"
520 " WRT types");
521 } else if (segment % 2) {
522 error(ERR_NONFATAL, "COFF format does not support"
523 " segment base references");
524 } else
525 fix = coff_add_reloc(s, segment, FALSE, FALSE);
527 p = mydata;
528 WRITELONG(p, *(int32_t *)data + fix);
529 coff_sect_write(s, mydata, realbytes);
531 } else {
532 int32_t fix = 0;
533 p = mydata;
534 if (realbytes == 8) {
535 /* if (segment != NO_SEG || wrt != NO_SEG) {
536 if (wrt != NO_SEG) {
537 error(ERR_NONFATAL, "COFF format does not support"
538 " WRT types");
539 } else if (segment % 2) {
540 error(ERR_NONFATAL, "COFF format does not support"
541 " segment base references");
542 } else
543 fix = coff_add_reloc(s, segment, FALSE);
544 } */
545 fix = coff_add_reloc(s, segment, FALSE, TRUE);
546 WRITEDLONG(p, *(int64_t *)data + fix);
547 coff_sect_write(s, mydata, realbytes);
548 } else {
549 fix = coff_add_reloc(s, segment, FALSE, FALSE);
550 WRITELONG(p, *(int32_t *)data + fix);
551 coff_sect_write(s, mydata, realbytes);
554 } else if (type == OUT_REL2ADR) {
555 error(ERR_NONFATAL, "COFF format does not support 16-bit"
556 " relocations");
557 } else if (type == OUT_REL4ADR) {
558 if (segment == segto && !(win64)) /* Acceptable for RIP-relative */
559 error(ERR_PANIC, "intra-segment OUT_REL4ADR");
560 else if (segment == NO_SEG && win32)
561 error(ERR_NONFATAL, "Win32 COFF does not correctly support"
562 " relative references to absolute addresses");
563 else {
564 int32_t fix = 0;
565 if (segment != NO_SEG && segment % 2) {
566 error(ERR_NONFATAL, "COFF format does not support"
567 " segment base references");
568 } else
569 fix = coff_add_reloc(s, segment, TRUE, FALSE);
570 p = mydata;
571 if (win32 | win64) {
572 WRITELONG(p, *(int32_t *)data + 4 - realbytes + fix);
573 } else {
574 WRITELONG(p, *(int32_t *)data - (realbytes + s->len) + fix);
576 coff_sect_write(s, mydata, 4L);
582 static void coff_sect_write(struct Section *sect,
583 const uint8_t *data, uint32_t len)
585 saa_wbytes(sect->data, data, len);
586 sect->len += len;
589 typedef struct tagString {
590 struct tagString *Next;
591 int len;
592 int8_t *String;
593 } STRING;
595 #define EXPORT_SECTION_NAME ".drectve"
596 #define EXPORT_SECTION_FLAGS INFO_FLAGS
598 #define EXPORT_SECTION_NAME ".text"
599 #define EXPORT_SECTION_FLAGS TEXT_FLAGS
602 static STRING *Exports = NULL;
603 static struct Section *directive_sec;
604 void AddExport(int8_t *name)
606 STRING *rvp = Exports, *newS;
608 newS = (STRING *) nasm_malloc(sizeof(STRING));
609 newS->len = strlen(name);
610 newS->Next = NULL;
611 newS->String = (int8_t *)nasm_malloc(newS->len + 1);
612 strcpy(newS->String, name);
613 if (rvp == NULL) {
614 int i;
615 for (i = 0; i < nsects; i++)
617 if (!strcmp(EXPORT_SECTION_NAME, sects[i]->name))
618 break;
619 if (i == nsects)
620 directive_sec =
621 sects[coff_make_section
622 (EXPORT_SECTION_NAME, EXPORT_SECTION_FLAGS)];
623 else
624 directive_sec = sects[i];
625 Exports = newS;
626 } else {
627 while (rvp->Next) {
628 if (!strcmp(rvp->String, name))
629 return;
630 rvp = rvp->Next;
632 rvp->Next = newS;
636 void BuildExportTable(void)
638 STRING *rvp = Exports, *next;
639 uint8_t buf[256];
640 int len;
641 if (rvp == NULL)
642 return;
643 while (rvp) {
644 len = sprintf((int8_t *)buf, "-export:%s ", rvp->String);
645 coff_sect_write(directive_sec, buf, len);
646 rvp = rvp->Next;
649 next = Exports;
650 while ((rvp = next)) {
651 next = rvp->Next;
652 nasm_free(rvp->String);
653 nasm_free(rvp);
655 Exports = NULL;
658 static int coff_directives(int8_t *directive, int8_t *value, int pass)
660 if (!strcmp(directive, "export")) {
661 int8_t *q, *name;
663 if (pass == 2)
664 return 1; /* ignore in pass two */
665 name = q = value;
666 while (*q && !isspace(*q))
667 q++;
668 if (isspace(*q)) {
669 *q++ = '\0';
670 while (*q && isspace(*q))
671 q++;
674 if (!*name) {
675 error(ERR_NONFATAL, "`export' directive requires export name");
676 return 1;
678 if (*q) {
679 error(ERR_NONFATAL, "unrecognized export qualifier `%s'", q);
680 return 1;
682 AddExport(name);
683 return 1;
685 return 0;
688 static void coff_write(void)
690 int32_t pos, sympos, vsize;
691 int i;
693 BuildExportTable(); /* fill in the .drectve section with -export's */
695 * Work out how big the file will get. Calculate the start of
696 * the `real' symbols at the same time.
698 pos = 0x14 + 0x28 * nsects;
699 initsym = 3; /* two for the file, one absolute */
700 for (i = 0; i < nsects; i++) {
701 if (sects[i]->data) {
702 sects[i]->pos = pos;
703 pos += sects[i]->len;
704 sects[i]->relpos = pos;
705 pos += 10 * sects[i]->nrelocs;
706 } else
707 sects[i]->pos = sects[i]->relpos = 0L;
708 initsym += 2; /* two for each section */
710 sympos = pos;
713 * Output the COFF header.
715 if (win64)
716 fwriteint16_t(0x8664, coffp); /* MACHINE_x86-64 */
717 else
718 fwriteint16_t(0x014C, coffp); /* MACHINE_i386 */
719 fwriteint16_t(nsects, coffp); /* number of sections */
720 fwriteint32_t(time(NULL), coffp); /* time stamp */
721 fwriteint32_t(sympos, coffp);
722 fwriteint32_t(nsyms + initsym, coffp);
723 fwriteint16_t(0, coffp); /* no optional header */
724 /* Flags: 32-bit, no line numbers. Win32 doesn't even bother with them. */
725 fwriteint16_t((win32 | win64) ? 0 : 0x104, coffp);
728 * Output the section headers.
730 vsize = 0L;
731 for (i = 0; i < nsects; i++) {
732 coff_section_header(sects[i]->name, vsize, sects[i]->len,
733 sects[i]->pos, sects[i]->relpos,
734 sects[i]->nrelocs, sects[i]->flags);
735 vsize += sects[i]->len;
739 * Output the sections and their relocations.
741 for (i = 0; i < nsects; i++)
742 if (sects[i]->data) {
743 saa_fpwrite(sects[i]->data, coffp);
744 coff_write_relocs(sects[i]);
748 * Output the symbol and string tables.
750 coff_write_symbols();
751 fwriteint32_t(strslen + 4, coffp); /* length includes length count */
752 saa_fpwrite(strs, coffp);
755 static void coff_section_header(int8_t *name, int32_t vsize,
756 int32_t datalen, int32_t datapos,
757 int32_t relpos, int nrelocs, int32_t flags)
759 int8_t padname[8];
761 memset(padname, 0, 8);
762 strncpy(padname, name, 8);
763 fwrite(padname, 8, 1, coffp);
764 fwriteint32_t(vsize, coffp);
765 fwriteint32_t(0L, coffp); /* RVA/offset - we ignore */
766 fwriteint32_t(datalen, coffp);
767 fwriteint32_t(datapos, coffp);
768 fwriteint32_t(relpos, coffp);
769 fwriteint32_t(0L, coffp); /* no line numbers - we don't do 'em */
770 fwriteint16_t(nrelocs, coffp);
771 fwriteint16_t(0, coffp); /* again, no line numbers */
772 fwriteint32_t(flags, coffp);
775 static void coff_write_relocs(struct Section *s)
777 struct Reloc *r;
779 for (r = s->head; r; r = r->next) {
780 fwriteint32_t(r->address, coffp);
781 fwriteint32_t(r->symbol + (r->symbase == REAL_SYMBOLS ? initsym :
782 r->symbase == ABS_SYMBOL ? initsym - 1 :
783 r->symbase == SECT_SYMBOLS ? 2 : 0),
784 coffp);
786 * Strange: Microsoft's COFF documentation says 0x03 for an
787 * absolute relocation, but both Visual C++ and DJGPP agree
788 * that in fact it's 0x06. I'll use 0x06 until someone
789 * argues. ***** UPDATE: PE/COFF Ver.8 docs confirm this -kkanios *****
791 if (win64)
792 fwriteint16_t(r->relative ? 0x04 : r->size64 ? 0x01 : 0x02, coffp);
793 else
794 fwriteint16_t(r->relative ? 0x14 : 0x06, coffp);
798 static void coff_symbol(int8_t *name, int32_t strpos, int32_t value,
799 int section, int type, int aux)
801 int8_t padname[8];
803 if (name) {
804 memset(padname, 0, 8);
805 strncpy(padname, name, 8);
806 fwrite(padname, 8, 1, coffp);
807 } else {
808 fwriteint32_t(0L, coffp);
809 fwriteint32_t(strpos, coffp);
811 fwriteint32_t(value, coffp);
812 fwriteint16_t(section, coffp);
813 fwriteint16_t(0, coffp);
814 fputc(type, coffp);
815 fputc(aux, coffp);
818 static void coff_write_symbols(void)
820 int8_t filename[18];
821 uint32_t i;
824 * The `.file' record, and the file name auxiliary record.
826 coff_symbol(".file", 0L, 0L, -2, 0x67, 1);
827 memset(filename, 0, 18);
828 strncpy(filename, coff_infile, 18);
829 fwrite(filename, 18, 1, coffp);
832 * The section records, with their auxiliaries.
834 memset(filename, 0, 18); /* useful zeroed buffer */
836 for (i = 0; i < nsects; i++) {
837 coff_symbol(sects[i]->name, 0L, 0L, i + 1, 3, 1);
838 fwriteint32_t(sects[i]->len, coffp);
839 fwriteint16_t(sects[i]->nrelocs, coffp);
840 fwrite(filename, 12, 1, coffp);
844 * The absolute symbol, for relative-to-absolute relocations.
846 coff_symbol(".absolut", 0L, 0L, -1, 3, 0);
849 * The real symbols.
851 saa_rewind(syms);
852 for (i = 0; i < nsyms; i++) {
853 struct Symbol *sym = saa_rstruct(syms);
854 coff_symbol(sym->strpos == -1 ? sym->name : NULL,
855 sym->strpos, sym->value, sym->section,
856 sym->is_global ? 2 : 3, 0);
860 static int32_t coff_segbase(int32_t segment)
862 return segment;
865 static void coff_std_filename(int8_t *inname, int8_t *outname, efunc error)
867 strcpy(coff_infile, inname);
868 standard_extension(inname, outname, ".o", error);
871 static void coff_win32_filename(int8_t *inname, int8_t *outname, efunc error)
873 strcpy(coff_infile, inname);
874 standard_extension(inname, outname, ".obj", error);
877 static const int8_t *coff_stdmac[] = {
878 "%define __SECT__ [section .text]",
879 "%macro __NASM_CDecl__ 1",
880 "%endmacro",
881 "%imacro export 1+.nolist",
882 "[export %1]",
883 "%endmacro",
884 NULL
887 static int coff_set_info(enum geninfo type, int8_t **val)
889 return 0;
891 #endif /* defined(OF_COFF) || defined(OF_WIN32) */
893 #ifdef OF_COFF
895 struct ofmt of_coff = {
896 "COFF (i386) object files (e.g. DJGPP for DOS)",
897 "coff",
898 NULL,
899 null_debug_arr,
900 &null_debug_form,
901 coff_stdmac,
902 coff_std_init,
903 coff_set_info,
904 coff_out,
905 coff_deflabel,
906 coff_section_names,
907 coff_segbase,
908 coff_directives,
909 coff_std_filename,
910 coff_cleanup
913 #endif
915 #ifdef OF_WIN32
917 struct ofmt of_win32 = {
918 "Microsoft Win32 (i386) object files",
919 "win32",
920 NULL,
921 null_debug_arr,
922 &null_debug_form,
923 coff_stdmac,
924 coff_win32_init,
925 coff_set_info,
926 coff_out,
927 coff_deflabel,
928 coff_section_names,
929 coff_segbase,
930 coff_directives,
931 coff_win32_filename,
932 coff_cleanup
935 #endif
937 #ifdef OF_WIN64
939 struct ofmt of_win64 = {
940 "Microsoft Win64 (x86-64) object files",
941 "win64",
942 NULL,
943 null_debug_arr,
944 &null_debug_form,
945 coff_stdmac,
946 coff_win64_init,
947 coff_set_info,
948 coff_out,
949 coff_deflabel,
950 coff_section_names,
951 coff_segbase,
952 coff_directives,
953 coff_win32_filename,
954 coff_cleanup
957 #endif