Fix unused warnings.
[official-gcc/graphite-test-results.git] / gcc / lto / lto-coff.c
blobf5aaff8bcaaa685145e5a2eb160cdb782076db36
1 /* LTO routines for COFF object files.
2 Copyright 2009, 2010 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
10 version.
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
15 for more details.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "diagnostic-core.h"
25 #include "toplev.h"
26 #include "lto.h"
27 #include "tm.h"
28 #include "libiberty.h"
29 #include "ggc.h"
30 #include "lto-streamer.h"
31 #include "lto/lto-coff.h"
34 /* Rather than implementing a libcoff to match libelf, or attempting to
35 integrate libbfd into GCC, this file is a self-contained (and very
36 minimal) COFF format object file reader/writer. The generated files
37 will contain a COFF header, a number of COFF section headers, the
38 section data itself, and a trailing string table for section names. */
40 /* Handle opening elf files on hosts, such as Windows, that may use
41 text file handling that will break binary access. */
43 #ifndef O_BINARY
44 #define O_BINARY 0
45 #endif
47 /* Known header magics for validation, as an array. */
49 static const unsigned int coff_machine_array[] = COFF_KNOWN_MACHINES;
51 /* Number of valid entries (no sentinel) in array. */
53 #define NUM_COFF_KNOWN_MACHINES \
54 (sizeof (coff_machine_array) / sizeof (coff_machine_array[0]))
56 /* Cached object file header. */
58 static Coff_header cached_coff_hdr;
60 /* Flag to indicate if we have read and cached any header yet. */
62 static bool cached_coff_hdr_valid = false;
64 /* The current output file. */
66 static lto_file *current_out_file;
69 /* Sets the current output file to FILE. Returns the old output file or
70 NULL. */
72 lto_file *
73 lto_set_current_out_file (lto_file *file)
75 lto_file *old_file = current_out_file;
76 current_out_file = file;
77 return old_file;
81 /* Returns the current output file. */
83 lto_file *
84 lto_get_current_out_file (void)
86 return current_out_file;
90 /* COFF section structure constructor. */
92 static lto_coff_section *
93 coff_newsection (lto_coff_file *file, const char *name, size_t type)
95 lto_coff_section *ptr, **chain_ptr_ptr;
97 ptr = XCNEW (lto_coff_section);
98 ptr->name = name;
99 ptr->type = type;
101 chain_ptr_ptr = &file->section_chain;
102 while (*chain_ptr_ptr)
103 chain_ptr_ptr = &(*chain_ptr_ptr)->next;
104 *chain_ptr_ptr = ptr;
106 return ptr;
110 /* COFF section data block structure constructor. */
112 static lto_coff_data *
113 coff_newdata (lto_coff_section *sec)
115 lto_coff_data *ptr, **chain_ptr_ptr;
117 ptr = XCNEW (lto_coff_data);
119 chain_ptr_ptr = &sec->data_chain;
120 while (*chain_ptr_ptr)
121 chain_ptr_ptr = &(*chain_ptr_ptr)->next;
122 *chain_ptr_ptr = ptr;
124 return ptr;
128 /* Initialize FILE, an LTO file object for FILENAME. */
130 static void
131 lto_file_init (lto_file *file, const char *filename, off_t offset)
133 file->filename = filename;
134 file->offset = offset;
137 /* Build a hash table whose key is the section names and whose data is
138 the start and size of each section in the .o file. */
140 htab_t
141 lto_obj_build_section_table (lto_file *lto_file)
143 lto_coff_file *coff_file = (lto_coff_file *)lto_file;
144 lto_coff_section *sec;
145 htab_t section_hash_table;
146 ssize_t strtab_size;
147 char *strtab;
149 section_hash_table = lto_obj_create_section_hash_table ();
151 /* Seek to start of string table. */
152 if (coff_file->strtab_offs != lseek (coff_file->fd,
153 coff_file->base.offset + coff_file->strtab_offs, SEEK_SET))
155 error ("altered or invalid COFF object file");
156 return section_hash_table;
159 strtab_size = coff_file->file_size - coff_file->strtab_offs;
160 strtab = XNEWVEC (char, strtab_size);
161 if (read (coff_file->fd, strtab, strtab_size) != strtab_size)
163 error ("invalid COFF object file string table");
164 return section_hash_table;
167 /* Scan sections looking at names. */
168 COFF_FOR_ALL_SECTIONS(coff_file, sec)
170 struct lto_section_slot s_slot;
171 void **slot;
172 char *new_name;
173 int stringoffset;
174 char *name = (char *) &sec->coffsec.Name[0];
176 /* Skip dummy string section if by any chance we see it. */
177 if (sec->type == 1)
178 continue;
180 if (name[0] == '/')
182 if (1 != sscanf (&name[1], "%d", &stringoffset)
183 || stringoffset < 0 || stringoffset >= strtab_size)
185 error ("invalid COFF section name string");
186 continue;
188 name = strtab + stringoffset;
190 else
192 /* If we cared about the VirtualSize field, we couldn't
193 crudely trash it like this to guarantee nul-termination
194 of the Name field. But we don't, so we do. */
195 name[8] = 0;
197 if (strncmp (name, LTO_SECTION_NAME_PREFIX,
198 strlen (LTO_SECTION_NAME_PREFIX)) != 0)
199 continue;
201 new_name = XNEWVEC (char, strlen (name) + 1);
202 strcpy (new_name, name);
203 s_slot.name = new_name;
204 slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
205 if (*slot == NULL)
207 struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
209 new_slot->name = new_name;
210 /* The offset into the file for this section. */
211 new_slot->start = coff_file->base.offset
212 + COFF_GET(&sec->coffsec,PointerToRawData);
213 new_slot->len = COFF_GET(&sec->coffsec,SizeOfRawData);
214 *slot = new_slot;
216 else
218 error ("two or more sections for %s:", new_name);
219 return NULL;
223 free (strtab);
224 return section_hash_table;
228 /* Begin a new COFF section named NAME with type TYPE in the current output
229 file. TYPE is an SHT_* macro from the libelf headers. */
231 static void
232 lto_coff_begin_section_with_type (const char *name, size_t type)
234 lto_coff_file *file;
235 size_t sh_name;
237 /* Grab the current output file and do some basic assertion checking. */
238 file = (lto_coff_file *) lto_get_current_out_file (),
239 gcc_assert (file);
240 gcc_assert (!file->scn);
242 /* Create a new section. */
243 file->scn = coff_newsection (file, name, type);
244 if (!file->scn)
245 fatal_error ("could not create a new COFF section: %m");
247 /* Add a string table entry and record the offset. */
248 gcc_assert (file->shstrtab_stream);
249 sh_name = file->shstrtab_stream->total_size;
250 lto_output_data_stream (file->shstrtab_stream, name, strlen (name) + 1);
252 /* Initialize the section header. */
253 file->scn->strtab_offs = sh_name;
257 /* Begin a new COFF section named NAME in the current output file. */
259 void
260 lto_obj_begin_section (const char *name)
262 lto_coff_begin_section_with_type (name, 0);
266 /* Append DATA of length LEN to the current output section. BASE is a pointer
267 to the output page containing DATA. It is freed once the output file has
268 been written. */
270 void
271 lto_obj_append_data (const void *data, size_t len, void *block)
273 lto_coff_file *file;
274 lto_coff_data *coff_data;
275 struct lto_char_ptr_base *base = (struct lto_char_ptr_base *) block;
277 /* Grab the current output file and do some basic assertion checking. */
278 file = (lto_coff_file *) lto_get_current_out_file ();
279 gcc_assert (file);
280 gcc_assert (file->scn);
282 coff_data = coff_newdata (file->scn);
283 if (!coff_data)
284 fatal_error ("could not append data to COFF section: %m");
286 coff_data->d_buf = CONST_CAST (void *, data);
287 coff_data->d_size = len;
289 /* Chain all data blocks (from all sections) on one singly-linked
290 list for freeing en masse after the file is closed. */
291 base->ptr = (char *)file->data;
292 file->data = base;
296 /* End the current output section. This just does some assertion checking
297 and sets the current output file's scn member to NULL. */
299 void
300 lto_obj_end_section (void)
302 lto_coff_file *file;
304 /* Grab the current output file and validate some basic assertions. */
305 file = (lto_coff_file *) lto_get_current_out_file ();
306 gcc_assert (file);
307 gcc_assert (file->scn);
309 file->scn = NULL;
313 /* Validate's COFF_FILE's executable header and, if cached_coff_hdr is
314 uninitialized, caches the results. Also records the section header string
315 table's section index. Returns true on success or false on failure. */
317 static bool
318 validate_file (lto_coff_file *coff_file)
320 size_t n, secnum;
321 unsigned int numsections, secheaderssize, numsyms;
322 off_t sectionsstart, symbolsstart, stringsstart;
323 unsigned int mach, charact;
325 /* Read and sanity check the raw header. */
326 n = read (coff_file->fd, &coff_file->coffhdr, sizeof (coff_file->coffhdr));
327 if (n != sizeof (coff_file->coffhdr))
329 error ("not a COFF object file");
330 return false;
333 mach = COFF_GET(&coff_file->coffhdr, Machine);
334 for (n = 0; n < NUM_COFF_KNOWN_MACHINES; n++)
335 if (mach == coff_machine_array[n])
336 break;
337 if (n == NUM_COFF_KNOWN_MACHINES)
339 error ("not a recognized COFF object file");
340 return false;
343 charact = COFF_GET(&coff_file->coffhdr, Characteristics);
344 if (COFF_NOT_CHARACTERISTICS & charact)
346 /* DLL, EXE or SYS file. */
347 error ("not a relocatable COFF object file");
348 return false;
351 if (mach != IMAGE_FILE_MACHINE_AMD64
352 && COFF_CHARACTERISTICS != (COFF_CHARACTERISTICS & charact))
354 /* ECOFF/XCOFF support not implemented. */
355 error ("not a 32-bit COFF object file");
356 return false;
359 /* It validated OK, so cached it if we don't already have one. */
360 if (!cached_coff_hdr_valid)
362 cached_coff_hdr_valid = true;
363 memcpy (&cached_coff_hdr, &coff_file->coffhdr, sizeof (cached_coff_hdr));
366 if (mach != COFF_GET(&cached_coff_hdr, Machine))
368 error ("inconsistent file architecture detected");
369 return false;
372 /* Read section headers and string table? */
374 numsections = COFF_GET(&coff_file->coffhdr, NumberOfSections);
375 secheaderssize = numsections * sizeof (Coff_section);
376 sectionsstart = sizeof (Coff_header) + secheaderssize;
377 symbolsstart = COFF_GET(&coff_file->coffhdr, PointerToSymbolTable);
378 numsyms = COFF_GET(&coff_file->coffhdr, NumberOfSymbols);
379 stringsstart = (symbolsstart + COFF_SYMBOL_SIZE * numsyms);
381 #define CVOFFSETTTED(x) (coff_file->base.offset + (x))
383 if (numsections <= 0 || symbolsstart <= 0 || numsyms <= 0
384 || (CVOFFSETTTED(sectionsstart) >= coff_file->file_size)
385 || (CVOFFSETTTED(symbolsstart) >= coff_file->file_size)
386 || (CVOFFSETTTED(stringsstart) >= coff_file->file_size))
388 error ("not a valid COFF object file");
389 return false;
392 #undef CVOFFSETTTED
394 /* Record start of string table. */
395 coff_file->strtab_offs = stringsstart;
397 /* Validate section table entries. */
398 for (secnum = 0; secnum < numsections; secnum++)
400 Coff_section coffsec;
401 lto_coff_section *ltosec;
402 off_t size_raw, offs_raw, offs_relocs, offs_lines;
403 off_t num_relocs, num_lines;
405 n = read (coff_file->fd, &coffsec, sizeof (coffsec));
406 if (n != sizeof (coffsec))
408 error ("short/missing COFF section table");
409 return false;
412 size_raw = COFF_GET(&coffsec, SizeOfRawData);
413 offs_raw = COFF_GET(&coffsec, PointerToRawData);
414 offs_relocs = COFF_GET(&coffsec, PointerToRelocations);
415 offs_lines = COFF_GET(&coffsec, PointerToLinenumbers);
416 num_relocs = COFF_GET(&coffsec, NumberOfRelocations);
417 num_lines = COFF_GET(&coffsec, NumberOfLinenumbers);
419 if (size_raw < 0 || num_relocs < 0 || num_lines < 0
420 || (size_raw
421 && ((COFF_GET(&coffsec, Characteristics)
422 & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
423 ? (offs_raw != 0)
424 : (offs_raw < sectionsstart || offs_raw >= coff_file->file_size)))
425 || (num_relocs
426 && (offs_relocs < sectionsstart
427 || offs_relocs >= coff_file->file_size))
428 || (num_lines
429 && (offs_lines < sectionsstart
430 || offs_lines >= coff_file->file_size)))
432 error ("invalid COFF section table");
433 return false;
436 /* Looks ok, so record its details. We don't read the
437 string table or set up names yet; we'll do that when
438 we build the hash table. */
439 ltosec = coff_newsection (coff_file, NULL, 0);
440 memcpy (&ltosec->coffsec, &coffsec, sizeof (ltosec->coffsec));
443 return true;
446 /* Initialize COFF_FILE's executable header using cached data from previously
447 read files. */
449 static void
450 init_coffhdr (lto_coff_file *coff_file)
452 gcc_assert (cached_coff_hdr_valid);
453 memset (&coff_file->coffhdr, 0, sizeof (coff_file->coffhdr));
454 COFF_PUT(&coff_file->coffhdr, Machine, COFF_GET(&cached_coff_hdr, Machine));
455 COFF_PUT(&coff_file->coffhdr, Characteristics, COFF_GET(&cached_coff_hdr, Characteristics));
458 /* Open COFF file FILENAME. If WRITABLE is true, the file is opened for write
459 and, if necessary, created. Otherwise, the file is opened for reading.
460 Returns the opened file. */
462 lto_file *
463 lto_obj_file_open (const char *filename, bool writable)
465 lto_coff_file *coff_file;
466 lto_file *result = NULL;
467 off_t offset;
468 const char *offset_p;
469 char *fname;
470 struct stat statbuf;
472 offset_p = strchr (filename, '@');
473 if (!offset_p)
475 fname = xstrdup (filename);
476 offset = 0;
478 else
480 /* The file started with '@' is a file containing command line
481 options. Stop if it doesn't exist. */
482 if (offset_p == filename)
483 fatal_error ("command line option file '%s' does not exist",
484 filename);
486 fname = (char *) xmalloc (offset_p - filename + 1);
487 memcpy (fname, filename, offset_p - filename);
488 fname[offset_p - filename] = '\0';
489 offset_p += 3; /* skip the @0x */
490 offset = lto_parse_hex (offset_p);
493 /* Set up. */
494 coff_file = XCNEW (lto_coff_file);
495 result = (lto_file *) coff_file;
496 lto_file_init (result, fname, offset);
497 coff_file->fd = -1;
499 /* Open the file. */
500 coff_file->fd = open (fname,
501 O_BINARY | (writable ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY), 0666);
503 if (coff_file->fd == -1)
505 error ("could not open file %s", fname);
506 goto fail;
509 if (stat (fname, &statbuf) < 0)
511 error ("could not stat file %s", fname);
512 goto fail;
515 coff_file->file_size = statbuf.st_size;
517 if (offset != 0)
519 char ar_tail[12];
520 int size;
522 /* Surely not? */
523 gcc_assert (!writable);
525 /* Seek to offset, or error. */
526 if (lseek (coff_file->fd, offset, SEEK_SET) != (ssize_t) offset)
528 error ("could not find archive member @0x%lx", (long) offset);
529 goto fail;
532 /* Now seek back 12 chars and read the tail of the AR header to
533 find the length of the member file. */
534 if (lseek (coff_file->fd, -12, SEEK_CUR) < 0
535 || read (coff_file->fd, ar_tail, 12) != 12
536 || lseek (coff_file->fd, 0, SEEK_CUR) != (ssize_t) offset
537 || ar_tail[10] != '`' || ar_tail[11] != '\n')
539 error ("could not find archive header @0x%lx", (long) offset);
540 goto fail;
543 ar_tail[11] = 0;
544 if (sscanf (ar_tail, "%d", &size) != 1)
546 error ("invalid archive header @0x%lx", (long) offset);
547 goto fail;
549 coff_file->file_size = size;
552 if (writable)
554 init_coffhdr (coff_file);
555 coff_file->shstrtab_stream = XCNEW (struct lto_output_stream);
557 else
558 if (!validate_file (coff_file))
559 goto fail;
561 return result;
563 fail:
564 if (result)
565 lto_obj_file_close (result);
566 return NULL;
570 /* Close COFF file FILE and clean up any associated data structures. If FILE
571 was opened for writing, the file's COFF data is written at this time, and
572 any cached data buffers are freed. Return TRUE if there was an error. */
574 static bool
575 coff_write_object_file (lto_coff_file *coff_file)
577 lto_coff_section *cursec, *stringsec;
578 lto_coff_data *data;
579 size_t fileoffset, numsections, totalsecsize, numsyms, stringssize;
580 bool write_err = false;
581 int secnum;
583 /* Infer whether this file was opened for reading or writing from the
584 presence or absense of an initialised stream for the string table;
585 do nothing if it was opened for reading. */
586 if (!coff_file->shstrtab_stream)
587 return false;
588 else
590 /* Write the COFF string table into a dummy new section that
591 we will not write a header for. */
592 lto_file *old_file = lto_set_current_out_file (&coff_file->base);
593 /* This recursively feeds in the data to a new section. */
594 lto_coff_begin_section_with_type (".strtab", 1);
595 lto_write_stream (coff_file->shstrtab_stream);
596 lto_obj_end_section ();
597 lto_set_current_out_file (old_file);
598 free (coff_file->shstrtab_stream);
601 /* Layout the file. Count sections (not dummy string section) and calculate
602 data size for all of them. */
603 numsections = 0;
604 totalsecsize = 0;
605 stringssize = 0;
606 stringsec = NULL;
607 COFF_FOR_ALL_SECTIONS(coff_file, cursec)
609 lto_coff_data *data;
610 size_t cursecsize;
611 cursecsize = 0;
612 COFF_FOR_ALL_DATA(cursec,data)
613 cursecsize += data->d_size;
614 if (cursec->type == 0)
616 ++numsections;
617 totalsecsize += COFF_ALIGN(cursecsize);
618 #if COFF_ALIGNMENT > 1
619 cursec->pad_needed = COFF_ALIGN(cursecsize) - cursecsize;
620 #endif
622 else
624 stringssize = cursecsize;
625 stringsec = cursec;
627 COFF_PUT(&cursec->coffsec, SizeOfRawData, cursecsize);
630 /* There is a file symbol and a section symbol per section,
631 and each of these has a single auxiliary symbol following. */
632 numsyms = 2 * (1 + numsections);
634 /* Great! Now we have enough info to fill out the file header. */
635 COFF_PUT(&coff_file->coffhdr, NumberOfSections, numsections);
636 COFF_PUT(&coff_file->coffhdr, NumberOfSymbols, numsyms);
637 COFF_PUT(&coff_file->coffhdr, PointerToSymbolTable, sizeof (Coff_header)
638 + numsections * sizeof (Coff_section) + totalsecsize);
639 /* The remaining members were initialised to zero or copied from
640 a cached header, so we leave them alone here. */
642 /* Now position all the sections, and fill out their headers. */
643 fileoffset = sizeof (Coff_header) + numsections * sizeof (Coff_section);
644 COFF_FOR_ALL_SECTIONS(coff_file, cursec)
646 /* Skip dummy string section. */
647 if (cursec->type == 1)
648 continue;
649 COFF_PUT(&cursec->coffsec, PointerToRawData, fileoffset);
650 fileoffset += COFF_ALIGN (COFF_GET(&cursec->coffsec, SizeOfRawData));
651 COFF_PUT(&cursec->coffsec, Characteristics, COFF_SECTION_CHARACTERISTICS);
652 snprintf ((char *)&cursec->coffsec.Name[0], 8, "/%d", cursec->strtab_offs + 4);
655 /* We can write the data now. As there's no way to indicate an error return
656 from this hook, error handling is limited to not wasting our time doing
657 any more writes in the event that any one fails. */
659 /* Write the COFF header. */
660 write_err = (write (coff_file->fd, &coff_file->coffhdr,
661 sizeof (coff_file->coffhdr)) != sizeof (coff_file->coffhdr));
663 /* Write the COFF section headers. */
664 COFF_FOR_ALL_SECTIONS(coff_file, cursec)
665 if (cursec->type == 1) /* Skip dummy string section. */
666 continue;
667 else if (!write_err)
668 write_err = (write (coff_file->fd, &cursec->coffsec,
669 sizeof (cursec->coffsec)) != sizeof (cursec->coffsec));
670 else
671 break;
673 /* Write the COFF sections. */
674 COFF_FOR_ALL_SECTIONS(coff_file, cursec)
676 #if COFF_ALIGNMENT > 1
677 static const char padzeros[COFF_ALIGNMENT] = { 0 };
678 #endif
679 /* Skip dummy string section. */
680 if (cursec->type == 1)
681 continue;
682 COFF_FOR_ALL_DATA(cursec, data)
683 if (!write_err)
684 write_err = (write (coff_file->fd, data->d_buf, data->d_size)
685 != data->d_size);
686 else
687 break;
688 #if COFF_ALIGNMENT > 1
689 if (!write_err && cursec->pad_needed)
690 write_err = (write (coff_file->fd, padzeros, cursec->pad_needed)
691 != cursec->pad_needed);
692 #endif
695 /* Write the COFF symbol table. */
696 if (!write_err)
698 union
700 Coff_symbol sym;
701 Coff_aux_sym_file file;
702 Coff_aux_sym_section sec;
703 } symbols[2];
704 memset (&symbols[0], 0, sizeof (symbols));
705 strcpy ((char *) &symbols[0].sym.Name[0], ".file");
706 COFF_PUT(&symbols[0].sym, SectionNumber, IMAGE_SYM_DEBUG);
707 COFF_PUT(&symbols[0].sym, Type, IMAGE_SYM_TYPE);
708 symbols[0].sym.StorageClass[0] = IMAGE_SYM_CLASS_FILE;
709 symbols[0].sym.NumberOfAuxSymbols[0] = 1;
710 snprintf ((char *)symbols[1].file.FileName,
711 sizeof (symbols[1].file.FileName),
712 "%s", lbasename (coff_file->base.filename));
713 write_err = (write (coff_file->fd, &symbols[0], sizeof (symbols))
714 != (2 * COFF_SYMBOL_SIZE));
716 /* Set up constant parts for section sym loop. */
717 memset (&symbols[0], 0, sizeof (symbols));
718 COFF_PUT(&symbols[0].sym, Type, IMAGE_SYM_TYPE);
719 symbols[0].sym.StorageClass[0] = IMAGE_SYM_CLASS_STATIC;
720 symbols[0].sym.NumberOfAuxSymbols[0] = 1;
722 secnum = 1;
723 if (!write_err)
724 COFF_FOR_ALL_SECTIONS(coff_file, cursec)
726 /* Skip dummy string section. */
727 if (cursec->type == 1)
728 continue;
729 /* Reuse section name string for section symbol name. */
730 COFF_PUT_NDXSZ(&symbols[0].sym, Name, 0, 0, 4);
731 COFF_PUT_NDXSZ(&symbols[0].sym, Name, cursec->strtab_offs + 4, 4, 4);
732 COFF_PUT(&symbols[0].sym, SectionNumber, secnum++);
733 COFF_PUT(&symbols[1].sec, Length,
734 COFF_GET(&cursec->coffsec, SizeOfRawData));
735 if (!write_err)
736 write_err = (write (coff_file->fd, &symbols[0], sizeof (symbols))
737 != (2 * COFF_SYMBOL_SIZE));
738 else
739 break;
743 /* Write the COFF string table. */
744 if (!write_err)
746 unsigned char outlen[4];
747 COFF_PUT4(outlen, stringssize + 4);
748 if (!write_err)
749 write_err = (write (coff_file->fd, outlen, 4) != 4);
750 if (stringsec)
752 COFF_FOR_ALL_DATA(stringsec, data)
753 if (!write_err)
754 write_err = (write (coff_file->fd, data->d_buf, data->d_size)
755 != data->d_size);
756 else
757 break;
761 return write_err;
764 /* Close COFF file FILE and clean up any associated data structures. If FILE
765 was opened for writing, the file's COFF data is written at this time, and
766 any cached data buffers are freed. */
768 void
769 lto_obj_file_close (lto_file *file)
771 lto_coff_file *coff_file = (lto_coff_file *) file;
772 struct lto_char_ptr_base *cur, *tmp;
773 lto_coff_section *cursec, *nextsec;
774 bool write_err = false;
776 /* Write the COFF string table into a dummy new section that
777 we will not write a header for. */
778 if (coff_file->shstrtab_stream)
779 coff_write_object_file (coff_file);
781 /* Close the file, we're done. */
782 if (coff_file->fd != -1)
783 close (coff_file->fd);
785 /* Free any data buffers. */
786 cur = coff_file->data;
787 while (cur)
789 tmp = cur;
790 cur = (struct lto_char_ptr_base *) cur->ptr;
791 free (tmp);
794 /* Free any sections and their data chains. */
795 cursec = coff_file->section_chain;
796 while (cursec)
798 lto_coff_data *curdata, *nextdata;
799 nextsec = cursec->next;
800 curdata = cursec->data_chain;
801 while (curdata)
803 nextdata = curdata->next;
804 free (curdata);
805 curdata = nextdata;
807 free (cursec);
808 cursec = nextsec;
811 free (file);
813 /* If there was an error, mention it. */
814 if (write_err)
815 error ("I/O error writing COFF output file");