Remove outermost loop parameter.
[official-gcc/graphite-test-results.git] / gcc / lto / lto-macho.c
blob1ba74c0a3a0d281a986dc140ea96454a71c7f185
1 /* LTO routines for Mach-O object files.
2 Copyright 2010 Free Software Foundation, Inc.
3 Contributed by Steven Bosscher.
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 "lto-streamer.h"
29 #include "lto/lto-endian.h"
30 #include "lto/lto-macho.h"
32 /* Rather than implementing a libmacho to match libelf, or attempting to
33 integrate libbfd into GCC, this file is a self-contained (and very
34 minimal) Mach-O format object file reader/writer. The generated files
35 will contain a Mach-O header, a number of Mach-O load commands an
36 section headers, the section data itself, and a trailing string table
37 for section names. */
39 /* This needs to be kept in sync with darwin.c. Better yet, lto-macho.c
40 and lto-macho.h should be moved to config/, and likewise for lto-coff.*
41 and lto-elf.*. */
43 /* Segment name for LTO sections. */
44 #define LTO_SEGMENT_NAME "__GNU_LTO"
46 /* Section name for LTO section names section. */
47 #define LTO_NAMES_SECTION "__section_names"
49 /* Handle opening elf files on hosts, such as Windows, that may use
50 text file handling that will break binary access. */
51 #ifndef O_BINARY
52 # define O_BINARY 0
53 #endif
55 /* Cached object file header. We use a header_64 for this, since all
56 the fields we need are in there, in the same position as header_32. */
57 mach_o_header_64 cached_mach_o_header;
58 uint32_t cached_mach_o_magic;
60 /* The current output file. */
61 static lto_file *current_out_file;
64 /* Is this a 32-bits or 64-bits Mach-O object file? */
65 static int
66 mach_o_word_size (void)
68 gcc_assert (cached_mach_o_magic != 0);
69 return (cached_mach_o_magic == MACH_O_MH_MAGIC_64
70 || cached_mach_o_magic == MACH_O_MH_CIGAM_64) ? 64 : 32;
73 /* Sets the current output file to FILE. Returns the old output file or
74 NULL. */
76 lto_file *
77 lto_set_current_out_file (lto_file *file)
79 lto_file *old_file = current_out_file;
80 current_out_file = file;
81 return old_file;
85 /* Returns the current output file. */
87 lto_file *
88 lto_get_current_out_file (void)
90 return current_out_file;
93 /* Mach-O section structure constructor. */
95 static lto_mach_o_section
96 mach_o_new_section (lto_mach_o_file *mach_o_file, const char *name)
98 lto_mach_o_section ptr;
100 /* FIXME We could allocate these things on an obstack. */
101 ptr = XCNEW (struct lto_mach_o_section_d);
102 if (name)
104 if (strncmp (name, LTO_SECTION_NAME_PREFIX,
105 strlen(LTO_SECTION_NAME_PREFIX)) != 0)
106 sorry ("not implemented: Mach-O writer for non-LTO sections");
107 ptr->name = xstrdup (name);
110 VEC_safe_push (lto_mach_o_section, heap, mach_o_file->section_vec, ptr);
112 return ptr;
115 /* Mach-O section data block structure constructor. */
117 static lto_mach_o_data
118 mach_o_new_data (lto_mach_o_section sec)
120 lto_mach_o_data ptr, *chain_ptr_ptr;
122 /* FIXME We could allocate these things on an obstack. */
123 ptr = XCNEW (struct lto_mach_o_data_d);
125 chain_ptr_ptr = &sec->data_chain;
126 while (*chain_ptr_ptr)
127 chain_ptr_ptr = &(*chain_ptr_ptr)->next;
128 *chain_ptr_ptr = ptr;
130 return ptr;
133 /* Initialize FILE, an LTO file object for FILENAME. Offset is the
134 offset into FILE where the object is located (e.g. in an archive). */
136 static void
137 lto_file_init (lto_file *file, const char *filename, off_t offset)
139 file->filename = filename;
140 file->offset = offset;
143 /* Returns a hash code for P. */
145 static hashval_t
146 hash_name (const void *p)
148 const struct lto_section_slot *s = (const struct lto_section_slot *) p;
149 return (hashval_t) htab_hash_string (s->name);
152 /* Returns nonzero if P1 and P2 are equal. */
154 static int
155 eq_name (const void *p1, const void *p2)
157 const struct lto_section_slot *s1 =
158 (const struct lto_section_slot *) p1;
159 const struct lto_section_slot *s2 =
160 (const struct lto_section_slot *) p2;
162 return strcmp (s1->name, s2->name) == 0;
165 /* Build a hash table whose key is the section names and whose data is
166 the start and size of each section in the .o file. */
168 htab_t
169 lto_obj_build_section_table (lto_file *lto_file)
171 lto_mach_o_file *mach_o_file = (lto_mach_o_file *)lto_file;
172 lto_mach_o_section sec;
173 htab_t section_hash_table;
174 off_t strtab_offs;
175 ssize_t strtab_size;
176 char *strtab = NULL;
177 int i;
179 section_hash_table = htab_create (37, hash_name, eq_name, free);
181 /* Seek the string table. */
182 /* FIXME The segment name should be in darwin.h, but can we include it
183 here in this file? */
184 for (i = 0;
185 VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
186 i++)
188 if (strncmp (sec->u.section.segname, "__GNU_LTO", 16) != 0)
189 continue;
190 if (strncmp (sec->u.section.sectname, "__section_names", 16) == 0)
191 break;
193 if (! sec)
195 error ("invalid Mach-O LTO object file: no __section_names section found");
196 goto done;
198 mach_o_file->section_names_section = sec;
200 if (mach_o_word_size () == 64)
202 strtab_offs = (off_t) get_uint32 (&sec->u.section_64.offset[0]);
203 strtab_size = (size_t) get_uint64 (&sec->u.section_64.size[0]);
205 else
207 strtab_offs = (off_t) get_uint32 (&sec->u.section_32.offset[0]);
208 strtab_size = (size_t) get_uint32 (&sec->u.section_32.size[0]);
211 /* Seek to start of string table. */
212 if (strtab_offs != lseek (mach_o_file->fd,
213 mach_o_file->base.offset + strtab_offs,
214 SEEK_SET))
216 error ("altered or invalid Mach-O object file");
217 goto done;
220 strtab = XNEWVEC (char, strtab_size);
221 if (read (mach_o_file->fd, strtab, strtab_size) != strtab_size)
223 error ("invalid Mach-O LTO object file __section_names section");
224 goto done;
227 /* Scan sections looking at names. */
228 for (i = 0;
229 VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
230 i++)
232 struct lto_section_slot s_slot;
233 void **slot;
234 char *new_name;
235 unsigned long stringoffset;
236 char name[17];
238 /* Ignore non-LTO sections. Also ignore the __section_names section
239 which does not need renaming. */
240 if (strncmp (sec->u.section.segname, "__GNU_LTO", 16) != 0)
241 continue;
242 if (sec == mach_o_file->section_names_section)
243 continue;
245 /* Try to extract the offset of the real name for this section from
246 __section_names. */
247 memcpy (&name[0], sec->u.section.sectname, 16);
248 name[16] = '\0';
249 if (name[0] != '_' || name[1] != '_'
250 || sscanf (&name[2], "%08lX", &stringoffset) != 1
251 || strtab_size < (ssize_t) stringoffset)
253 error ("invalid Mach-O LTO section name string: %s", name);
254 continue;
257 new_name = XNEWVEC (char, strlen (strtab + stringoffset) + 1);
258 strcpy (new_name, strtab + stringoffset);
259 s_slot.name = new_name;
260 slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
261 if (*slot == NULL)
263 struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
265 new_slot->name = new_name;
266 if (mach_o_word_size() == 64)
268 new_slot->start =
269 (intptr_t) get_uint32 (&sec->u.section_64.offset[0]);
270 new_slot->len =
271 (size_t) get_uint64 (&sec->u.section_64.size[0]);
273 else
275 new_slot->start =
276 (intptr_t) get_uint32 (&sec->u.section_32.offset[0]);
277 new_slot->len =
278 (size_t) get_uint32 (&sec->u.section_32.size[0]);
281 *slot = new_slot;
283 else
285 error ("two or more sections for %s:", new_name);
286 goto done;
290 done:
291 if (strtab)
292 free (strtab);
293 return section_hash_table;
297 /* Begin a new Mach-O section named NAME in the current output file. */
299 void
300 lto_obj_begin_section (const char *name)
302 lto_mach_o_file *file;
304 if (strncmp (name, LTO_SECTION_NAME_PREFIX,
305 strlen(LTO_SECTION_NAME_PREFIX)) != 0)
306 sorry ("not implemented: Mach-O writer for non-LTO sections");
308 /* Grab the current output file and do some basic assertion checking. */
309 file = (lto_mach_o_file *) lto_get_current_out_file (),
310 gcc_assert (file && file->writable && !file->scn);
312 /* Create a new section. */
313 file->scn = mach_o_new_section (file, name);
314 if (!file->scn)
315 fatal_error ("could not create a new Mach-O section: %m");
319 /* Append DATA of length LEN to the current output section. BASE is a pointer
320 to the output page containing DATA. It is freed once the output file has
321 been written. */
323 void
324 lto_obj_append_data (const void *data, size_t len, void *block)
326 lto_mach_o_file *file;
327 lto_mach_o_data mach_o_data;
328 struct lto_char_ptr_base *base = (struct lto_char_ptr_base *) block;
330 /* Grab the current output file and do some basic assertion checking. */
331 file = (lto_mach_o_file *) lto_get_current_out_file ();
332 gcc_assert (file);
333 gcc_assert (file->scn);
335 mach_o_data = mach_o_new_data (file->scn);
336 if (!mach_o_data)
337 fatal_error ("could not append data to Mach-O section: %m");
339 mach_o_data->d_buf = CONST_CAST (void *, data);
340 mach_o_data->d_size = len;
342 /* Chain all data blocks (from all sections) on one singly-linked
343 list for freeing en masse after the file is closed. */
344 base->ptr = (char *)file->data;
345 file->data = base;
349 /* End the current output section. This just does some assertion checking
350 and sets the current output file's scn member to NULL. */
352 void
353 lto_obj_end_section (void)
355 lto_mach_o_file *file;
357 /* Grab the current output file and validate some basic assertions. */
358 file = (lto_mach_o_file *) lto_get_current_out_file ();
359 gcc_assert (file);
360 gcc_assert (file->scn);
362 file->scn = NULL;
366 /* Read a Mach-O header from MACH_O_FILE and validate it.
367 The file descriptor in MACH_O_FILE points at the start of the file.
368 If cached_mach_o_header is uninitialized, caches the results.
369 On succes, returns true and moves file pointer to the start of the
370 load commands. On failure, returns false. */
372 static bool
373 validate_mach_o_header (lto_mach_o_file *mach_o_file)
375 ssize_t i, n;
376 unsigned char magic[4];
377 uint32_t cputype;
378 off_t startpos;
380 /* Known header magics for validation, as an array. */
381 static const unsigned int mach_o_known_formats[] = {
382 MACH_O_MH_MAGIC,
383 MACH_O_MH_CIGAM,
384 MACH_O_MH_MAGIC_64,
385 MACH_O_MH_CIGAM_64,
387 #define MACH_O_NUM_KNOWN_FORMATS \
388 ((ssize_t) ARRAY_SIZE (mach_o_known_formats))
390 startpos = lseek (mach_o_file->fd, 0, SEEK_CUR);
391 if (read (mach_o_file->fd, &magic, sizeof (magic)) != 4
392 || lseek (mach_o_file->fd, -4, SEEK_CUR) != startpos)
394 error ("cannot read file %s", mach_o_file->base.filename);
395 return false;
398 for (i = 0; i < MACH_O_NUM_KNOWN_FORMATS; ++i)
399 if (get_uint32 (&magic[0]) == mach_o_known_formats[i])
400 break;
401 if (i == MACH_O_NUM_KNOWN_FORMATS)
402 goto not_for_target;
404 /* Check the endian-ness. */
405 if (BYTES_BIG_ENDIAN && magic[0] != 0xfe)
406 goto not_for_target;
408 /* Set or check cached magic number. */
409 if (cached_mach_o_magic == 0)
410 cached_mach_o_magic = get_uint32 (&magic[0]);
411 else if (cached_mach_o_magic != get_uint32 (&magic[0]))
412 goto not_for_target;
414 n = mach_o_word_size () == 64
415 ? sizeof (mach_o_header_64) : sizeof (mach_o_header_32);
416 if (read (mach_o_file->fd, &mach_o_file->u.header, n) != n)
417 goto not_for_target;
419 /* Is this a supported CPU? */
420 /* ??? Would be nice to validate the exact target architecture. */
421 cputype = get_uint32 (&mach_o_file->u.header.cputype[0]);
422 if (cputype == MACH_O_CPU_TYPE_I386
423 || cputype == MACH_O_CPU_TYPE_POWERPC)
425 if (mach_o_word_size () != 32)
426 goto not_for_target;
428 else if (cputype == MACH_O_CPU_TYPE_X86_64
429 || cputype == MACH_O_CPU_TYPE_POWERPC_64)
431 if (mach_o_word_size () != 64)
432 goto not_for_target;
435 /* Is this an MH_OBJECT file? */
436 if (get_uint32 (&mach_o_file->u.header.filetype[0]) != MACH_O_MH_OBJECT)
437 error ("Mach-O file %s is not an MH_OBJECT file",
438 mach_o_file->base.filename);
440 /* Save the header for future use. */
441 memcpy (&cached_mach_o_header, &mach_o_file->u.header,
442 sizeof (cached_mach_o_header));
444 return true;
446 not_for_target:
447 error ("file %s is not a Mach-O object file for target",
448 mach_o_file->base.filename);
449 return false;
453 /* Read a Mach-O LC_SEGMENT command (32 bits) from MACH_O_FILE and
454 validate it.
455 The file descriptor in MACH_O_FILE points at the start of the load
456 command. On sucess, returns true and advances the file pointer
457 past the end of the load command. On failure, returns false. */
459 static bool
460 validate_mach_o_segment_command_32 (lto_mach_o_file *mach_o_file)
462 mach_o_segment_command_32 seg_cmd_32;
463 unsigned int i;
464 ssize_t n;
465 off_t startpos;
467 /* Fields we're interested in. */
468 uint32_t cmd;
469 uint32_t cmdsize;
470 uint32_t nsects;
472 startpos = lseek (mach_o_file->fd, 0, SEEK_CUR);
474 n = sizeof (mach_o_segment_command_32);
475 if (read (mach_o_file->fd, (void *) &seg_cmd_32, n) != n)
476 goto fail;
478 cmd = get_uint32 (&seg_cmd_32.cmd[0]);
479 cmdsize = get_uint32 (&seg_cmd_32.cmdsize[0]);
480 nsects = get_uint32 (&seg_cmd_32.nsects[0]);
481 gcc_assert (cmd == MACH_O_LC_SEGMENT);
483 /* Validate section table entries. */
484 for (i = 0; i < nsects; i++)
486 mach_o_section_32 sec_32;
487 lto_mach_o_section ltosec;
489 n = sizeof (mach_o_section_32);
490 if (read (mach_o_file->fd, &sec_32, n) != n)
491 goto fail;
493 /* ??? Perform some checks. */
495 /* Looks ok, so record its details. We don't read the
496 string table or set up names yet; we'll do that when
497 we build the hash table. */
498 ltosec = mach_o_new_section (mach_o_file, NULL);
499 memcpy (&ltosec->u.section_32, &sec_32, sizeof (sec_32));
502 if (lseek (mach_o_file->fd, 0, SEEK_CUR) != startpos + cmdsize)
503 goto fail;
505 return true;
507 fail:
508 error ("could not read LC_SEGMENT command in Mach-O file %s",
509 mach_o_file->base.filename);
510 return false;
514 /* Read a Mach-O LC_SEGMENT_64 command from MACH_O_FILE and validate it.
515 The file descriptor in MACH_O_FILE points at the start of the load
516 command. On sucess, returns true and advances the file pointer
517 past the end of the load command. On failure, returns false. */
519 static bool
520 validate_mach_o_segment_command_64 (lto_mach_o_file *mach_o_file)
522 mach_o_segment_command_64 seg_cmd_64;
523 unsigned int i;
524 ssize_t n;
525 off_t startpos;
527 /* Fields we're interested in. */
528 uint32_t cmd;
529 uint32_t cmdsize;
530 uint32_t nsects;
532 startpos = lseek (mach_o_file->fd, 0, SEEK_CUR);
534 n = sizeof (mach_o_segment_command_64);
535 if (read (mach_o_file->fd, (void *) &seg_cmd_64, n) != n)
536 goto fail;
538 cmd = get_uint32 (&seg_cmd_64.cmd[0]);
539 cmdsize = get_uint32 (&seg_cmd_64.cmdsize[0]);
540 nsects = get_uint32 (&seg_cmd_64.nsects[0]);
541 gcc_assert (cmd == MACH_O_LC_SEGMENT_64);
543 /* Validate section table entries. */
544 for (i = 0; i < nsects; i++)
546 mach_o_section_64 sec_64;
547 lto_mach_o_section ltosec;
549 n = sizeof (mach_o_section_64);
550 if (read (mach_o_file->fd, &sec_64, n) != n)
551 goto fail;
553 /* ??? Perform some checks. */
555 /* Looks ok, so record its details. We don't read the
556 string table or set up names yet; we'll do that when
557 we build the hash table. */
558 ltosec = mach_o_new_section (mach_o_file, NULL);
559 memcpy (&ltosec->u.section_64, &sec_64, sizeof (sec_64));
562 if (lseek (mach_o_file->fd, 0, SEEK_CUR) != startpos + cmdsize)
563 goto fail;
565 return true;
567 fail:
568 error ("could not read LC_SEGMENT_64 command in Mach-O file %s",
569 mach_o_file->base.filename);
570 return false;
573 /* Read a Mach-O load commands from MACH_O_FILE and validate it.
574 The file descriptor in MACH_O_FILE points at the start of the load
575 command. On sucess, returns true and advances the file pointer
576 past the end of the load command. On failure, returns false. */
578 static bool
579 validate_mach_o_load_command (lto_mach_o_file *mach_o_file)
581 mach_o_load_command load_command;
582 uint32_t cmd;
583 uint32_t cmdsize;
584 ssize_t n;
586 n = sizeof (load_command);
587 if (read (mach_o_file->fd, &load_command, n) != n)
589 error ("could not read load commands in Mach-O file %s",
590 mach_o_file->base.filename);
591 return false;
593 lseek (mach_o_file->fd, -1 * (off_t) sizeof (load_command), SEEK_CUR);
595 cmd = get_uint32 (&load_command.cmd[0]);
596 cmdsize = get_uint32 (&load_command.cmdsize[0]);
597 switch (cmd)
599 case MACH_O_LC_SEGMENT:
600 return validate_mach_o_segment_command_32 (mach_o_file);
601 case MACH_O_LC_SEGMENT_64:
602 return validate_mach_o_segment_command_64 (mach_o_file);
604 default:
605 /* Just skip over it. */
606 lseek (mach_o_file->fd, cmdsize, SEEK_CUR);
607 return true;
611 /* Validate's MACH_O_FILE's executable header and, if cached_mach_o_header is
612 uninitialized, caches the results. Also records the section header string
613 table's section index. Returns true on success, false on failure. */
615 static bool
616 validate_file (lto_mach_o_file *mach_o_file)
618 uint32_t i, ncmds;
620 /* Read and sanity check the raw header. */
621 if (! validate_mach_o_header (mach_o_file))
622 return false;
624 ncmds = get_uint32 (&mach_o_file->u.header.ncmds[0]);
625 for (i = 0; i < ncmds; ++i)
626 if (! validate_mach_o_load_command (mach_o_file))
627 return false;
629 return true;
632 /* Initialize MACH_O_FILE's executable header using cached data from previously
633 read files. */
635 static void
636 init_mach_o_header (lto_mach_o_file *mach_o_file)
638 gcc_assert (cached_mach_o_magic != 0);
639 memcpy (&mach_o_file->u.header,
640 &cached_mach_o_header,
641 sizeof (mach_o_file->u.header));
642 put_uint32 (&mach_o_file->u.header.ncmds[0], 0);
643 put_uint32 (&mach_o_file->u.header.sizeofcmds[0], 0);
646 /* Open Mach-O file FILENAME. If WRITABLE is true, the file is opened for write
647 and, if necessary, created. Otherwise, the file is opened for reading.
648 Returns the opened file. */
650 lto_file *
651 lto_obj_file_open (const char *filename, bool writable)
653 lto_mach_o_file *mach_o_file;
654 lto_file *result = NULL;
655 off_t offset;
656 const char *offset_p;
657 char *fname;
658 struct stat statbuf;
660 offset_p = strchr (filename, '@');
661 if (!offset_p)
663 fname = xstrdup (filename);
664 offset = 0;
666 else
668 /* The file started with '@' is a file containing command line
669 options. Stop if it doesn't exist. */
670 if (offset_p == filename)
671 fatal_error ("command line option file '%s' does not exist",
672 filename);
674 fname = (char *) xmalloc (offset_p - filename + 1);
675 memcpy (fname, filename, offset_p - filename);
676 fname[offset_p - filename] = '\0';
677 offset_p += 3; /* skip the @0x */
678 offset = lto_parse_hex (offset_p);
681 /* Set up. */
682 mach_o_file = XCNEW (lto_mach_o_file);
683 result = (lto_file *) mach_o_file;
684 lto_file_init (result, fname, offset);
685 mach_o_file->fd = -1;
686 mach_o_file->writable = writable;
688 /* Open the file. */
689 mach_o_file->fd = open (fname,
690 O_BINARY | (writable ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY), 0666);
692 if (mach_o_file->fd == -1)
694 error ("could not open file %s", fname);
695 goto fail;
698 if (stat (fname, &statbuf) < 0)
700 error ("could not stat file %s", fname);
701 goto fail;
704 mach_o_file->file_size = statbuf.st_size;
706 /* If the object is in an archive, get it out. */
707 if (offset != 0)
709 char ar_tail[12];
710 int size;
712 /* Surely not? */
713 gcc_assert (!writable);
715 /* Seek to offset, or error. */
716 if (lseek (mach_o_file->fd, offset, SEEK_SET) != (ssize_t) offset)
718 error ("could not find archive member @0x%lx", (long) offset);
719 goto fail;
722 /* Now seek back 12 chars and read the tail of the AR header to
723 find the length of the member file. */
724 if (lseek (mach_o_file->fd, -12, SEEK_CUR) < 0
725 || read (mach_o_file->fd, ar_tail, 12) != 12
726 || lseek (mach_o_file->fd, 0, SEEK_CUR) != (ssize_t) offset
727 || ar_tail[10] != '`' || ar_tail[11] != '\n')
729 error ("could not find archive header @0x%lx", (long) offset);
730 goto fail;
733 ar_tail[11] = 0;
734 if (sscanf (ar_tail, "%d", &size) != 1)
736 error ("invalid archive header @0x%lx", (long) offset);
737 goto fail;
739 mach_o_file->file_size = size;
742 if (writable)
744 init_mach_o_header (mach_o_file);
746 else
747 if (! validate_file (mach_o_file))
748 goto fail;
750 return result;
752 fail:
753 if (result)
754 lto_obj_file_close (result);
755 return NULL;
759 /* Write the data in MACH_O_FILE to a real Mach-O binary object.
760 We write a header, a segment load command, and section data. */
762 static bool
763 mach_o_write_object_file (lto_mach_o_file *mach_o_file)
765 lto_mach_o_section sec, snsec;
766 lto_mach_o_data snsec_data;
767 ssize_t hdrsize, cmdsize, secsize;
768 size_t num_sections, snsec_size, total_sec_size;
769 unsigned int sec_offs, strtab_offs;
770 int i;
771 bool write_err = false;
773 /* The number of sections we will write is the number of sections added by
774 the streamer, plus 1 for the section names section. */
775 num_sections = VEC_length (lto_mach_o_section, mach_o_file->section_vec) + 1;
777 /* Calculate the size of the basic data structures on disk. */
778 if (mach_o_word_size () == 64)
780 hdrsize = sizeof (mach_o_header_64);
781 secsize = sizeof (mach_o_section_64);
782 cmdsize = sizeof (mach_o_segment_command_64) + num_sections * secsize;
784 else
786 hdrsize = sizeof (mach_o_header_32);
787 secsize = sizeof (mach_o_section_32);
788 cmdsize = sizeof (mach_o_segment_command_32) + num_sections * secsize;
791 /* Allocate the section names section. */
792 snsec_size = 0;
793 for (i = 0;
794 VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
795 i++)
796 snsec_size += strlen (sec->name) + 1;
797 snsec = mach_o_new_section (mach_o_file, NULL);
798 snsec->name = LTO_NAMES_SECTION;
799 snsec_data = mach_o_new_data (snsec);
800 snsec_data->d_buf = XCNEWVEC (char, snsec_size);
801 snsec_data->d_size = snsec_size;
803 /* Position all the sections, and fill out their headers. */
804 sec_offs = hdrsize + cmdsize;
805 strtab_offs = 0;
806 total_sec_size = 0;
807 for (i = 0;
808 VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
809 i++)
811 lto_mach_o_data data;
812 size_t data_size;
813 /* Put the section and segment names. Add the section name to the
814 section names section (unless, of course, this *is* the section
815 names section). */
816 if (sec == snsec)
817 snprintf (sec->u.section.sectname, 16, "%s", LTO_NAMES_SECTION);
818 else
820 sprintf (sec->u.section.sectname, "__%08X", strtab_offs);
821 memcpy ((char *) snsec_data->d_buf + strtab_offs, sec->name, strlen (sec->name));
823 memcpy (&sec->u.section.segname[0],
824 LTO_SEGMENT_NAME, strlen (LTO_SEGMENT_NAME));
826 /* Add layout and attributes. */
827 for (data = sec->data_chain, data_size = 0; data; data = data->next)
828 data_size += data->d_size;
829 if (mach_o_word_size () == 64)
831 put_uint64 (&sec->u.section_64.addr[0], total_sec_size);
832 put_uint64 (&sec->u.section_64.size[0], data_size);
833 put_uint32 (&sec->u.section_64.offset[0], sec_offs);
834 put_uint32 (&sec->u.section_64.flags[0], MACH_O_S_ATTR_DEBUG);
836 else
838 put_uint32 (&sec->u.section_64.addr[0], total_sec_size);
839 put_uint32 (&sec->u.section_32.size[0], data_size);
840 put_uint32 (&sec->u.section_32.offset[0], sec_offs);
841 put_uint32 (&sec->u.section_32.flags[0], MACH_O_S_ATTR_DEBUG);
844 sec_offs += data_size;
845 total_sec_size += data_size;
846 strtab_offs += strlen (sec->name) + 1;
849 /* We can write the data now. As there's no way to indicate an error return
850 from this hook, error handling is limited to not wasting our time doing
851 any more writes in the event that any one fails. */
853 /* Write the header. */
854 put_uint32 (&mach_o_file->u.header.ncmds[0], 1);
855 put_uint32 (&mach_o_file->u.header.sizeofcmds[0], cmdsize);
856 write_err = (write (mach_o_file->fd,
857 &mach_o_file->u.header, hdrsize) != hdrsize);
858 /* Write the segment load command. */
859 if (mach_o_word_size () == 64)
861 mach_o_segment_command_64 lc;
862 ssize_t lc_size = sizeof (lc);
863 memset (&lc, 0, lc_size);
864 put_uint32 (&lc.cmd[0], MACH_O_LC_SEGMENT_64);
865 put_uint32 (&lc.cmdsize[0], cmdsize);
866 put_uint64 (&lc.fileoff[0], hdrsize + cmdsize);
867 put_uint64 (&lc.filesize[0], total_sec_size);
868 put_uint32 (&lc.nsects[0], num_sections);
869 write_err = (write (mach_o_file->fd, &lc, lc_size) != lc_size);
871 else
873 mach_o_segment_command_32 lc;
874 ssize_t lc_size = sizeof (lc);
875 memset (&lc, 0, lc_size);
876 put_uint32 (&lc.cmd[0], MACH_O_LC_SEGMENT);
877 put_uint32 (&lc.cmdsize[0], cmdsize);
878 put_uint32 (&lc.fileoff[0], hdrsize + cmdsize);
879 put_uint32 (&lc.filesize[0], total_sec_size);
880 put_uint32 (&lc.nsects[0], num_sections);
881 write_err = (write (mach_o_file->fd, &lc, lc_size) != lc_size);
883 for (i = 0;
884 !write_err
885 && VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
886 i++)
887 write_err = (write (mach_o_file->fd,
888 &sec->u.section, secsize) != secsize);
890 gcc_assert (lseek (mach_o_file->fd, 0, SEEK_CUR) == hdrsize + cmdsize);
892 /* Write the section data. */
893 for (i = 0;
894 !write_err
895 && VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
896 i++)
898 lto_mach_o_data data;
900 for (data = sec->data_chain; data; data = data->next)
902 if (!write_err)
903 write_err = (write (mach_o_file->fd, data->d_buf, data->d_size)
904 != data->d_size);
905 else
906 break;
910 return !write_err;
913 /* Close Mach-O file FILE and clean up any associated data structures. If FILE
914 was opened for writing, the file's Mach-O data is written at this time. Any
915 cached data buffers are freed. */
917 void
918 lto_obj_file_close (lto_file *file)
920 lto_mach_o_file *mach_o_file = (lto_mach_o_file *) file;
921 struct lto_char_ptr_base *cur, *tmp;
922 lto_mach_o_section sec;
923 bool write_err = false;
924 int i;
926 /* If this file is open for writing, write a Mach-O object file. */
927 if (mach_o_file->writable)
929 if (! mach_o_write_object_file (mach_o_file))
930 fatal_error ("cannot write Mach-O object file");
933 /* Close the file, we're done. */
934 if (mach_o_file->fd != -1)
935 close (mach_o_file->fd);
937 /* Free any data buffers. */
938 cur = mach_o_file->data;
939 while (cur)
941 tmp = cur;
942 cur = (struct lto_char_ptr_base *) cur->ptr;
943 free (tmp);
946 /* Free any sections and their data chains. */
947 for (i = 0;
948 VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
949 i++)
951 lto_mach_o_data curdata, nextdata;
952 curdata = sec->data_chain;
953 while (curdata)
955 nextdata = curdata->next;
956 free (curdata);
957 curdata = nextdata;
959 free (sec);
961 VEC_free (lto_mach_o_section, heap, mach_o_file->section_vec);
963 free (file);
965 /* If there was an error, mention it. */
966 if (write_err)
967 error ("I/O error writing Mach-O output file");