OSDN Git Service

ChangeLog:
[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 (COFF_CHARACTERISTICS != (COFF_CHARACTERISTICS & charact))
383     {
384       /* ECOFF/XCOFF/PE+ support not implemented.  */
385       error ("not a 32-bit COFF object file");
386       return false;
387     }
388
389   /* It validated OK, so cached it if we don't already have one.  */
390   if (!cached_coff_hdr_valid)
391     {
392       cached_coff_hdr_valid = true;
393       memcpy (&cached_coff_hdr, &coff_file->coffhdr, sizeof (cached_coff_hdr));
394     }
395
396   if (mach != COFF_GET(&cached_coff_hdr, Machine))
397     {
398       error ("inconsistent file architecture detected");
399       return false;
400     }
401
402   /* Read section headers and string table? */
403
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);
410
411 #define CVOFFSETTTED(x) (coff_file->base.offset + (x))
412
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))
417     {
418       error ("not a valid COFF object file");
419       return false;
420     }
421
422 #undef CVOFFSETTTED
423
424   /* Record start of string table.  */
425   coff_file->strtab_offs = stringsstart;
426
427   /* Validate section table entries.  */
428   for (secnum = 0; secnum < numsections; secnum++)
429     {
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;
434
435       n = read (coff_file->fd, &coffsec, sizeof (coffsec));
436       if (n != sizeof (coffsec))
437         {
438           error ("short/missing COFF section table");
439           return false;
440         }
441
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);
448
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)))
461         {
462           error ("invalid COFF section table");
463           return false;
464         }
465
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));
471     }
472
473   return true;
474 }
475
476 /* Initialize COFF_FILE's executable header using cached data from previously
477    read files.  */
478
479 static void
480 init_coffhdr (lto_coff_file *coff_file)
481 {
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));
486 }
487
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.  */
491
492 lto_file *
493 lto_obj_file_open (const char *filename, bool writable)
494 {
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;
501
502   offset_p = strchr (filename, '@');
503   if (!offset_p)
504     {
505       fname = xstrdup (filename);
506       offset = 0;
507     }
508   else
509     {
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);
515
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);
521     }
522
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;
528
529   /* Open the file.  */
530   coff_file->fd = open (fname,
531     O_BINARY | (writable ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY), 0666);
532
533   if (coff_file->fd == -1)
534     {
535       error ("could not open file %s", fname);
536       goto fail;
537     }
538
539   if (stat (fname, &statbuf) < 0)
540     {
541       error ("could not stat file %s", fname);
542       goto fail;
543     }
544
545   coff_file->file_size = statbuf.st_size;
546
547   if (offset != 0)
548     {
549       char ar_tail[12];
550       int size;
551
552       /* Surely not?  */
553       gcc_assert (!writable);
554
555       /* Seek to offset, or error.  */
556       if (lseek (coff_file->fd, offset, SEEK_SET) != (ssize_t) offset)
557         {
558           error ("could not find archive member @0x%lx", (long) offset);
559           goto fail;
560         }
561
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')
568         {
569           error ("could not find archive header @0x%lx", (long) offset);
570           goto fail;
571         }
572
573       ar_tail[11] = 0;
574       if (sscanf (ar_tail, "%d", &size) != 1)
575         {
576           error ("invalid archive header @0x%lx", (long) offset);
577           goto fail;
578         }
579       coff_file->file_size = size;
580     }
581
582   if (writable)
583     {
584       init_coffhdr (coff_file);
585       coff_file->shstrtab_stream = XCNEW (struct lto_output_stream);
586     }
587   else
588     if (!validate_file (coff_file))
589       goto fail;
590
591   return result;
592
593  fail:
594   if (result)
595     lto_obj_file_close (result);
596   return NULL;
597 }
598
599
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.  */
603
604 static bool
605 coff_write_object_file (lto_coff_file *coff_file)
606 {
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;
612
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
619     {
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);
629     }
630
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)
638     {
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)
645         {
646           ++numsections;
647           totalsecsize += COFF_ALIGN(cursecsize);
648 #if COFF_ALIGNMENT > 1
649           cursec->pad_needed = COFF_ALIGN(cursecsize) - cursecsize;
650 #endif
651         }
652       else
653         {
654           stringssize = cursecsize;
655           stringsec = cursec;
656         }
657       COFF_PUT(&cursec->coffsec, SizeOfRawData, cursecsize);
658     }
659
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);
663
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.  */
671
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)
675     {
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);
683     }
684
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.  */
688
689   /* Write the COFF header.  */
690   write_err = (write (coff_file->fd, &coff_file->coffhdr,
691                 sizeof (coff_file->coffhdr)) != sizeof (coff_file->coffhdr));
692
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;
702
703   /* Write the COFF sections.  */
704   COFF_FOR_ALL_SECTIONS(coff_file, cursec)
705     {
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
723     }
724
725   /* Write the COFF symbol table.  */
726   if (!write_err)
727     {
728       union
729         {
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));
745
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;
751
752       secnum = 1;
753       if (!write_err)
754         COFF_FOR_ALL_SECTIONS(coff_file, cursec)
755           {
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;
770           }
771     }
772
773   /* Write the COFF string table.  */
774   if (!write_err)
775     {
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;
787     }
788
789   return write_err;
790 }
791
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.  */
795
796 void
797 lto_obj_file_close (lto_file *file)
798 {
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;
803
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);
808
809   /* Close the file, we're done.  */
810   if (coff_file->fd != -1)
811     close (coff_file->fd);
812
813   /* Free any data buffers.  */
814   cur = coff_file->data;
815   while (cur)
816     {
817       tmp = cur;
818       cur = (struct lto_char_ptr_base *) cur->ptr;
819       free (tmp);
820     }
821
822   /* Free any sections and their data chains.  */
823   cursec = coff_file->section_chain;
824   while (cursec)
825     {
826       lto_coff_data *curdata, *nextdata;
827       nextsec = cursec->next;
828       curdata = cursec->data_chain;
829       while (curdata)
830         {
831           nextdata = curdata->next;
832           free (curdata);
833           curdata = nextdata;
834         }
835       free (cursec);
836       cursec = nextsec;
837     }
838
839   free (file);
840
841   /* If there was an error, mention it.  */
842   if (write_err)
843     error ("I/O error writing COFF output file");
844 }
845