OSDN Git Service

2010-05-11 Kai Tietz <kai.tietz@onevision.com>
[pf3gnuchains/gcc-fork.git] / gcc / lto / lto-coff.c
1 /* LTO routines for COFF object files.
2    Copyright 2009 Free Software Foundation, Inc.
3    Contributed by Dave Korn.
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>.  */
20
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"
31
32
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.  */
38
39 /* Handle opening elf files on hosts, such as Windows, that may use 
40    text file handling that will break binary access.  */
41
42 #ifndef O_BINARY
43 #define O_BINARY 0
44 #endif
45
46 /* Known header magics for validation, as an array.  */
47
48 static const unsigned int coff_machine_array[] = COFF_KNOWN_MACHINES;
49
50 /* Number of valid entries (no sentinel) in array.  */
51
52 #define NUM_COFF_KNOWN_MACHINES \
53         (sizeof (coff_machine_array) / sizeof (coff_machine_array[0]))
54
55 /* Cached object file header.  */
56
57 static Coff_header cached_coff_hdr;
58
59 /* Flag to indicate if we have read and cached any header yet.  */
60
61 static bool cached_coff_hdr_valid = false;
62
63 /* The current output file.  */
64
65 static lto_file *current_out_file;
66
67
68 /* Sets the current output file to FILE.  Returns the old output file or
69    NULL.  */
70
71 lto_file *
72 lto_set_current_out_file (lto_file *file)
73 {
74   lto_file *old_file = current_out_file;
75   current_out_file = file;
76   return old_file;
77 }
78
79
80 /* Returns the current output file.  */
81
82 lto_file *
83 lto_get_current_out_file (void)
84 {
85   return current_out_file;
86 }
87
88
89 /* COFF section structure constructor.  */
90
91 static lto_coff_section *
92 coff_newsection (lto_coff_file *file, const char *name, size_t type)
93 {
94   lto_coff_section *ptr, **chain_ptr_ptr;
95
96   ptr = XCNEW (lto_coff_section);
97   ptr->name = name;
98   ptr->type = type;
99
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;
104
105   return ptr;
106 }
107
108
109 /* COFF section data block structure constructor.  */
110
111 static lto_coff_data *
112 coff_newdata (lto_coff_section *sec)
113 {
114   lto_coff_data *ptr, **chain_ptr_ptr;
115
116   ptr = XCNEW (lto_coff_data);
117
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;
122
123   return ptr;
124 }
125
126
127 /* Initialize FILE, an LTO file object for FILENAME.  */
128
129 static void
130 lto_file_init (lto_file *file, const char *filename, off_t offset)
131 {
132   file->filename = filename;
133   file->offset = offset;
134 }
135
136 /* Return an error string after an error, or a predetermined one
137    if ERRCODE is not -1.  */
138
139 static const char *
140 coff_errmsg (int errcode)
141 {
142   return strerror (errcode == -1 ? errno : errcode);
143 }
144
145 /* Returns a hash code for P.  */
146
147 static hashval_t
148 hash_name (const void *p)
149 {
150   const struct lto_section_slot *ds = (const struct lto_section_slot *) p;
151   return (hashval_t) htab_hash_string (ds->name);
152 }
153
154 /* Returns nonzero if P1 and P2 are equal.  */
155
156 static int
157 eq_name (const void *p1, const void *p2)
158 {
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;
163
164   return strcmp (s1->name, s2->name) == 0;
165 }
166
167
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.  */
170
171 htab_t
172 lto_obj_build_section_table (lto_file *lto_file) 
173 {
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;
179
180   section_hash_table = htab_create (37, hash_name, eq_name, free);
181
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))
185     {
186       error ("altered or invalid COFF object file");
187       return section_hash_table;
188     }
189
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)
193     {
194       error ("invalid COFF object file string table");
195       return section_hash_table;
196     }
197
198   /* Scan sections looking at names.  */
199   COFF_FOR_ALL_SECTIONS(coff_file, sec)
200     {
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];
206
207       /* Skip dummy string section if by any chance we see it.  */
208       if (sec->type == 1)
209         continue;
210
211       if (name[0] == '/')
212         {
213           if (1 != sscanf (&name[1], "%d", &stringoffset)
214                 || stringoffset < 0 || stringoffset >= strtab_size)
215             {
216               error ("invalid COFF section name string");
217               continue;
218             }
219           name = strtab + stringoffset;
220         }
221       else
222         {
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;
227         }
228       if (strncmp (name, LTO_SECTION_NAME_PREFIX,
229                         strlen (LTO_SECTION_NAME_PREFIX)) != 0)
230           continue;
231
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)
237         {
238           struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
239
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;
246         }
247       else
248         {
249           error ("two or more sections for %s:", new_name);
250           return NULL;
251         }
252     }
253
254   free (strtab);
255   return section_hash_table;
256 }
257
258
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.  */
261
262 static void
263 lto_coff_begin_section_with_type (const char *name, size_t type)
264 {
265   lto_coff_file *file;
266   size_t sh_name;
267
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);
272
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));
277
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);
282
283   /* Initialize the section header.  */
284   file->scn->strtab_offs = sh_name;
285 }
286
287
288 /* Begin a new COFF section named NAME in the current output file.  */
289
290 void
291 lto_obj_begin_section (const char *name)
292 {
293   lto_coff_begin_section_with_type (name, 0);
294 }
295
296
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.  */
300
301 void
302 lto_obj_append_data (const void *data, size_t len, void *block)
303 {
304   lto_coff_file *file;
305   lto_coff_data *coff_data;
306   struct lto_char_ptr_base *base = (struct lto_char_ptr_base *) block;
307
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);
312
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));
316
317   coff_data->d_buf = CONST_CAST (void *, data);
318   coff_data->d_size = len;
319
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;
324 }
325
326
327 /* End the current output section.  This just does some assertion checking
328    and sets the current output file's scn member to NULL.  */
329
330 void
331 lto_obj_end_section (void)
332 {
333   lto_coff_file *file;
334
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);
339
340   file->scn = NULL;
341 }
342
343
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.  */
347
348 static bool
349 validate_file (lto_coff_file *coff_file)
350 {
351   size_t n, secnum;
352   unsigned int numsections, secheaderssize, numsyms;
353   off_t sectionsstart, symbolsstart, stringsstart;
354   unsigned int mach, charact;
355
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))
359     {
360       error ("not a COFF object file");
361       return false;
362     }
363
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)
369     {
370       error ("not a recognized COFF object file");
371       return false;
372     }
373
374   charact = COFF_GET(&coff_file->coffhdr, Characteristics);
375   if (COFF_NOT_CHARACTERISTICS & charact)
376     {
377       /* DLL, EXE or SYS file.  */
378       error ("not a relocatable COFF object file");
379       return false;
380     }
381
382   if (mach != IMAGE_FILE_MACHINE_ADM64
383       && COFF_CHARACTERISTICS != (COFF_CHARACTERISTICS & charact))
384     {
385       /* ECOFF/XCOFF support not implemented.  */
386       error ("not a 32-bit COFF object file");
387       return false;
388     }
389
390   /* It validated OK, so cached it if we don't already have one.  */
391   if (!cached_coff_hdr_valid)
392     {
393       cached_coff_hdr_valid = true;
394       memcpy (&cached_coff_hdr, &coff_file->coffhdr, sizeof (cached_coff_hdr));
395     }
396
397   if (mach != COFF_GET(&cached_coff_hdr, Machine))
398     {
399       error ("inconsistent file architecture detected");
400       return false;
401     }
402
403   /* Read section headers and string table? */
404
405   numsections = COFF_GET(&coff_file->coffhdr, NumberOfSections);
406   secheaderssize = numsections * sizeof (Coff_section);
407   sectionsstart = sizeof (Coff_header) + secheaderssize;
408   symbolsstart = COFF_GET(&coff_file->coffhdr, PointerToSymbolTable);
409   numsyms = COFF_GET(&coff_file->coffhdr, NumberOfSymbols);
410   stringsstart = (symbolsstart + COFF_SYMBOL_SIZE * numsyms);
411
412 #define CVOFFSETTTED(x) (coff_file->base.offset + (x))
413
414   if (numsections <= 0 || symbolsstart <= 0 || numsyms <= 0
415         || (CVOFFSETTTED(sectionsstart) >= coff_file->file_size)
416         || (CVOFFSETTTED(symbolsstart) >= coff_file->file_size)
417         || (CVOFFSETTTED(stringsstart) >= coff_file->file_size))
418     {
419       error ("not a valid COFF object file");
420       return false;
421     }
422
423 #undef CVOFFSETTTED
424
425   /* Record start of string table.  */
426   coff_file->strtab_offs = stringsstart;
427
428   /* Validate section table entries.  */
429   for (secnum = 0; secnum < numsections; secnum++)
430     {
431       Coff_section coffsec;
432       lto_coff_section *ltosec;
433       off_t size_raw, offs_raw, offs_relocs, offs_lines;
434       off_t num_relocs, num_lines;
435
436       n = read (coff_file->fd, &coffsec, sizeof (coffsec));
437       if (n != sizeof (coffsec))
438         {
439           error ("short/missing COFF section table");
440           return false;
441         }
442
443       size_raw = COFF_GET(&coffsec, SizeOfRawData);
444       offs_raw = COFF_GET(&coffsec, PointerToRawData);
445       offs_relocs = COFF_GET(&coffsec, PointerToRelocations);
446       offs_lines = COFF_GET(&coffsec, PointerToLinenumbers);
447       num_relocs = COFF_GET(&coffsec, NumberOfRelocations);
448       num_lines = COFF_GET(&coffsec, NumberOfLinenumbers);
449
450       if (size_raw < 0 || num_relocs < 0 || num_lines < 0
451         || (size_raw
452           && ((COFF_GET(&coffsec, Characteristics)
453               & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
454             ? (offs_raw != 0)
455             : (offs_raw < sectionsstart || offs_raw >= coff_file->file_size)))
456         || (num_relocs
457           && (offs_relocs < sectionsstart
458             || offs_relocs >= coff_file->file_size))
459         || (num_lines
460           && (offs_lines < sectionsstart
461             || offs_lines >= coff_file->file_size)))
462         {
463           error ("invalid COFF section table");
464           return false;
465         }
466
467       /* Looks ok, so record its details.  We don't read the 
468          string table or set up names yet; we'll do that when
469          we build the hash table.  */
470       ltosec = coff_newsection (coff_file, NULL, 0);
471       memcpy (&ltosec->coffsec, &coffsec, sizeof (ltosec->coffsec));
472     }
473
474   return true;
475 }
476
477 /* Initialize COFF_FILE's executable header using cached data from previously
478    read files.  */
479
480 static void
481 init_coffhdr (lto_coff_file *coff_file)
482 {
483   gcc_assert (cached_coff_hdr_valid);
484   memset (&coff_file->coffhdr, 0, sizeof (coff_file->coffhdr));
485   COFF_PUT(&coff_file->coffhdr, Machine, COFF_GET(&cached_coff_hdr, Machine));
486   COFF_PUT(&coff_file->coffhdr, Characteristics, COFF_GET(&cached_coff_hdr, Characteristics));
487 }
488
489 /* Open COFF file FILENAME.  If WRITABLE is true, the file is opened for write
490    and, if necessary, created.  Otherwise, the file is opened for reading.
491    Returns the opened file.  */
492
493 lto_file *
494 lto_obj_file_open (const char *filename, bool writable)
495 {
496   lto_coff_file *coff_file;
497   lto_file *result = NULL;
498   off_t offset;
499   const char *offset_p;
500   char *fname;
501   struct stat statbuf;
502
503   offset_p = strchr (filename, '@');
504   if (!offset_p)
505     {
506       fname = xstrdup (filename);
507       offset = 0;
508     }
509   else
510     {
511       /* The file started with '@' is a file containing command line
512          options.  Stop if it doesn't exist.  */
513       if (offset_p == filename)
514         fatal_error ("command line option file '%s' does not exist",
515                      filename);
516
517       fname = (char *) xmalloc (offset_p - filename + 1);
518       memcpy (fname, filename, offset_p - filename);
519       fname[offset_p - filename] = '\0';
520       offset_p += 3; /* skip the @0x */
521       offset = lto_parse_hex (offset_p);
522     }
523
524   /* Set up.  */
525   coff_file = XCNEW (lto_coff_file);
526   result = (lto_file *) coff_file;
527   lto_file_init (result, fname, offset);
528   coff_file->fd = -1;
529
530   /* Open the file.  */
531   coff_file->fd = open (fname,
532     O_BINARY | (writable ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY), 0666);
533
534   if (coff_file->fd == -1)
535     {
536       error ("could not open file %s", fname);
537       goto fail;
538     }
539
540   if (stat (fname, &statbuf) < 0)
541     {
542       error ("could not stat file %s", fname);
543       goto fail;
544     }
545
546   coff_file->file_size = statbuf.st_size;
547
548   if (offset != 0)
549     {
550       char ar_tail[12];
551       int size;
552
553       /* Surely not?  */
554       gcc_assert (!writable);
555
556       /* Seek to offset, or error.  */
557       if (lseek (coff_file->fd, offset, SEEK_SET) != (ssize_t) offset)
558         {
559           error ("could not find archive member @0x%lx", (long) offset);
560           goto fail;
561         }
562
563       /* Now seek back 12 chars and read the tail of the AR header to
564          find the length of the member file.  */
565       if (lseek (coff_file->fd, -12, SEEK_CUR) < 0
566           || read (coff_file->fd, ar_tail, 12) != 12
567           || lseek (coff_file->fd, 0, SEEK_CUR) != (ssize_t) offset
568           || ar_tail[10] != '`' || ar_tail[11] != '\n')
569         {
570           error ("could not find archive header @0x%lx", (long) offset);
571           goto fail;
572         }
573
574       ar_tail[11] = 0;
575       if (sscanf (ar_tail, "%d", &size) != 1)
576         {
577           error ("invalid archive header @0x%lx", (long) offset);
578           goto fail;
579         }
580       coff_file->file_size = size;
581     }
582
583   if (writable)
584     {
585       init_coffhdr (coff_file);
586       coff_file->shstrtab_stream = XCNEW (struct lto_output_stream);
587     }
588   else
589     if (!validate_file (coff_file))
590       goto fail;
591
592   return result;
593
594  fail:
595   if (result)
596     lto_obj_file_close (result);
597   return NULL;
598 }
599
600
601 /* Close COFF file FILE and clean up any associated data structures.  If FILE
602    was opened for writing, the file's COFF data is written at this time, and
603    any cached data buffers are freed.  Return TRUE if there was an error.  */
604
605 static bool
606 coff_write_object_file (lto_coff_file *coff_file)
607 {
608   lto_coff_section *cursec, *stringsec;
609   lto_coff_data *data;
610   size_t fileoffset, numsections, totalsecsize, numsyms, stringssize;
611   bool write_err = false;
612   int secnum;
613
614   /* Infer whether this file was opened for reading or writing from the
615      presence or absense of an initialised stream for the string table;
616      do nothing if it was opened for reading.  */
617   if (!coff_file->shstrtab_stream)
618     return false;
619   else
620     {
621       /* Write the COFF string table into a dummy new section that
622          we will not write a header for.  */
623       lto_file *old_file = lto_set_current_out_file (&coff_file->base);
624       /* This recursively feeds in the data to a new section.  */
625       lto_coff_begin_section_with_type (".strtab", 1);
626       lto_write_stream (coff_file->shstrtab_stream);
627       lto_obj_end_section ();
628       lto_set_current_out_file (old_file);
629       free (coff_file->shstrtab_stream);
630     }
631
632   /* Layout the file.  Count sections (not dummy string section) and calculate
633      data size for all of them.  */
634   numsections = 0;
635   totalsecsize = 0;
636   stringssize = 0;
637   stringsec = NULL;
638   COFF_FOR_ALL_SECTIONS(coff_file, cursec)
639     {
640       lto_coff_data *data;
641       size_t cursecsize;
642       cursecsize = 0;
643       COFF_FOR_ALL_DATA(cursec,data)
644         cursecsize += data->d_size;
645       if (cursec->type == 0)
646         {
647           ++numsections;
648           totalsecsize += COFF_ALIGN(cursecsize);
649 #if COFF_ALIGNMENT > 1
650           cursec->pad_needed = COFF_ALIGN(cursecsize) - cursecsize;
651 #endif
652         }
653       else
654         {
655           stringssize = cursecsize;
656           stringsec = cursec;
657         }
658       COFF_PUT(&cursec->coffsec, SizeOfRawData, cursecsize);
659     }
660
661   /* There is a file symbol and a section symbol per section,
662      and each of these has a single auxiliary symbol following.  */
663   numsyms = 2 * (1 + numsections);
664
665   /* Great!  Now we have enough info to fill out the file header.  */
666   COFF_PUT(&coff_file->coffhdr, NumberOfSections, numsections);
667   COFF_PUT(&coff_file->coffhdr, NumberOfSymbols, numsyms);
668   COFF_PUT(&coff_file->coffhdr, PointerToSymbolTable, sizeof (Coff_header)
669                 + numsections * sizeof (Coff_section) + totalsecsize);
670   /* The remaining members were initialised to zero or copied from
671      a cached header, so we leave them alone here.  */
672
673   /* Now position all the sections, and fill out their headers.  */
674   fileoffset = sizeof (Coff_header) + numsections * sizeof (Coff_section);
675   COFF_FOR_ALL_SECTIONS(coff_file, cursec)
676     {
677       /* Skip dummy string section.  */
678       if (cursec->type == 1)
679         continue;
680       COFF_PUT(&cursec->coffsec, PointerToRawData, fileoffset);
681       fileoffset += COFF_ALIGN (COFF_GET(&cursec->coffsec, SizeOfRawData));
682       COFF_PUT(&cursec->coffsec, Characteristics, COFF_SECTION_CHARACTERISTICS);
683       snprintf ((char *)&cursec->coffsec.Name[0], 8, "/%d", cursec->strtab_offs + 4);
684     }
685
686   /* We can write the data now.  As there's no way to indicate an error return
687      from this hook, error handling is limited to not wasting our time doing
688      any more writes in the event that any one fails.  */
689
690   /* Write the COFF header.  */
691   write_err = (write (coff_file->fd, &coff_file->coffhdr,
692                 sizeof (coff_file->coffhdr)) != sizeof (coff_file->coffhdr));
693
694   /* Write the COFF section headers.  */
695   COFF_FOR_ALL_SECTIONS(coff_file, cursec)
696     if (cursec->type == 1)      /* Skip dummy string section.  */
697         continue;
698     else if (!write_err)
699       write_err = (write (coff_file->fd, &cursec->coffsec,
700                 sizeof (cursec->coffsec)) != sizeof (cursec->coffsec));
701     else
702       break;
703
704   /* Write the COFF sections.  */
705   COFF_FOR_ALL_SECTIONS(coff_file, cursec)
706     {
707 #if COFF_ALIGNMENT > 1
708       static const char padzeros[COFF_ALIGNMENT] = { 0 };
709 #endif
710       /* Skip dummy string section.  */
711       if (cursec->type == 1)
712         continue;
713       COFF_FOR_ALL_DATA(cursec, data)
714         if (!write_err)
715           write_err = (write (coff_file->fd, data->d_buf, data->d_size)
716                 != data->d_size);
717         else
718           break;
719 #if COFF_ALIGNMENT > 1
720       if (!write_err && cursec->pad_needed)
721         write_err = (write (coff_file->fd, padzeros, cursec->pad_needed)
722                 != cursec->pad_needed);
723 #endif
724     }
725
726   /* Write the COFF symbol table.  */
727   if (!write_err)
728     {
729       union
730         {
731           Coff_symbol sym;
732           Coff_aux_sym_file file;
733           Coff_aux_sym_section sec;
734         } symbols[2];
735       memset (&symbols[0], 0, sizeof (symbols));
736       strcpy ((char *) &symbols[0].sym.Name[0], ".file");
737       COFF_PUT(&symbols[0].sym, SectionNumber, IMAGE_SYM_DEBUG);
738       COFF_PUT(&symbols[0].sym, Type, IMAGE_SYM_TYPE);
739       symbols[0].sym.StorageClass[0] = IMAGE_SYM_CLASS_FILE;
740       symbols[0].sym.NumberOfAuxSymbols[0] = 1;
741       snprintf ((char *)symbols[1].file.FileName,
742                 sizeof (symbols[1].file.FileName),
743                 "%s", lbasename (coff_file->base.filename));
744       write_err = (write (coff_file->fd, &symbols[0], sizeof (symbols))
745                 != (2 * COFF_SYMBOL_SIZE));
746
747       /* Set up constant parts for section sym loop.  */
748       memset (&symbols[0], 0, sizeof (symbols));
749       COFF_PUT(&symbols[0].sym, Type, IMAGE_SYM_TYPE);
750       symbols[0].sym.StorageClass[0] = IMAGE_SYM_CLASS_STATIC;
751       symbols[0].sym.NumberOfAuxSymbols[0] = 1;
752
753       secnum = 1;
754       if (!write_err)
755         COFF_FOR_ALL_SECTIONS(coff_file, cursec)
756           {
757             /* Skip dummy string section.  */
758             if (cursec->type == 1)
759               continue;
760             /* Reuse section name string for section symbol name.  */
761             COFF_PUT_NDXSZ(&symbols[0].sym, Name, 0, 0, 4);
762             COFF_PUT_NDXSZ(&symbols[0].sym, Name, cursec->strtab_offs + 4, 4, 4);
763             COFF_PUT(&symbols[0].sym, SectionNumber, secnum++);
764             COFF_PUT(&symbols[1].sec, Length,
765                         COFF_GET(&cursec->coffsec, SizeOfRawData));
766             if (!write_err)
767               write_err = (write (coff_file->fd, &symbols[0], sizeof (symbols))
768                         != (2 * COFF_SYMBOL_SIZE));
769             else
770               break;
771           }
772     }
773
774   /* Write the COFF string table.  */
775   if (!write_err)
776     {
777       unsigned char outlen[4];
778       COFF_PUT4(outlen, stringssize + 4);
779       if (!write_err)
780         write_err = (write (coff_file->fd, outlen, 4) != 4);
781       if (stringsec)
782         COFF_FOR_ALL_DATA(stringsec, data)
783           if (!write_err)
784         write_err = (write (coff_file->fd, data->d_buf, data->d_size)
785                         != data->d_size);
786         else
787           break;
788     }
789
790   return write_err;
791 }
792
793 /* Close COFF file FILE and clean up any associated data structures.  If FILE
794    was opened for writing, the file's COFF data is written at this time, and
795    any cached data buffers are freed.  */
796
797 void
798 lto_obj_file_close (lto_file *file)
799 {
800   lto_coff_file *coff_file = (lto_coff_file *) file;
801   struct lto_char_ptr_base *cur, *tmp;
802   lto_coff_section *cursec, *nextsec;
803   bool write_err = false;
804
805   /* Write the COFF string table into a dummy new section that
806      we will not write a header for.  */
807   if (coff_file->shstrtab_stream)
808     coff_write_object_file (coff_file);
809
810   /* Close the file, we're done.  */
811   if (coff_file->fd != -1)
812     close (coff_file->fd);
813
814   /* Free any data buffers.  */
815   cur = coff_file->data;
816   while (cur)
817     {
818       tmp = cur;
819       cur = (struct lto_char_ptr_base *) cur->ptr;
820       free (tmp);
821     }
822
823   /* Free any sections and their data chains.  */
824   cursec = coff_file->section_chain;
825   while (cursec)
826     {
827       lto_coff_data *curdata, *nextdata;
828       nextsec = cursec->next;
829       curdata = cursec->data_chain;
830       while (curdata)
831         {
832           nextdata = curdata->next;
833           free (curdata);
834           curdata = nextdata;
835         }
836       free (cursec);
837       cursec = nextsec;
838     }
839
840   free (file);
841
842   /* If there was an error, mention it.  */
843   if (write_err)
844     error ("I/O error writing COFF output file");
845 }
846