1 /* LTO routines for COFF object files.
2 Copyright 2009 Free Software Foundation, Inc.
3 Contributed by Dave Korn.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "libiberty.h"
29 #include "lto-streamer.h"
30 #include "lto/lto-coff.h"
33 /* Rather than implementing a libcoff to match libelf, or attempting to
34 integrate libbfd into GCC, this file is a self-contained (and very
35 minimal) COFF format object file reader/writer. The generated files
36 will contain a COFF header, a number of COFF section headers, the
37 section data itself, and a trailing string table for section names. */
39 /* Handle opening elf files on hosts, such as Windows, that may use
40 text file handling that will break binary access. */
46 /* Known header magics for validation, as an array. */
48 static const unsigned int coff_machine_array[] = COFF_KNOWN_MACHINES;
50 /* Number of valid entries (no sentinel) in array. */
52 #define NUM_COFF_KNOWN_MACHINES \
53 (sizeof (coff_machine_array) / sizeof (coff_machine_array[0]))
55 /* Cached object file header. */
57 static Coff_header cached_coff_hdr;
59 /* Flag to indicate if we have read and cached any header yet. */
61 static bool cached_coff_hdr_valid = false;
63 /* The current output file. */
65 static lto_file *current_out_file;
68 /* Sets the current output file to FILE. Returns the old output file or
72 lto_set_current_out_file (lto_file *file)
74 lto_file *old_file = current_out_file;
75 current_out_file = file;
80 /* Returns the current output file. */
83 lto_get_current_out_file (void)
85 return current_out_file;
89 /* COFF section structure constructor. */
91 static lto_coff_section *
92 coff_newsection (lto_coff_file *file, const char *name, size_t type)
94 lto_coff_section *ptr, **chain_ptr_ptr;
96 ptr = XCNEW (lto_coff_section);
100 chain_ptr_ptr = &file->section_chain;
101 while (*chain_ptr_ptr)
102 chain_ptr_ptr = &(*chain_ptr_ptr)->next;
103 *chain_ptr_ptr = ptr;
109 /* COFF section data block structure constructor. */
111 static lto_coff_data *
112 coff_newdata (lto_coff_section *sec)
114 lto_coff_data *ptr, **chain_ptr_ptr;
116 ptr = XCNEW (lto_coff_data);
118 chain_ptr_ptr = &sec->data_chain;
119 while (*chain_ptr_ptr)
120 chain_ptr_ptr = &(*chain_ptr_ptr)->next;
121 *chain_ptr_ptr = ptr;
127 /* Initialize FILE, an LTO file object for FILENAME. */
130 lto_file_init (lto_file *file, const char *filename, off_t offset)
132 file->filename = filename;
133 file->offset = offset;
136 /* Return an error string after an error, or a predetermined one
137 if ERRCODE is not -1. */
140 coff_errmsg (int errcode)
142 return strerror (errcode == -1 ? errno : errcode);
145 /* Returns a hash code for P. */
148 hash_name (const void *p)
150 const struct lto_section_slot *ds = (const struct lto_section_slot *) p;
151 return (hashval_t) htab_hash_string (ds->name);
154 /* Returns nonzero if P1 and P2 are equal. */
157 eq_name (const void *p1, const void *p2)
159 const struct lto_section_slot *s1 =
160 (const struct lto_section_slot *) p1;
161 const struct lto_section_slot *s2 =
162 (const struct lto_section_slot *) p2;
164 return strcmp (s1->name, s2->name) == 0;
168 /* Build a hash table whose key is the section names and whose data is
169 the start and size of each section in the .o file. */
172 lto_obj_build_section_table (lto_file *lto_file)
174 lto_coff_file *coff_file = (lto_coff_file *)lto_file;
175 lto_coff_section *sec;
176 htab_t section_hash_table;
180 section_hash_table = htab_create (37, hash_name, eq_name, free);
182 /* Seek to start of string table. */
183 if (coff_file->strtab_offs != lseek (coff_file->fd,
184 coff_file->base.offset + coff_file->strtab_offs, SEEK_SET))
186 error ("altered or invalid COFF object file");
187 return section_hash_table;
190 strtab_size = coff_file->file_size - coff_file->strtab_offs;
191 strtab = XNEWVEC (char, strtab_size);
192 if (read (coff_file->fd, strtab, strtab_size) != strtab_size)
194 error ("invalid COFF object file string table");
195 return section_hash_table;
198 /* Scan sections looking at names. */
199 COFF_FOR_ALL_SECTIONS(coff_file, sec)
201 struct lto_section_slot s_slot;
205 char *name = (char *) &sec->coffsec.Name[0];
207 /* Skip dummy string section if by any chance we see it. */
213 if (1 != sscanf (&name[1], "%d", &stringoffset)
214 || stringoffset < 0 || stringoffset >= strtab_size)
216 error ("invalid COFF section name string");
219 name = strtab + stringoffset;
223 /* If we cared about the VirtualSize field, we couldn't
224 crudely trash it like this to guarantee nul-termination
225 of the Name field. But we don't, so we do. */
228 if (strncmp (name, LTO_SECTION_NAME_PREFIX,
229 strlen (LTO_SECTION_NAME_PREFIX)) != 0)
232 new_name = XNEWVEC (char, strlen (name) + 1);
233 strcpy (new_name, name);
234 s_slot.name = new_name;
235 slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
238 struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
240 new_slot->name = new_name;
241 /* The offset into the file for this section. */
242 new_slot->start = coff_file->base.offset
243 + COFF_GET(&sec->coffsec,PointerToRawData);
244 new_slot->len = COFF_GET(&sec->coffsec,SizeOfRawData);
249 error ("two or more sections for %s:", new_name);
255 return section_hash_table;
259 /* Begin a new COFF section named NAME with type TYPE in the current output
260 file. TYPE is an SHT_* macro from the libelf headers. */
263 lto_coff_begin_section_with_type (const char *name, size_t type)
268 /* Grab the current output file and do some basic assertion checking. */
269 file = (lto_coff_file *) lto_get_current_out_file (),
271 gcc_assert (!file->scn);
273 /* Create a new section. */
274 file->scn = coff_newsection (file, name, type);
276 fatal_error ("could not create a new COFF section: %s", coff_errmsg (-1));
278 /* Add a string table entry and record the offset. */
279 gcc_assert (file->shstrtab_stream);
280 sh_name = file->shstrtab_stream->total_size;
281 lto_output_data_stream (file->shstrtab_stream, name, strlen (name) + 1);
283 /* Initialize the section header. */
284 file->scn->strtab_offs = sh_name;
288 /* Begin a new COFF section named NAME in the current output file. */
291 lto_obj_begin_section (const char *name)
293 lto_coff_begin_section_with_type (name, 0);
297 /* Append DATA of length LEN to the current output section. BASE is a pointer
298 to the output page containing DATA. It is freed once the output file has
302 lto_obj_append_data (const void *data, size_t len, void *block)
305 lto_coff_data *coff_data;
306 struct lto_char_ptr_base *base = (struct lto_char_ptr_base *) block;
308 /* Grab the current output file and do some basic assertion checking. */
309 file = (lto_coff_file *) lto_get_current_out_file ();
311 gcc_assert (file->scn);
313 coff_data = coff_newdata (file->scn);
315 fatal_error ("could not append data to COFF section: %s", coff_errmsg (-1));
317 coff_data->d_buf = CONST_CAST (void *, data);
318 coff_data->d_size = len;
320 /* Chain all data blocks (from all sections) on one singly-linked
321 list for freeing en masse after the file is closed. */
322 base->ptr = (char *)file->data;
327 /* End the current output section. This just does some assertion checking
328 and sets the current output file's scn member to NULL. */
331 lto_obj_end_section (void)
335 /* Grab the current output file and validate some basic assertions. */
336 file = (lto_coff_file *) lto_get_current_out_file ();
338 gcc_assert (file->scn);
344 /* Validate's COFF_FILE's executable header and, if cached_coff_hdr is
345 uninitialized, caches the results. Also records the section header string
346 table's section index. Returns true on success or false on failure. */
349 validate_file (lto_coff_file *coff_file)
352 unsigned int numsections, secheaderssize, numsyms;
353 off_t sectionsstart, symbolsstart, stringsstart;
354 unsigned int mach, charact;
356 /* Read and sanity check the raw header. */
357 n = read (coff_file->fd, &coff_file->coffhdr, sizeof (coff_file->coffhdr));
358 if (n != sizeof (coff_file->coffhdr))
360 error ("not a COFF object file");
364 mach = COFF_GET(&coff_file->coffhdr, Machine);
365 for (n = 0; n < NUM_COFF_KNOWN_MACHINES; n++)
366 if (mach == coff_machine_array[n])
368 if (n == NUM_COFF_KNOWN_MACHINES)
370 error ("not a recognized COFF object file");
374 charact = COFF_GET(&coff_file->coffhdr, Characteristics);
375 if (COFF_NOT_CHARACTERISTICS & charact)
377 /* DLL, EXE or SYS file. */
378 error ("not a relocatable COFF object file");
382 if (mach != IMAGE_FILE_MACHINE_AMD64
383 && COFF_CHARACTERISTICS != (COFF_CHARACTERISTICS & charact))
385 /* ECOFF/XCOFF support not implemented. */
386 error ("not a 32-bit COFF object file");
390 /* It validated OK, so cached it if we don't already have one. */
391 if (!cached_coff_hdr_valid)
393 cached_coff_hdr_valid = true;
394 memcpy (&cached_coff_hdr, &coff_file->coffhdr, sizeof (cached_coff_hdr));
397 if (mach != COFF_GET(&cached_coff_hdr, Machine))
399 error ("inconsistent file architecture detected");
403 /* Read section headers and string table? */
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);
412 #define CVOFFSETTTED(x) (coff_file->base.offset + (x))
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))
419 error ("not a valid COFF object file");
425 /* Record start of string table. */
426 coff_file->strtab_offs = stringsstart;
428 /* Validate section table entries. */
429 for (secnum = 0; secnum < numsections; secnum++)
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;
436 n = read (coff_file->fd, &coffsec, sizeof (coffsec));
437 if (n != sizeof (coffsec))
439 error ("short/missing COFF section table");
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);
450 if (size_raw < 0 || num_relocs < 0 || num_lines < 0
452 && ((COFF_GET(&coffsec, Characteristics)
453 & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
455 : (offs_raw < sectionsstart || offs_raw >= coff_file->file_size)))
457 && (offs_relocs < sectionsstart
458 || offs_relocs >= coff_file->file_size))
460 && (offs_lines < sectionsstart
461 || offs_lines >= coff_file->file_size)))
463 error ("invalid COFF section table");
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 (<osec->coffsec, &coffsec, sizeof (ltosec->coffsec));
477 /* Initialize COFF_FILE's executable header using cached data from previously
481 init_coffhdr (lto_coff_file *coff_file)
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));
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. */
494 lto_obj_file_open (const char *filename, bool writable)
496 lto_coff_file *coff_file;
497 lto_file *result = NULL;
499 const char *offset_p;
503 offset_p = strchr (filename, '@');
506 fname = xstrdup (filename);
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",
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);
525 coff_file = XCNEW (lto_coff_file);
526 result = (lto_file *) coff_file;
527 lto_file_init (result, fname, offset);
531 coff_file->fd = open (fname,
532 O_BINARY | (writable ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY), 0666);
534 if (coff_file->fd == -1)
536 error ("could not open file %s", fname);
540 if (stat (fname, &statbuf) < 0)
542 error ("could not stat file %s", fname);
546 coff_file->file_size = statbuf.st_size;
554 gcc_assert (!writable);
556 /* Seek to offset, or error. */
557 if (lseek (coff_file->fd, offset, SEEK_SET) != (ssize_t) offset)
559 error ("could not find archive member @0x%lx", (long) offset);
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')
570 error ("could not find archive header @0x%lx", (long) offset);
575 if (sscanf (ar_tail, "%d", &size) != 1)
577 error ("invalid archive header @0x%lx", (long) offset);
580 coff_file->file_size = size;
585 init_coffhdr (coff_file);
586 coff_file->shstrtab_stream = XCNEW (struct lto_output_stream);
589 if (!validate_file (coff_file))
596 lto_obj_file_close (result);
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. */
606 coff_write_object_file (lto_coff_file *coff_file)
608 lto_coff_section *cursec, *stringsec;
610 size_t fileoffset, numsections, totalsecsize, numsyms, stringssize;
611 bool write_err = false;
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)
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);
632 /* Layout the file. Count sections (not dummy string section) and calculate
633 data size for all of them. */
638 COFF_FOR_ALL_SECTIONS(coff_file, cursec)
643 COFF_FOR_ALL_DATA(cursec,data)
644 cursecsize += data->d_size;
645 if (cursec->type == 0)
648 totalsecsize += COFF_ALIGN(cursecsize);
649 #if COFF_ALIGNMENT > 1
650 cursec->pad_needed = COFF_ALIGN(cursecsize) - cursecsize;
655 stringssize = cursecsize;
658 COFF_PUT(&cursec->coffsec, SizeOfRawData, cursecsize);
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);
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. */
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)
677 /* Skip dummy string section. */
678 if (cursec->type == 1)
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);
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. */
690 /* Write the COFF header. */
691 write_err = (write (coff_file->fd, &coff_file->coffhdr,
692 sizeof (coff_file->coffhdr)) != sizeof (coff_file->coffhdr));
694 /* Write the COFF section headers. */
695 COFF_FOR_ALL_SECTIONS(coff_file, cursec)
696 if (cursec->type == 1) /* Skip dummy string section. */
699 write_err = (write (coff_file->fd, &cursec->coffsec,
700 sizeof (cursec->coffsec)) != sizeof (cursec->coffsec));
704 /* Write the COFF sections. */
705 COFF_FOR_ALL_SECTIONS(coff_file, cursec)
707 #if COFF_ALIGNMENT > 1
708 static const char padzeros[COFF_ALIGNMENT] = { 0 };
710 /* Skip dummy string section. */
711 if (cursec->type == 1)
713 COFF_FOR_ALL_DATA(cursec, data)
715 write_err = (write (coff_file->fd, data->d_buf, data->d_size)
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);
726 /* Write the COFF symbol table. */
732 Coff_aux_sym_file file;
733 Coff_aux_sym_section sec;
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));
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;
755 COFF_FOR_ALL_SECTIONS(coff_file, cursec)
757 /* Skip dummy string section. */
758 if (cursec->type == 1)
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));
767 write_err = (write (coff_file->fd, &symbols[0], sizeof (symbols))
768 != (2 * COFF_SYMBOL_SIZE));
774 /* Write the COFF string table. */
777 unsigned char outlen[4];
778 COFF_PUT4(outlen, stringssize + 4);
780 write_err = (write (coff_file->fd, outlen, 4) != 4);
782 COFF_FOR_ALL_DATA(stringsec, data)
784 write_err = (write (coff_file->fd, data->d_buf, data->d_size)
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. */
798 lto_obj_file_close (lto_file *file)
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;
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);
810 /* Close the file, we're done. */
811 if (coff_file->fd != -1)
812 close (coff_file->fd);
814 /* Free any data buffers. */
815 cur = coff_file->data;
819 cur = (struct lto_char_ptr_base *) cur->ptr;
823 /* Free any sections and their data chains. */
824 cursec = coff_file->section_chain;
827 lto_coff_data *curdata, *nextdata;
828 nextsec = cursec->next;
829 curdata = cursec->data_chain;
832 nextdata = curdata->next;
842 /* If there was an error, mention it. */
844 error ("I/O error writing COFF output file");