Merged r158704 through r158906 into branch.
[official-gcc.git] / gcc / lto / lto-coff.c
blob1814cfdb82b9cb157098d73e9ba399e6ed9e0133
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
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 "toplev.h"
25 #include "lto.h"
26 #include "tm.h"
27 #include "libiberty.h"
28 #include "ggc.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. */
42 #ifndef O_BINARY
43 #define O_BINARY 0
44 #endif
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
69 NULL. */
71 lto_file *
72 lto_set_current_out_file (lto_file *file)
74 lto_file *old_file = current_out_file;
75 current_out_file = file;
76 return old_file;
80 /* Returns the current output file. */
82 lto_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);
97 ptr->name = name;
98 ptr->type = type;
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;
105 return 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;
123 return ptr;
127 /* Initialize FILE, an LTO file object for FILENAME. */
129 static void
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. */
139 static const char *
140 coff_errmsg (int errcode)
142 return strerror (errcode == -1 ? errno : errcode);
145 /* Returns a hash code for P. */
147 static hashval_t
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. */
156 static int
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. */
171 htab_t
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;
177 ssize_t strtab_size;
178 char *strtab;
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;
202 void **slot;
203 char *new_name;
204 int stringoffset;
205 char *name = (char *) &sec->coffsec.Name[0];
207 /* Skip dummy string section if by any chance we see it. */
208 if (sec->type == 1)
209 continue;
211 if (name[0] == '/')
213 if (1 != sscanf (&name[1], "%d", &stringoffset)
214 || stringoffset < 0 || stringoffset >= strtab_size)
216 error ("invalid COFF section name string");
217 continue;
219 name = strtab + stringoffset;
221 else
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. */
226 name[8] = 0;
228 if (strncmp (name, LTO_SECTION_NAME_PREFIX,
229 strlen (LTO_SECTION_NAME_PREFIX)) != 0)
230 continue;
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);
236 if (*slot == NULL)
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);
245 *slot = new_slot;
247 else
249 error ("two or more sections for %s:", new_name);
250 return NULL;
254 free (strtab);
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. */
262 static void
263 lto_coff_begin_section_with_type (const char *name, size_t type)
265 lto_coff_file *file;
266 size_t sh_name;
268 /* Grab the current output file and do some basic assertion checking. */
269 file = (lto_coff_file *) lto_get_current_out_file (),
270 gcc_assert (file);
271 gcc_assert (!file->scn);
273 /* Create a new section. */
274 file->scn = coff_newsection (file, name, type);
275 if (!file->scn)
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. */
290 void
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
299 been written. */
301 void
302 lto_obj_append_data (const void *data, size_t len, void *block)
304 lto_coff_file *file;
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 ();
310 gcc_assert (file);
311 gcc_assert (file->scn);
313 coff_data = coff_newdata (file->scn);
314 if (!coff_data)
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;
323 file->data = base;
327 /* End the current output section. This just does some assertion checking
328 and sets the current output file's scn member to NULL. */
330 void
331 lto_obj_end_section (void)
333 lto_coff_file *file;
335 /* Grab the current output file and validate some basic assertions. */
336 file = (lto_coff_file *) lto_get_current_out_file ();
337 gcc_assert (file);
338 gcc_assert (file->scn);
340 file->scn = NULL;
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. */
348 static bool
349 validate_file (lto_coff_file *coff_file)
351 size_t n, secnum;
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");
361 return false;
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])
367 break;
368 if (n == NUM_COFF_KNOWN_MACHINES)
370 error ("not a recognized COFF object file");
371 return false;
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");
379 return false;
382 if (COFF_CHARACTERISTICS != (COFF_CHARACTERISTICS & charact))
384 /* ECOFF/XCOFF/PE+ support not implemented. */
385 error ("not a 32-bit COFF object file");
386 return false;
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");
399 return false;
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");
419 return false;
422 #undef CVOFFSETTTED
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");
439 return false;
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
450 || (size_raw
451 && ((COFF_GET(&coffsec, Characteristics)
452 & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
453 ? (offs_raw != 0)
454 : (offs_raw < sectionsstart || offs_raw >= coff_file->file_size)))
455 || (num_relocs
456 && (offs_relocs < sectionsstart
457 || offs_relocs >= coff_file->file_size))
458 || (num_lines
459 && (offs_lines < sectionsstart
460 || offs_lines >= coff_file->file_size)))
462 error ("invalid COFF section table");
463 return false;
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 (&ltosec->coffsec, &coffsec, sizeof (ltosec->coffsec));
473 return true;
476 /* Initialize COFF_FILE's executable header using cached data from previously
477 read files. */
479 static void
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. */
492 lto_file *
493 lto_obj_file_open (const char *filename, bool writable)
495 lto_coff_file *coff_file;
496 lto_file *result = NULL;
497 off_t offset;
498 const char *offset_p;
499 char *fname;
500 struct stat statbuf;
502 offset_p = strchr (filename, '@');
503 if (!offset_p)
505 fname = xstrdup (filename);
506 offset = 0;
508 else
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",
514 filename);
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);
523 /* Set up. */
524 coff_file = XCNEW (lto_coff_file);
525 result = (lto_file *) coff_file;
526 lto_file_init (result, fname, offset);
527 coff_file->fd = -1;
529 /* Open the file. */
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);
536 goto fail;
539 if (stat (fname, &statbuf) < 0)
541 error ("could not stat file %s", fname);
542 goto fail;
545 coff_file->file_size = statbuf.st_size;
547 if (offset != 0)
549 char ar_tail[12];
550 int size;
552 /* Surely not? */
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);
559 goto fail;
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);
570 goto fail;
573 ar_tail[11] = 0;
574 if (sscanf (ar_tail, "%d", &size) != 1)
576 error ("invalid archive header @0x%lx", (long) offset);
577 goto fail;
579 coff_file->file_size = size;
582 if (writable)
584 init_coffhdr (coff_file);
585 coff_file->shstrtab_stream = XCNEW (struct lto_output_stream);
587 else
588 if (!validate_file (coff_file))
589 goto fail;
591 return result;
593 fail:
594 if (result)
595 lto_obj_file_close (result);
596 return NULL;
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. */
604 static bool
605 coff_write_object_file (lto_coff_file *coff_file)
607 lto_coff_section *cursec, *stringsec;
608 lto_coff_data *data;
609 size_t fileoffset, numsections, totalsecsize, numsyms, stringssize;
610 bool write_err = false;
611 int secnum;
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)
617 return false;
618 else
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. */
633 numsections = 0;
634 totalsecsize = 0;
635 stringssize = 0;
636 stringsec = NULL;
637 COFF_FOR_ALL_SECTIONS(coff_file, cursec)
639 lto_coff_data *data;
640 size_t cursecsize;
641 cursecsize = 0;
642 COFF_FOR_ALL_DATA(cursec,data)
643 cursecsize += data->d_size;
644 if (cursec->type == 0)
646 ++numsections;
647 totalsecsize += COFF_ALIGN(cursecsize);
648 #if COFF_ALIGNMENT > 1
649 cursec->pad_needed = COFF_ALIGN(cursecsize) - cursecsize;
650 #endif
652 else
654 stringssize = cursecsize;
655 stringsec = cursec;
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)
678 continue;
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. */
696 continue;
697 else if (!write_err)
698 write_err = (write (coff_file->fd, &cursec->coffsec,
699 sizeof (cursec->coffsec)) != sizeof (cursec->coffsec));
700 else
701 break;
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 };
708 #endif
709 /* Skip dummy string section. */
710 if (cursec->type == 1)
711 continue;
712 COFF_FOR_ALL_DATA(cursec, data)
713 if (!write_err)
714 write_err = (write (coff_file->fd, data->d_buf, data->d_size)
715 != data->d_size);
716 else
717 break;
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);
722 #endif
725 /* Write the COFF symbol table. */
726 if (!write_err)
728 union
730 Coff_symbol sym;
731 Coff_aux_sym_file file;
732 Coff_aux_sym_section sec;
733 } symbols[2];
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;
752 secnum = 1;
753 if (!write_err)
754 COFF_FOR_ALL_SECTIONS(coff_file, cursec)
756 /* Skip dummy string section. */
757 if (cursec->type == 1)
758 continue;
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));
765 if (!write_err)
766 write_err = (write (coff_file->fd, &symbols[0], sizeof (symbols))
767 != (2 * COFF_SYMBOL_SIZE));
768 else
769 break;
773 /* Write the COFF string table. */
774 if (!write_err)
776 unsigned char outlen[4];
777 COFF_PUT4(outlen, stringssize + 4);
778 if (!write_err)
779 write_err = (write (coff_file->fd, outlen, 4) != 4);
780 if (stringsec)
781 COFF_FOR_ALL_DATA(stringsec, data)
782 if (!write_err)
783 write_err = (write (coff_file->fd, data->d_buf, data->d_size)
784 != data->d_size);
785 else
786 break;
789 return write_err;
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. */
796 void
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;
815 while (cur)
817 tmp = cur;
818 cur = (struct lto_char_ptr_base *) cur->ptr;
819 free (tmp);
822 /* Free any sections and their data chains. */
823 cursec = coff_file->section_chain;
824 while (cursec)
826 lto_coff_data *curdata, *nextdata;
827 nextsec = cursec->next;
828 curdata = cursec->data_chain;
829 while (curdata)
831 nextdata = curdata->next;
832 free (curdata);
833 curdata = nextdata;
835 free (cursec);
836 cursec = nextsec;
839 free (file);
841 /* If there was an error, mention it. */
842 if (write_err)
843 error ("I/O error writing COFF output file");