NASM 0.98.22
[platform/upstream/nasm.git] / outcoff.c
1 /* outcoff.c    output routines for the Netwide Assembler to produce
2  *              COFF object files (for DJGPP and Win32)
3  *
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  */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <time.h>
15
16 #include "nasm.h"
17 #include "nasmlib.h"
18 #include "outform.h"
19
20 #if defined(OF_COFF) || defined(OF_WIN32)
21
22 /*
23  * Notes on COFF:
24  *
25  * (0) When I say `standard COFF' below, I mean `COFF as output and
26  * used by DJGPP'. I assume DJGPP gets it right.
27  *
28  * (1) Win32 appears to interpret the term `relative relocation'
29  * differently from standard COFF. Standard COFF understands a
30  * relative relocation to mean that during relocation you add the
31  * address of the symbol you're referencing, and subtract the base
32  * address of the section you're in. Win32 COFF, by contrast, seems
33  * to add the address of the symbol and then subtract the address
34  * of THE BYTE AFTER THE RELOCATED DWORD. Hence the two formats are
35  * subtly incompatible.
36  *
37  * (2) Win32 doesn't bother putting any flags in the header flags
38  * field (at offset 0x12 into the file).
39  *
40  * (3) Win32 uses some extra flags into the section header table:
41  * it defines flags 0x80000000 (writable), 0x40000000 (readable)
42  * and 0x20000000 (executable), and uses them in the expected
43  * combinations. It also defines 0x00100000 through 0x00700000 for
44  * section alignments of 1 through 64 bytes.
45  *
46  * (4) Both standard COFF and Win32 COFF seem to use the DWORD
47  * field directly after the section name in the section header
48  * table for something strange: they store what the address of the
49  * section start point _would_ be, if you laid all the sections end
50  * to end starting at zero. Dunno why. Microsoft's documentation
51  * lists this field as "Virtual Size of Section", which doesn't
52  * seem to fit at all. In fact, Win32 even includes non-linked
53  * sections such as .drectve in this calculation.
54  *
55  * (5) Standard COFF does something very strange to common
56  * variables: the relocation point for a common variable is as far
57  * _before_ the variable as its size stretches out _after_ it. So
58  * we must fix up common variable references. Win32 seems to be
59  * sensible on this one.
60  */
61
62 /* Flag which version of COFF we are currently outputting. */
63 static int win32;
64
65 struct Reloc {
66     struct Reloc *next;
67     long address;                      /* relative to _start_ of section */
68     long symbol;                       /* symbol number */
69     enum {
70         SECT_SYMBOLS,
71         ABS_SYMBOL,
72         REAL_SYMBOLS
73     } symbase;                         /* relocation for symbol number :) */
74     int relative;                      /* TRUE or FALSE */
75 };
76
77 struct Symbol {
78     char name[9];
79     long strpos;                       /* string table position of name */
80     int section;                       /* section number where it's defined
81                                         * - in COFF codes, not NASM codes */
82     int is_global;                     /* is it a global symbol or not? */
83     long value;                        /* address, or COMMON variable size */
84 };
85
86 static FILE *coffp;
87 static efunc error;
88 static char coff_infile[FILENAME_MAX];
89
90 struct Section {
91     struct SAA *data;
92     unsigned long len;
93     int nrelocs;
94     long index;
95     struct Reloc *head, **tail;
96     unsigned long flags;               /* section flags */
97     char name[9];
98     long pos, relpos;
99 };
100
101 #define TEXT_FLAGS (win32 ? 0x60500020L : 0x20L)
102 #define DATA_FLAGS (win32 ? 0xC0300040L : 0x40L)
103 #define BSS_FLAGS (win32 ? 0xC0300080L : 0x80L)
104 #define INFO_FLAGS 0x00100A00L
105 #define RDATA_FLAGS (win32 ? 0x40400040L : 0x40L)
106
107 #define SECT_DELTA 32
108 static struct Section **sects;
109 static int nsects, sectlen;
110
111 static struct SAA *syms;
112 static unsigned long nsyms;
113
114 static long def_seg;
115
116 static int initsym;
117
118 static struct RAA *bsym, *symval;
119
120 static struct SAA *strs;
121 static unsigned long strslen;
122
123 static void coff_gen_init(FILE *, efunc);
124 static void coff_sect_write (struct Section *, unsigned char *,
125                              unsigned long);
126 static void coff_write (void);
127 static void coff_section_header (char *, long, long, long, long, int, long);
128 static void coff_write_relocs (struct Section *);
129 static void coff_write_symbols (void);
130
131 static void coff_win32_init(FILE *fp,  efunc errfunc,
132                             ldfunc ldef, evalfunc eval) 
133 {
134     win32 = TRUE;
135     (void) ldef;                       /* placate optimisers */
136     coff_gen_init(fp, errfunc);
137 }
138
139 static void coff_std_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
140 {
141     win32 = FALSE;
142     (void) ldef;                       /* placate optimisers */
143     coff_gen_init(fp, errfunc);
144 }
145
146 static void coff_gen_init(FILE *fp, efunc errfunc) 
147 {
148
149     coffp = fp;
150     error = errfunc;
151     sects = NULL;
152     nsects = sectlen = 0;
153     syms = saa_init((long)sizeof(struct Symbol));
154     nsyms = 0;
155     bsym = raa_init();
156     symval = raa_init();
157     strs = saa_init(1L);
158     strslen = 0;
159     def_seg = seg_alloc();
160 }
161
162 static void coff_cleanup(int debuginfo) 
163 {
164     struct Reloc *r;
165     int i;
166
167     (void) debuginfo;
168
169     coff_write();
170     fclose (coffp);
171     for (i=0; i<nsects; i++) {
172         if (sects[i]->data)
173             saa_free (sects[i]->data);
174         while (sects[i]->head) {
175             r = sects[i]->head;
176             sects[i]->head = sects[i]->head->next;
177             nasm_free (r);
178         }
179         nasm_free (sects[i]);
180     }
181     nasm_free (sects);
182     saa_free (syms);
183     raa_free (bsym);
184     raa_free (symval);
185     saa_free (strs);
186 }
187
188 static int coff_make_section (char *name, unsigned long flags) 
189 {
190     struct Section *s;
191
192     s = nasm_malloc (sizeof(*s));
193
194     if (flags != BSS_FLAGS)
195         s->data = saa_init (1L);
196     else
197         s->data = NULL;
198     s->head = NULL;
199     s->tail = &s->head;
200     s->len = 0;
201     s->nrelocs = 0;
202     if (!strcmp(name, ".text"))
203         s->index = def_seg;
204     else
205         s->index = seg_alloc();
206     strncpy (s->name, name, 8);
207     s->name[8] = '\0';
208     s->flags = flags;
209
210     if (nsects >= sectlen)
211         sects = nasm_realloc (sects, (sectlen += SECT_DELTA)*sizeof(*sects));
212     sects[nsects++] = s;
213
214     return nsects-1;
215 }
216
217 static long coff_section_names (char *name, int pass, int *bits) 
218 {
219     char *p;
220     unsigned long flags, align_and = ~0L, align_or = 0L;
221     int i;
222
223     /*
224      * Default is 32 bits.
225      */
226     if (!name)
227         *bits = 32;
228
229     if (!name)
230         return def_seg;
231
232     p = name;
233     while (*p && !isspace(*p)) p++;
234     if (*p) *p++ = '\0';
235     if (strlen(name) > 8) {
236         error (ERR_WARNING, "COFF section names limited to 8 characters:"
237                " truncating");
238         name[8] = '\0';
239     }
240     flags = 0;
241
242     while (*p && isspace(*p)) p++;
243     while (*p) {
244         char *q = p;
245         while (*p && !isspace(*p)) p++;
246         if (*p) *p++ = '\0';
247         while (*p && isspace(*p)) p++;
248
249         if (!nasm_stricmp(q, "code") || !nasm_stricmp(q, "text")) {
250             flags = TEXT_FLAGS;
251         } else if (!nasm_stricmp(q, "data")) {
252             flags = DATA_FLAGS;
253         } else if (!nasm_stricmp(q, "rdata")) {
254             if (win32)
255             flags = RDATA_FLAGS;
256             else {
257                 flags = DATA_FLAGS;    /* gotta do something */
258                 error (ERR_NONFATAL, "standard COFF does not support"
259                        " read-only data sections");
260             }
261         } else if (!nasm_stricmp(q, "bss")) {
262             flags = BSS_FLAGS;
263         } else if (!nasm_stricmp(q, "info")) {
264             if (win32)
265                 flags = INFO_FLAGS;
266             else {
267                 flags = DATA_FLAGS;    /* gotta do something */
268                 error (ERR_NONFATAL, "standard COFF does not support"
269                        " informational sections");
270             }
271         } else if (!nasm_strnicmp(q,"align=",6)) {
272             if (!win32)
273                 error (ERR_NONFATAL, "standard COFF does not support"
274                        " section alignment specification");
275             else {
276                 if (q[6+strspn(q+6,"0123456789")])
277                     error(ERR_NONFATAL, "argument to `align' is not numeric");
278                 else {
279                     unsigned int align = atoi(q+6);
280                     if (!align || ((align-1) & align))
281                         error(ERR_NONFATAL, "argument to `align' is not a"
282                               " power of two");
283                     else if (align > 64)
284                         error(ERR_NONFATAL, "Win32 cannot align sections"
285                               " to better than 64-byte boundaries");
286                     else {
287                         align_and = ~0x00F00000L;
288                         align_or = (align == 1 ? 0x00100000L :
289                                     align == 2 ? 0x00200000L :
290                                     align == 4 ? 0x00300000L :
291                                     align == 8 ? 0x00400000L :
292                                     align == 16 ? 0x00500000L :
293                                     align == 32 ? 0x00600000L : 0x00700000L);
294                     }
295                 }
296             }
297         }
298     }
299
300     for (i=0; i<nsects; i++)
301         if (!strcmp(name, sects[i]->name))
302             break;
303     if (i == nsects) {
304         if (!flags) {
305             if (!strcmp(name, ".data"))
306                 flags = DATA_FLAGS;
307             else if (!strcmp(name, ".rdata"))
308                 flags = RDATA_FLAGS;
309             else if (!strcmp(name, ".bss"))
310                 flags = BSS_FLAGS;
311             else
312                 flags = TEXT_FLAGS;
313         }
314         i = coff_make_section (name, flags);
315         if (flags)
316             sects[i]->flags = flags;
317         sects[i]->flags &= align_and;
318         sects[i]->flags |= align_or;
319     } else if (pass == 1) {
320         if (flags)
321             error (ERR_WARNING, "section attributes ignored on"
322                    " redeclaration of section `%s'", name);
323     }
324
325     return sects[i]->index;
326 }
327
328 static void coff_deflabel (char *name, long segment, long offset,
329                            int is_global, char *special) 
330 {
331     int pos = strslen+4;
332     struct Symbol *sym;
333
334     if (special)
335         error (ERR_NONFATAL, "binary format does not support any"
336                " special symbol types");
337
338     if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
339         error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
340         return;
341     }
342
343     if (strlen(name) > 8) {
344         saa_wbytes (strs, name, (long)(1+strlen(name)));
345         strslen += 1+strlen(name);
346     } else
347         pos = -1;
348
349     sym = saa_wstruct (syms);
350
351     sym->strpos = pos;
352     if (pos == -1)
353         strcpy (sym->name, name);
354     sym->is_global = !!is_global;
355     if (segment == NO_SEG)
356         sym->section = -1;      /* absolute symbol */
357     else {
358         int i;
359         sym->section = 0;
360         for (i=0; i<nsects; i++)
361             if (segment == sects[i]->index) {
362                 sym->section = i+1;
363                 break;
364             }
365         if (!sym->section)
366             sym->is_global = TRUE;
367     }
368     if (is_global == 2)
369         sym->value = offset;
370     else
371         sym->value = (sym->section == 0 ? 0 : offset);
372
373     /*
374      * define the references from external-symbol segment numbers
375      * to these symbol records.
376      */
377     if (sym->section == 0)
378         bsym = raa_write (bsym, segment, nsyms);
379
380     if (segment != NO_SEG)
381         symval = raa_write (symval, segment, sym->section ? 0 : sym->value);
382
383     nsyms++;
384 }
385
386 static long coff_add_reloc (struct Section *sect, long segment,
387                             int relative) 
388 {
389     struct Reloc *r;
390
391     r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
392     sect->tail = &r->next;
393     r->next = NULL;
394
395     r->address = sect->len;
396     if (segment == NO_SEG)
397         r->symbol = 0, r->symbase = ABS_SYMBOL;
398     else {
399         int i;
400         r->symbase = REAL_SYMBOLS;
401         for (i=0; i<nsects; i++)
402             if (segment == sects[i]->index) {
403                 r->symbol = i*2;
404                 r->symbase = SECT_SYMBOLS;
405                 break;
406             }
407         if (r->symbase == REAL_SYMBOLS)
408             r->symbol = raa_read (bsym, segment);
409     }
410     r->relative = relative;
411
412     sect->nrelocs++;
413
414     /*
415      * Return the fixup for standard COFF common variables.
416      */
417     if (r->symbase == REAL_SYMBOLS && !win32)
418         return raa_read (symval, segment);
419     else
420         return 0;
421 }
422
423 static void coff_out (long segto, void *data, unsigned long type,
424                       long segment, long wrt) 
425 {
426     struct Section *s;
427     long realbytes = type & OUT_SIZMASK;
428     unsigned char mydata[4], *p;
429     int i;
430
431     if (wrt != NO_SEG) {
432         wrt = NO_SEG;                  /* continue to do _something_ */
433         error (ERR_NONFATAL, "WRT not supported by COFF output formats");
434     }
435
436     type &= OUT_TYPMASK;
437
438     /*
439      * handle absolute-assembly (structure definitions)
440      */
441     if (segto == NO_SEG) {
442         if (type != OUT_RESERVE)
443             error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
444                    " space");
445         return;
446     }
447
448     s = NULL;
449     for (i=0; i<nsects; i++)
450         if (segto == sects[i]->index) {
451             s = sects[i];
452             break;
453         }
454     if (!s) {
455         int tempint;                   /* ignored */
456         if (segto != coff_section_names (".text", 2, &tempint))
457             error (ERR_PANIC, "strange segment conditions in COFF driver");
458         else
459             s = sects[nsects-1];
460     }
461
462     if (!s->data && type != OUT_RESERVE) {
463         error(ERR_WARNING, "attempt to initialise memory in"
464               " BSS section `%s': ignored", s->name);
465         if (type == OUT_REL2ADR)
466             realbytes = 2;
467         else if (type == OUT_REL4ADR)
468             realbytes = 4;
469         s->len += realbytes;
470         return;
471     }
472
473     if (type == OUT_RESERVE) {
474         if (s->data) {
475             error(ERR_WARNING, "uninitialised space declared in"
476                   " non-BSS section `%s': zeroing", s->name);
477             coff_sect_write (s, NULL, realbytes);
478         } else
479             s->len += realbytes;
480     } else if (type == OUT_RAWDATA) {
481         if (segment != NO_SEG)
482             error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
483         coff_sect_write (s, data, realbytes);
484     } else if (type == OUT_ADDRESS) {
485         if (realbytes != 4 && (segment != NO_SEG || wrt != NO_SEG))
486             error(ERR_NONFATAL, "COFF format does not support non-32-bit"
487                   " relocations");
488         else {
489             long fix = 0;
490             if (segment != NO_SEG || wrt != NO_SEG) {
491                 if (wrt != NO_SEG) {
492                     error(ERR_NONFATAL, "COFF format does not support"
493                           " WRT types");
494                 } else if (segment % 2) {
495                     error(ERR_NONFATAL, "COFF format does not support"
496                           " segment base references");
497                 } else
498                     fix = coff_add_reloc (s, segment, FALSE);
499             }
500             p = mydata;
501             WRITELONG (p, *(long *)data + fix);
502             coff_sect_write (s, mydata, realbytes);
503         }
504     } else if (type == OUT_REL2ADR) {
505         error(ERR_NONFATAL, "COFF format does not support 16-bit"
506               " relocations");
507     } else if (type == OUT_REL4ADR) {
508         if (segment == segto)
509             error(ERR_PANIC, "intra-segment OUT_REL4ADR");
510         else if (segment == NO_SEG && win32)
511             error(ERR_NONFATAL, "Win32 COFF does not correctly support"
512                   " relative references to absolute addresses");
513         else {
514             long fix = 0;
515             if (segment != NO_SEG && segment % 2) {
516                 error(ERR_NONFATAL, "COFF format does not support"
517                       " segment base references");
518             } else
519                 fix = coff_add_reloc (s, segment, TRUE);
520             p = mydata;
521             if (win32) {
522                 WRITELONG (p, *(long*)data + 4 - realbytes + fix);
523             } else {
524                 WRITELONG (p, *(long*)data-(realbytes + s->len) + fix);
525             }
526             coff_sect_write (s, mydata, 4L);
527         }
528     }
529 }
530
531 static void coff_sect_write (struct Section *sect,
532                              unsigned char *data, unsigned long len) 
533 {
534     saa_wbytes (sect->data, data, len);
535     sect->len += len;
536 }
537
538 static int coff_directives (char *directive, char *value, int pass) 
539 {
540     return 0;
541 }
542
543 static void coff_write (void) 
544 {
545     long pos, sympos, vsize;
546     int i;
547
548     /*
549      * Work out how big the file will get. Calculate the start of
550      * the `real' symbols at the same time.
551      */
552     pos = 0x14 + 0x28 * nsects;
553     initsym = 3;                       /* two for the file, one absolute */
554     for (i=0; i<nsects; i++) {
555         if (sects[i]->data) {
556             sects[i]->pos = pos;
557             pos += sects[i]->len;
558             sects[i]->relpos = pos;
559             pos += 10 * sects[i]->nrelocs;
560         } else
561             sects[i]->pos = sects[i]->relpos = 0L;
562         initsym += 2;                  /* two for each section */
563     }
564     sympos = pos;
565
566     /*
567      * Output the COFF header.
568      */
569     fwriteshort (0x14C, coffp);        /* MACHINE_i386 */
570     fwriteshort (nsects, coffp);       /* number of sections */
571     fwritelong (time(NULL), coffp);    /* time stamp */
572     fwritelong (sympos, coffp);
573     fwritelong (nsyms + initsym, coffp);
574     fwriteshort (0, coffp);            /* no optional header */
575     /* Flags: 32-bit, no line numbers. Win32 doesn't even bother with them. */
576     fwriteshort (win32 ? 0 : 0x104, coffp);
577
578     /*
579      * Output the section headers.
580      */
581     vsize = 0L;
582     for (i=0; i<nsects; i++) {
583         coff_section_header (sects[i]->name, vsize, sects[i]->len,
584                              sects[i]->pos, sects[i]->relpos,
585                              sects[i]->nrelocs, sects[i]->flags);
586         vsize += sects[i]->len;
587     }
588
589     /*
590      * Output the sections and their relocations.
591      */
592     for (i=0; i<nsects; i++)
593         if (sects[i]->data) {
594             saa_fpwrite (sects[i]->data, coffp);
595             coff_write_relocs (sects[i]);
596         }
597
598     /*
599      * Output the symbol and string tables.
600      */
601     coff_write_symbols();
602     fwritelong (strslen+4, coffp);     /* length includes length count */
603     saa_fpwrite (strs, coffp);
604 }
605
606 static void coff_section_header (char *name, long vsize,
607                                  long datalen, long datapos,
608                                  long relpos, int nrelocs, long flags) 
609 {
610     char padname[8];
611
612     memset (padname, 0, 8);
613     strncpy (padname, name, 8);
614     fwrite (padname, 8, 1, coffp);
615     fwritelong (vsize, coffp);
616     fwritelong (0L, coffp);            /* RVA/offset - we ignore */
617     fwritelong (datalen, coffp);
618     fwritelong (datapos, coffp);
619     fwritelong (relpos, coffp);
620     fwritelong (0L, coffp);            /* no line numbers - we don't do 'em */
621     fwriteshort (nrelocs, coffp);
622     fwriteshort (0, coffp);            /* again, no line numbers */
623     fwritelong (flags, coffp);
624 }
625
626 static void coff_write_relocs (struct Section *s) 
627 {
628     struct Reloc *r;
629
630     for (r = s->head; r; r = r->next) {
631         fwritelong (r->address, coffp);
632         fwritelong (r->symbol + (r->symbase == REAL_SYMBOLS ? initsym :
633                                  r->symbase == ABS_SYMBOL ? initsym-1 :
634                                  r->symbase == SECT_SYMBOLS ? 2 : 0), coffp);
635         /*
636          * Strange: Microsoft's COFF documentation says 0x03 for an
637          * absolute relocation, but both Visual C++ and DJGPP agree
638          * that in fact it's 0x06. I'll use 0x06 until someone
639          * argues.
640          */
641         fwriteshort (r->relative ? 0x14 : 0x06, coffp);
642     }
643 }
644
645 static void coff_symbol (char *name, long strpos, long value,
646                          int section, int type, int aux) 
647 {
648     char padname[8];
649
650     if (name) {
651         memset (padname, 0, 8);
652         strncpy (padname, name, 8);
653         fwrite (padname, 8, 1, coffp);
654     } else {
655         fwritelong (0L, coffp);
656         fwritelong (strpos, coffp);
657     }
658     fwritelong (value, coffp);
659     fwriteshort (section, coffp);
660     fwriteshort (0, coffp);
661     fputc (type, coffp);
662     fputc (aux, coffp);
663 }
664
665 static void coff_write_symbols (void)
666 {
667     char filename[18];
668     unsigned long i;
669
670     /*
671      * The `.file' record, and the file name auxiliary record.
672      */
673     coff_symbol (".file", 0L, 0L, -2, 0x67, 1);
674     memset (filename, 0, 18);
675     strncpy (filename, coff_infile, 18);
676     fwrite (filename, 18, 1, coffp);
677
678     /*
679      * The section records, with their auxiliaries.
680      */
681     memset (filename, 0, 18);          /* useful zeroed buffer */
682
683     for (i = 0; i < nsects; i++) {
684         coff_symbol (sects[i]->name, 0L, 0L, i+1, 3, 1);
685         fwritelong (sects[i]->len, coffp);
686         fwriteshort (sects[i]->nrelocs, coffp);
687         fwrite (filename, 12, 1, coffp);
688     }
689
690     /*
691      * The absolute symbol, for relative-to-absolute relocations.
692      */
693     coff_symbol (".absolut", 0L, 0L, -1, 3, 0);
694
695     /*
696      * The real symbols.
697      */
698     saa_rewind (syms);
699     for (i = 0; i < nsyms; i++) {
700         struct Symbol *sym = saa_rstruct (syms);
701         coff_symbol (sym->strpos == -1 ? sym->name : NULL,
702                      sym->strpos, sym->value, sym->section,
703                      sym->is_global ? 2 : 3, 0);
704     }
705 }
706
707 static long coff_segbase (long segment) 
708 {
709     return segment;
710 }
711
712 static void coff_std_filename (char *inname, char *outname, efunc error) 
713 {
714     strcpy(coff_infile, inname);
715     standard_extension (inname, outname, ".o", error);
716 }
717
718 static void coff_win32_filename (char *inname, char *outname, efunc error) 
719 {
720     strcpy(coff_infile, inname);
721     standard_extension (inname, outname, ".obj", error);
722 }
723
724 static char *coff_stdmac[] = {
725     "%define __SECT__ [section .text]",
726     "%macro __NASM_CDecl__ 1",
727     "%endmacro",
728     NULL
729 };
730
731 static int coff_set_info(enum geninfo type, char **val)
732 {
733     return 0;
734 }
735 #endif /* defined(OF_COFF) || defined(OF_WIN32) */
736
737 #ifdef OF_COFF
738
739 struct ofmt of_coff = {
740     "COFF (i386) object files (e.g. DJGPP for DOS)",
741     "coff",
742     NULL,
743     null_debug_arr,
744     &null_debug_form,
745     coff_stdmac,
746     coff_std_init,
747     coff_set_info,
748     coff_out,
749     coff_deflabel,
750     coff_section_names,
751     coff_segbase,
752     coff_directives,
753     coff_std_filename,
754     coff_cleanup
755 };
756
757 #endif
758
759 #ifdef OF_WIN32
760
761 struct ofmt of_win32 = {
762     "Microsoft Win32 (i386) object files",
763     "win32",
764     NULL,
765     null_debug_arr,
766     &null_debug_form,
767     coff_stdmac,
768     coff_win32_init,
769     coff_set_info,
770     coff_out,
771     coff_deflabel,
772     coff_section_names,
773     coff_segbase,
774     coff_directives,
775     coff_win32_filename,
776     coff_cleanup
777 };
778
779 #endif