1 /* LTO routines for COFF object files.
2 Copyright 2009 Free Software Foundation, Inc.
3 Contributed by Dave Korn.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "libiberty.h"
29 #include "lto-streamer.h"
30 #include "lto/lto-coff.h"
33 /* Rather than implementing a libcoff to match libelf, or attempting to
34 integrate libbfd into GCC, this file is a self-contained (and very
35 minimal) COFF format object file reader/writer. The generated files
36 will contain a COFF header, a number of COFF section headers, the
37 section data itself, and a trailing string table for section names. */
39 /* Handle opening elf files on hosts, such as Windows, that may use
40 text file handling that will break binary access. */
46 /* Known header magics for validation, as an array. */
48 static const unsigned int coff_machine_array
[] = COFF_KNOWN_MACHINES
;
50 /* Number of valid entries (no sentinel) in array. */
52 #define NUM_COFF_KNOWN_MACHINES \
53 (sizeof (coff_machine_array) / sizeof (coff_machine_array[0]))
55 /* Cached object file header. */
57 static Coff_header cached_coff_hdr
;
59 /* Flag to indicate if we have read and cached any header yet. */
61 static bool cached_coff_hdr_valid
= false;
63 /* The current output file. */
65 static lto_file
*current_out_file
;
68 /* Sets the current output file to FILE. Returns the old output file or
72 lto_set_current_out_file (lto_file
*file
)
74 lto_file
*old_file
= current_out_file
;
75 current_out_file
= file
;
80 /* Returns the current output file. */
83 lto_get_current_out_file (void)
85 return current_out_file
;
89 /* COFF section structure constructor. */
91 static lto_coff_section
*
92 coff_newsection (lto_coff_file
*file
, const char *name
, size_t type
)
94 lto_coff_section
*ptr
, **chain_ptr_ptr
;
96 ptr
= XCNEW (lto_coff_section
);
100 chain_ptr_ptr
= &file
->section_chain
;
101 while (*chain_ptr_ptr
)
102 chain_ptr_ptr
= &(*chain_ptr_ptr
)->next
;
103 *chain_ptr_ptr
= ptr
;
109 /* COFF section data block structure constructor. */
111 static lto_coff_data
*
112 coff_newdata (lto_coff_section
*sec
)
114 lto_coff_data
*ptr
, **chain_ptr_ptr
;
116 ptr
= XCNEW (lto_coff_data
);
118 chain_ptr_ptr
= &sec
->data_chain
;
119 while (*chain_ptr_ptr
)
120 chain_ptr_ptr
= &(*chain_ptr_ptr
)->next
;
121 *chain_ptr_ptr
= ptr
;
127 /* Initialize FILE, an LTO file object for FILENAME. */
130 lto_file_init (lto_file
*file
, const char *filename
, off_t offset
)
132 file
->filename
= filename
;
133 file
->offset
= offset
;
136 /* Return an error string after an error, or a predetermined one
137 if ERRCODE is not -1. */
140 coff_errmsg (int errcode
)
142 return strerror (errcode
== -1 ? errno
: errcode
);
145 /* Returns a hash code for P. */
148 hash_name (const void *p
)
150 const struct lto_section_slot
*ds
= (const struct lto_section_slot
*) p
;
151 return (hashval_t
) htab_hash_string (ds
->name
);
154 /* Returns nonzero if P1 and P2 are equal. */
157 eq_name (const void *p1
, const void *p2
)
159 const struct lto_section_slot
*s1
=
160 (const struct lto_section_slot
*) p1
;
161 const struct lto_section_slot
*s2
=
162 (const struct lto_section_slot
*) p2
;
164 return strcmp (s1
->name
, s2
->name
) == 0;
168 /* Build a hash table whose key is the section names and whose data is
169 the start and size of each section in the .o file. */
172 lto_obj_build_section_table (lto_file
*lto_file
)
174 lto_coff_file
*coff_file
= (lto_coff_file
*)lto_file
;
175 lto_coff_section
*sec
;
176 htab_t section_hash_table
;
180 section_hash_table
= htab_create (37, hash_name
, eq_name
, free
);
182 /* Seek to start of string table. */
183 if (coff_file
->strtab_offs
!= lseek (coff_file
->fd
,
184 coff_file
->base
.offset
+ coff_file
->strtab_offs
, SEEK_SET
))
186 error ("altered or invalid COFF object file");
187 return section_hash_table
;
190 strtab_size
= coff_file
->file_size
- coff_file
->strtab_offs
;
191 strtab
= XNEWVEC (char, strtab_size
);
192 if (read (coff_file
->fd
, strtab
, strtab_size
) != strtab_size
)
194 error ("invalid COFF object file string table");
195 return section_hash_table
;
198 /* Scan sections looking at names. */
199 COFF_FOR_ALL_SECTIONS(coff_file
, sec
)
201 struct lto_section_slot s_slot
;
205 char *name
= (char *) &sec
->coffsec
.Name
[0];
207 /* Skip dummy string section if by any chance we see it. */
213 if (1 != sscanf (&name
[1], "%d", &stringoffset
)
214 || stringoffset
< 0 || stringoffset
>= strtab_size
)
216 error ("invalid COFF section name string");
219 name
= strtab
+ stringoffset
;
223 /* If we cared about the VirtualSize field, we couldn't
224 crudely trash it like this to guarantee nul-termination
225 of the Name field. But we don't, so we do. */
228 if (strncmp (name
, LTO_SECTION_NAME_PREFIX
,
229 strlen (LTO_SECTION_NAME_PREFIX
)) != 0)
232 new_name
= XNEWVEC (char, strlen (name
) + 1);
233 strcpy (new_name
, name
);
234 s_slot
.name
= new_name
;
235 slot
= htab_find_slot (section_hash_table
, &s_slot
, INSERT
);
238 struct lto_section_slot
*new_slot
= XNEW (struct lto_section_slot
);
240 new_slot
->name
= new_name
;
241 /* The offset into the file for this section. */
242 new_slot
->start
= coff_file
->base
.offset
243 + COFF_GET(&sec
->coffsec
,PointerToRawData
);
244 new_slot
->len
= COFF_GET(&sec
->coffsec
,SizeOfRawData
);
249 error ("two or more sections for %s:", new_name
);
255 return section_hash_table
;
259 /* Begin a new COFF section named NAME with type TYPE in the current output
260 file. TYPE is an SHT_* macro from the libelf headers. */
263 lto_coff_begin_section_with_type (const char *name
, size_t type
)
268 /* Grab the current output file and do some basic assertion checking. */
269 file
= (lto_coff_file
*) lto_get_current_out_file (),
271 gcc_assert (!file
->scn
);
273 /* Create a new section. */
274 file
->scn
= coff_newsection (file
, name
, type
);
276 fatal_error ("could not create a new COFF section: %s", coff_errmsg (-1));
278 /* Add a string table entry and record the offset. */
279 gcc_assert (file
->shstrtab_stream
);
280 sh_name
= file
->shstrtab_stream
->total_size
;
281 lto_output_data_stream (file
->shstrtab_stream
, name
, strlen (name
) + 1);
283 /* Initialize the section header. */
284 file
->scn
->strtab_offs
= sh_name
;
288 /* Begin a new COFF section named NAME in the current output file. */
291 lto_obj_begin_section (const char *name
)
293 lto_coff_begin_section_with_type (name
, 0);
297 /* Append DATA of length LEN to the current output section. BASE is a pointer
298 to the output page containing DATA. It is freed once the output file has
302 lto_obj_append_data (const void *data
, size_t len
, void *block
)
305 lto_coff_data
*coff_data
;
306 struct lto_char_ptr_base
*base
= (struct lto_char_ptr_base
*) block
;
308 /* Grab the current output file and do some basic assertion checking. */
309 file
= (lto_coff_file
*) lto_get_current_out_file ();
311 gcc_assert (file
->scn
);
313 coff_data
= coff_newdata (file
->scn
);
315 fatal_error ("could not append data to COFF section: %s", coff_errmsg (-1));
317 coff_data
->d_buf
= CONST_CAST (void *, data
);
318 coff_data
->d_size
= len
;
320 /* Chain all data blocks (from all sections) on one singly-linked
321 list for freeing en masse after the file is closed. */
322 base
->ptr
= (char *)file
->data
;
327 /* End the current output section. This just does some assertion checking
328 and sets the current output file's scn member to NULL. */
331 lto_obj_end_section (void)
335 /* Grab the current output file and validate some basic assertions. */
336 file
= (lto_coff_file
*) lto_get_current_out_file ();
338 gcc_assert (file
->scn
);
344 /* Validate's COFF_FILE's executable header and, if cached_coff_hdr is
345 uninitialized, caches the results. Also records the section header string
346 table's section index. Returns true on success or false on failure. */
349 validate_file (lto_coff_file
*coff_file
)
352 unsigned int numsections
, secheaderssize
, numsyms
;
353 off_t sectionsstart
, symbolsstart
, stringsstart
;
354 unsigned int mach
, charact
;
356 /* Read and sanity check the raw header. */
357 n
= read (coff_file
->fd
, &coff_file
->coffhdr
, sizeof (coff_file
->coffhdr
));
358 if (n
!= sizeof (coff_file
->coffhdr
))
360 error ("not a COFF object file");
364 mach
= COFF_GET(&coff_file
->coffhdr
, Machine
);
365 for (n
= 0; n
< NUM_COFF_KNOWN_MACHINES
; n
++)
366 if (mach
== coff_machine_array
[n
])
368 if (n
== NUM_COFF_KNOWN_MACHINES
)
370 error ("not a recognized COFF object file");
374 charact
= COFF_GET(&coff_file
->coffhdr
, Characteristics
);
375 if (COFF_NOT_CHARACTERISTICS
& charact
)
377 /* DLL, EXE or SYS file. */
378 error ("not a relocatable COFF object file");
382 if (COFF_CHARACTERISTICS
!= (COFF_CHARACTERISTICS
& charact
))
384 /* ECOFF/XCOFF/PE+ support not implemented. */
385 error ("not a 32-bit COFF object file");
389 /* It validated OK, so cached it if we don't already have one. */
390 if (!cached_coff_hdr_valid
)
392 cached_coff_hdr_valid
= true;
393 memcpy (&cached_coff_hdr
, &coff_file
->coffhdr
, sizeof (cached_coff_hdr
));
396 if (mach
!= COFF_GET(&cached_coff_hdr
, Machine
))
398 error ("inconsistent file architecture detected");
402 /* Read section headers and string table? */
404 numsections
= COFF_GET(&coff_file
->coffhdr
, NumberOfSections
);
405 secheaderssize
= numsections
* sizeof (Coff_section
);
406 sectionsstart
= sizeof (Coff_header
) + secheaderssize
;
407 symbolsstart
= COFF_GET(&coff_file
->coffhdr
, PointerToSymbolTable
);
408 numsyms
= COFF_GET(&coff_file
->coffhdr
, NumberOfSymbols
);
409 stringsstart
= (symbolsstart
+ COFF_SYMBOL_SIZE
* numsyms
);
411 #define CVOFFSETTTED(x) (coff_file->base.offset + (x))
413 if (numsections
<= 0 || symbolsstart
<= 0 || numsyms
<= 0
414 || (CVOFFSETTTED(sectionsstart
) >= coff_file
->file_size
)
415 || (CVOFFSETTTED(symbolsstart
) >= coff_file
->file_size
)
416 || (CVOFFSETTTED(stringsstart
) >= coff_file
->file_size
))
418 error ("not a valid COFF object file");
424 /* Record start of string table. */
425 coff_file
->strtab_offs
= stringsstart
;
427 /* Validate section table entries. */
428 for (secnum
= 0; secnum
< numsections
; secnum
++)
430 Coff_section coffsec
;
431 lto_coff_section
*ltosec
;
432 off_t size_raw
, offs_raw
, offs_relocs
, offs_lines
;
433 off_t num_relocs
, num_lines
;
435 n
= read (coff_file
->fd
, &coffsec
, sizeof (coffsec
));
436 if (n
!= sizeof (coffsec
))
438 error ("short/missing COFF section table");
442 size_raw
= COFF_GET(&coffsec
, SizeOfRawData
);
443 offs_raw
= COFF_GET(&coffsec
, PointerToRawData
);
444 offs_relocs
= COFF_GET(&coffsec
, PointerToRelocations
);
445 offs_lines
= COFF_GET(&coffsec
, PointerToLinenumbers
);
446 num_relocs
= COFF_GET(&coffsec
, NumberOfRelocations
);
447 num_lines
= COFF_GET(&coffsec
, NumberOfLinenumbers
);
449 if (size_raw
< 0 || num_relocs
< 0 || num_lines
< 0
451 && ((COFF_GET(&coffsec
, Characteristics
)
452 & IMAGE_SCN_CNT_UNINITIALIZED_DATA
)
454 : (offs_raw
< sectionsstart
|| offs_raw
>= coff_file
->file_size
)))
456 && (offs_relocs
< sectionsstart
457 || offs_relocs
>= coff_file
->file_size
))
459 && (offs_lines
< sectionsstart
460 || offs_lines
>= coff_file
->file_size
)))
462 error ("invalid COFF section table");
466 /* Looks ok, so record its details. We don't read the
467 string table or set up names yet; we'll do that when
468 we build the hash table. */
469 ltosec
= coff_newsection (coff_file
, NULL
, 0);
470 memcpy (<osec
->coffsec
, &coffsec
, sizeof (ltosec
->coffsec
));
476 /* Initialize COFF_FILE's executable header using cached data from previously
480 init_coffhdr (lto_coff_file
*coff_file
)
482 gcc_assert (cached_coff_hdr_valid
);
483 memset (&coff_file
->coffhdr
, 0, sizeof (coff_file
->coffhdr
));
484 COFF_PUT(&coff_file
->coffhdr
, Machine
, COFF_GET(&cached_coff_hdr
, Machine
));
485 COFF_PUT(&coff_file
->coffhdr
, Characteristics
, COFF_GET(&cached_coff_hdr
, Characteristics
));
488 /* Open COFF file FILENAME. If WRITABLE is true, the file is opened for write
489 and, if necessary, created. Otherwise, the file is opened for reading.
490 Returns the opened file. */
493 lto_obj_file_open (const char *filename
, bool writable
)
495 lto_coff_file
*coff_file
;
496 lto_file
*result
= NULL
;
498 const char *offset_p
;
502 offset_p
= strchr (filename
, '@');
505 fname
= xstrdup (filename
);
510 /* The file started with '@' is a file containing command line
511 options. Stop if it doesn't exist. */
512 if (offset_p
== filename
)
513 fatal_error ("command line option file '%s' does not exist",
516 fname
= (char *) xmalloc (offset_p
- filename
+ 1);
517 memcpy (fname
, filename
, offset_p
- filename
);
518 fname
[offset_p
- filename
] = '\0';
519 offset_p
+= 3; /* skip the @0x */
520 offset
= lto_parse_hex (offset_p
);
524 coff_file
= XCNEW (lto_coff_file
);
525 result
= (lto_file
*) coff_file
;
526 lto_file_init (result
, fname
, offset
);
530 coff_file
->fd
= open (fname
,
531 O_BINARY
| (writable
? O_WRONLY
| O_CREAT
| O_TRUNC
: O_RDONLY
), 0666);
533 if (coff_file
->fd
== -1)
535 error ("could not open file %s", fname
);
539 if (stat (fname
, &statbuf
) < 0)
541 error ("could not stat file %s", fname
);
545 coff_file
->file_size
= statbuf
.st_size
;
553 gcc_assert (!writable
);
555 /* Seek to offset, or error. */
556 if (lseek (coff_file
->fd
, offset
, SEEK_SET
) != (ssize_t
) offset
)
558 error ("could not find archive member @0x%lx", (long) offset
);
562 /* Now seek back 12 chars and read the tail of the AR header to
563 find the length of the member file. */
564 if (lseek (coff_file
->fd
, -12, SEEK_CUR
) < 0
565 || read (coff_file
->fd
, ar_tail
, 12) != 12
566 || lseek (coff_file
->fd
, 0, SEEK_CUR
) != (ssize_t
) offset
567 || ar_tail
[10] != '`' || ar_tail
[11] != '\n')
569 error ("could not find archive header @0x%lx", (long) offset
);
574 if (sscanf (ar_tail
, "%d", &size
) != 1)
576 error ("invalid archive header @0x%lx", (long) offset
);
579 coff_file
->file_size
= size
;
584 init_coffhdr (coff_file
);
585 coff_file
->shstrtab_stream
= XCNEW (struct lto_output_stream
);
588 if (!validate_file (coff_file
))
595 lto_obj_file_close (result
);
600 /* Close COFF file FILE and clean up any associated data structures. If FILE
601 was opened for writing, the file's COFF data is written at this time, and
602 any cached data buffers are freed. Return TRUE if there was an error. */
605 coff_write_object_file (lto_coff_file
*coff_file
)
607 lto_coff_section
*cursec
, *stringsec
;
609 size_t fileoffset
, numsections
, totalsecsize
, numsyms
, stringssize
;
610 bool write_err
= false;
613 /* Infer whether this file was opened for reading or writing from the
614 presence or absense of an initialised stream for the string table;
615 do nothing if it was opened for reading. */
616 if (!coff_file
->shstrtab_stream
)
620 /* Write the COFF string table into a dummy new section that
621 we will not write a header for. */
622 lto_file
*old_file
= lto_set_current_out_file (&coff_file
->base
);
623 /* This recursively feeds in the data to a new section. */
624 lto_coff_begin_section_with_type (".strtab", 1);
625 lto_write_stream (coff_file
->shstrtab_stream
);
626 lto_obj_end_section ();
627 lto_set_current_out_file (old_file
);
628 free (coff_file
->shstrtab_stream
);
631 /* Layout the file. Count sections (not dummy string section) and calculate
632 data size for all of them. */
637 COFF_FOR_ALL_SECTIONS(coff_file
, cursec
)
642 COFF_FOR_ALL_DATA(cursec
,data
)
643 cursecsize
+= data
->d_size
;
644 if (cursec
->type
== 0)
647 totalsecsize
+= COFF_ALIGN(cursecsize
);
648 #if COFF_ALIGNMENT > 1
649 cursec
->pad_needed
= COFF_ALIGN(cursecsize
) - cursecsize
;
654 stringssize
= cursecsize
;
657 COFF_PUT(&cursec
->coffsec
, SizeOfRawData
, cursecsize
);
660 /* There is a file symbol and a section symbol per section,
661 and each of these has a single auxiliary symbol following. */
662 numsyms
= 2 * (1 + numsections
);
664 /* Great! Now we have enough info to fill out the file header. */
665 COFF_PUT(&coff_file
->coffhdr
, NumberOfSections
, numsections
);
666 COFF_PUT(&coff_file
->coffhdr
, NumberOfSymbols
, numsyms
);
667 COFF_PUT(&coff_file
->coffhdr
, PointerToSymbolTable
, sizeof (Coff_header
)
668 + numsections
* sizeof (Coff_section
) + totalsecsize
);
669 /* The remaining members were initialised to zero or copied from
670 a cached header, so we leave them alone here. */
672 /* Now position all the sections, and fill out their headers. */
673 fileoffset
= sizeof (Coff_header
) + numsections
* sizeof (Coff_section
);
674 COFF_FOR_ALL_SECTIONS(coff_file
, cursec
)
676 /* Skip dummy string section. */
677 if (cursec
->type
== 1)
679 COFF_PUT(&cursec
->coffsec
, PointerToRawData
, fileoffset
);
680 fileoffset
+= COFF_ALIGN (COFF_GET(&cursec
->coffsec
, SizeOfRawData
));
681 COFF_PUT(&cursec
->coffsec
, Characteristics
, COFF_SECTION_CHARACTERISTICS
);
682 snprintf ((char *)&cursec
->coffsec
.Name
[0], 8, "/%d", cursec
->strtab_offs
+ 4);
685 /* We can write the data now. As there's no way to indicate an error return
686 from this hook, error handling is limited to not wasting our time doing
687 any more writes in the event that any one fails. */
689 /* Write the COFF header. */
690 write_err
= (write (coff_file
->fd
, &coff_file
->coffhdr
,
691 sizeof (coff_file
->coffhdr
)) != sizeof (coff_file
->coffhdr
));
693 /* Write the COFF section headers. */
694 COFF_FOR_ALL_SECTIONS(coff_file
, cursec
)
695 if (cursec
->type
== 1) /* Skip dummy string section. */
698 write_err
= (write (coff_file
->fd
, &cursec
->coffsec
,
699 sizeof (cursec
->coffsec
)) != sizeof (cursec
->coffsec
));
703 /* Write the COFF sections. */
704 COFF_FOR_ALL_SECTIONS(coff_file
, cursec
)
706 #if COFF_ALIGNMENT > 1
707 static const char padzeros
[COFF_ALIGNMENT
] = { 0 };
709 /* Skip dummy string section. */
710 if (cursec
->type
== 1)
712 COFF_FOR_ALL_DATA(cursec
, data
)
714 write_err
= (write (coff_file
->fd
, data
->d_buf
, data
->d_size
)
718 #if COFF_ALIGNMENT > 1
719 if (!write_err
&& cursec
->pad_needed
)
720 write_err
= (write (coff_file
->fd
, padzeros
, cursec
->pad_needed
)
721 != cursec
->pad_needed
);
725 /* Write the COFF symbol table. */
731 Coff_aux_sym_file file
;
732 Coff_aux_sym_section sec
;
734 memset (&symbols
[0], 0, sizeof (symbols
));
735 strcpy ((char *) &symbols
[0].sym
.Name
[0], ".file");
736 COFF_PUT(&symbols
[0].sym
, SectionNumber
, IMAGE_SYM_DEBUG
);
737 COFF_PUT(&symbols
[0].sym
, Type
, IMAGE_SYM_TYPE
);
738 symbols
[0].sym
.StorageClass
[0] = IMAGE_SYM_CLASS_FILE
;
739 symbols
[0].sym
.NumberOfAuxSymbols
[0] = 1;
740 snprintf ((char *)symbols
[1].file
.FileName
,
741 sizeof (symbols
[1].file
.FileName
),
742 "%s", lbasename (coff_file
->base
.filename
));
743 write_err
= (write (coff_file
->fd
, &symbols
[0], sizeof (symbols
))
744 != (2 * COFF_SYMBOL_SIZE
));
746 /* Set up constant parts for section sym loop. */
747 memset (&symbols
[0], 0, sizeof (symbols
));
748 COFF_PUT(&symbols
[0].sym
, Type
, IMAGE_SYM_TYPE
);
749 symbols
[0].sym
.StorageClass
[0] = IMAGE_SYM_CLASS_STATIC
;
750 symbols
[0].sym
.NumberOfAuxSymbols
[0] = 1;
754 COFF_FOR_ALL_SECTIONS(coff_file
, cursec
)
756 /* Skip dummy string section. */
757 if (cursec
->type
== 1)
759 /* Reuse section name string for section symbol name. */
760 COFF_PUT_NDXSZ(&symbols
[0].sym
, Name
, 0, 0, 4);
761 COFF_PUT_NDXSZ(&symbols
[0].sym
, Name
, cursec
->strtab_offs
+ 4, 4, 4);
762 COFF_PUT(&symbols
[0].sym
, SectionNumber
, secnum
++);
763 COFF_PUT(&symbols
[1].sec
, Length
,
764 COFF_GET(&cursec
->coffsec
, SizeOfRawData
));
766 write_err
= (write (coff_file
->fd
, &symbols
[0], sizeof (symbols
))
767 != (2 * COFF_SYMBOL_SIZE
));
773 /* Write the COFF string table. */
776 unsigned char outlen
[4];
777 COFF_PUT4(outlen
, stringssize
+ 4);
779 write_err
= (write (coff_file
->fd
, outlen
, 4) != 4);
781 COFF_FOR_ALL_DATA(stringsec
, data
)
783 write_err
= (write (coff_file
->fd
, data
->d_buf
, data
->d_size
)
792 /* Close COFF file FILE and clean up any associated data structures. If FILE
793 was opened for writing, the file's COFF data is written at this time, and
794 any cached data buffers are freed. */
797 lto_obj_file_close (lto_file
*file
)
799 lto_coff_file
*coff_file
= (lto_coff_file
*) file
;
800 struct lto_char_ptr_base
*cur
, *tmp
;
801 lto_coff_section
*cursec
, *nextsec
;
802 bool write_err
= false;
804 /* Write the COFF string table into a dummy new section that
805 we will not write a header for. */
806 if (coff_file
->shstrtab_stream
)
807 coff_write_object_file (coff_file
);
809 /* Close the file, we're done. */
810 if (coff_file
->fd
!= -1)
811 close (coff_file
->fd
);
813 /* Free any data buffers. */
814 cur
= coff_file
->data
;
818 cur
= (struct lto_char_ptr_base
*) cur
->ptr
;
822 /* Free any sections and their data chains. */
823 cursec
= coff_file
->section_chain
;
826 lto_coff_data
*curdata
, *nextdata
;
827 nextsec
= cursec
->next
;
828 curdata
= cursec
->data_chain
;
831 nextdata
= curdata
->next
;
841 /* If there was an error, mention it. */
843 error ("I/O error writing COFF output file");