Mercurial > hg > CbC > CbC_gcc
comparison gcc/lto/lto-macho.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
56:3c8a44c06a95 | 63:b7f97abdc517 |
---|---|
1 /* LTO routines for Mach-O object files. | |
2 Copyright 2010 Free Software Foundation, Inc. | |
3 Contributed by Steven Bosscher. | |
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 "lto-streamer.h" | |
29 #include "lto/lto-endian.h" | |
30 #include "lto/lto-macho.h" | |
31 | |
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. */ | |
38 | |
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.*. */ | |
42 | |
43 /* Segment name for LTO sections. */ | |
44 #define LTO_SEGMENT_NAME "__GNU_LTO" | |
45 | |
46 /* Section name for LTO section names section. */ | |
47 #define LTO_NAMES_SECTION "__section_names" | |
48 | |
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 | |
54 | |
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; | |
59 | |
60 /* The current output file. */ | |
61 static lto_file *current_out_file; | |
62 | |
63 | |
64 /* Is this a 32-bits or 64-bits Mach-O object file? */ | |
65 static int | |
66 mach_o_word_size (void) | |
67 { | |
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; | |
71 } | |
72 | |
73 /* Sets the current output file to FILE. Returns the old output file or | |
74 NULL. */ | |
75 | |
76 lto_file * | |
77 lto_set_current_out_file (lto_file *file) | |
78 { | |
79 lto_file *old_file = current_out_file; | |
80 current_out_file = file; | |
81 return old_file; | |
82 } | |
83 | |
84 | |
85 /* Returns the current output file. */ | |
86 | |
87 lto_file * | |
88 lto_get_current_out_file (void) | |
89 { | |
90 return current_out_file; | |
91 } | |
92 | |
93 /* Mach-O section structure constructor. */ | |
94 | |
95 static lto_mach_o_section | |
96 mach_o_new_section (lto_mach_o_file *mach_o_file, const char *name) | |
97 { | |
98 lto_mach_o_section ptr; | |
99 | |
100 /* FIXME We could allocate these things on an obstack. */ | |
101 ptr = XCNEW (struct lto_mach_o_section_d); | |
102 if (name) | |
103 { | |
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); | |
108 } | |
109 | |
110 VEC_safe_push (lto_mach_o_section, heap, mach_o_file->section_vec, ptr); | |
111 | |
112 return ptr; | |
113 } | |
114 | |
115 /* Mach-O section data block structure constructor. */ | |
116 | |
117 static lto_mach_o_data | |
118 mach_o_new_data (lto_mach_o_section sec) | |
119 { | |
120 lto_mach_o_data ptr, *chain_ptr_ptr; | |
121 | |
122 /* FIXME We could allocate these things on an obstack. */ | |
123 ptr = XCNEW (struct lto_mach_o_data_d); | |
124 | |
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; | |
129 | |
130 return ptr; | |
131 } | |
132 | |
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). */ | |
135 | |
136 static void | |
137 lto_file_init (lto_file *file, const char *filename, off_t offset) | |
138 { | |
139 file->filename = filename; | |
140 file->offset = offset; | |
141 } | |
142 | |
143 /* Return an error string after an error, or a predetermined one | |
144 if ERRCODE is not -1. */ | |
145 | |
146 static const char * | |
147 mach_o_errmsg (int errcode) | |
148 { | |
149 return strerror (errcode == -1 ? errno : errcode); | |
150 } | |
151 | |
152 /* Returns a hash code for P. */ | |
153 | |
154 static hashval_t | |
155 hash_name (const void *p) | |
156 { | |
157 const struct lto_section_slot *s = (const struct lto_section_slot *) p; | |
158 return (hashval_t) htab_hash_string (s->name); | |
159 } | |
160 | |
161 /* Returns nonzero if P1 and P2 are equal. */ | |
162 | |
163 static int | |
164 eq_name (const void *p1, const void *p2) | |
165 { | |
166 const struct lto_section_slot *s1 = | |
167 (const struct lto_section_slot *) p1; | |
168 const struct lto_section_slot *s2 = | |
169 (const struct lto_section_slot *) p2; | |
170 | |
171 return strcmp (s1->name, s2->name) == 0; | |
172 } | |
173 | |
174 /* Build a hash table whose key is the section names and whose data is | |
175 the start and size of each section in the .o file. */ | |
176 | |
177 htab_t | |
178 lto_obj_build_section_table (lto_file *lto_file) | |
179 { | |
180 lto_mach_o_file *mach_o_file = (lto_mach_o_file *)lto_file; | |
181 lto_mach_o_section sec; | |
182 htab_t section_hash_table; | |
183 off_t strtab_offs; | |
184 ssize_t strtab_size; | |
185 char *strtab = NULL; | |
186 int i; | |
187 | |
188 section_hash_table = htab_create (37, hash_name, eq_name, free); | |
189 | |
190 /* Seek the string table. */ | |
191 /* FIXME The segment name should be in darwin.h, but can we include it | |
192 here in this file? */ | |
193 for (i = 0; | |
194 VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec); | |
195 i++) | |
196 { | |
197 if (strncmp (sec->u.section.segname, "__GNU_LTO", 16) != 0) | |
198 continue; | |
199 if (strncmp (sec->u.section.sectname, "__section_names", 16) == 0) | |
200 break; | |
201 } | |
202 if (! sec) | |
203 { | |
204 error ("invalid Mach-O LTO object file: no __section_names section found"); | |
205 goto done; | |
206 } | |
207 mach_o_file->section_names_section = sec; | |
208 | |
209 if (mach_o_word_size () == 64) | |
210 { | |
211 strtab_offs = (off_t) get_uint32 (&sec->u.section_64.offset[0]); | |
212 strtab_size = (size_t) get_uint64 (&sec->u.section_64.size[0]); | |
213 } | |
214 else | |
215 { | |
216 strtab_offs = (off_t) get_uint32 (&sec->u.section_32.offset[0]); | |
217 strtab_size = (size_t) get_uint32 (&sec->u.section_32.size[0]); | |
218 } | |
219 | |
220 /* Seek to start of string table. */ | |
221 if (strtab_offs != lseek (mach_o_file->fd, | |
222 mach_o_file->base.offset + strtab_offs, | |
223 SEEK_SET)) | |
224 { | |
225 error ("altered or invalid Mach-O object file"); | |
226 goto done; | |
227 } | |
228 | |
229 strtab = XNEWVEC (char, strtab_size); | |
230 if (read (mach_o_file->fd, strtab, strtab_size) != strtab_size) | |
231 { | |
232 error ("invalid Mach-O LTO object file __section_names section"); | |
233 goto done; | |
234 } | |
235 | |
236 /* Scan sections looking at names. */ | |
237 for (i = 0; | |
238 VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec); | |
239 i++) | |
240 { | |
241 struct lto_section_slot s_slot; | |
242 void **slot; | |
243 char *new_name; | |
244 unsigned long stringoffset; | |
245 char name[17]; | |
246 | |
247 /* Ignore non-LTO sections. Also ignore the __section_names section | |
248 which does not need renaming. */ | |
249 if (strncmp (sec->u.section.segname, "__GNU_LTO", 16) != 0) | |
250 continue; | |
251 if (sec == mach_o_file->section_names_section) | |
252 continue; | |
253 | |
254 /* Try to extract the offset of the real name for this section from | |
255 __section_names. */ | |
256 memcpy (&name[0], sec->u.section.sectname, 16); | |
257 name[16] = '\0'; | |
258 if (name[0] != '_' || name[1] != '_' | |
259 || sscanf (&name[2], "%08lX", &stringoffset) != 1 | |
260 || strtab_size < (ssize_t) stringoffset) | |
261 { | |
262 error ("invalid Mach-O LTO section name string: %s", name); | |
263 continue; | |
264 } | |
265 | |
266 new_name = XNEWVEC (char, strlen (strtab + stringoffset) + 1); | |
267 strcpy (new_name, strtab + stringoffset); | |
268 s_slot.name = new_name; | |
269 slot = htab_find_slot (section_hash_table, &s_slot, INSERT); | |
270 if (*slot == NULL) | |
271 { | |
272 struct lto_section_slot *new_slot = XNEW (struct lto_section_slot); | |
273 | |
274 new_slot->name = new_name; | |
275 if (mach_o_word_size() == 64) | |
276 { | |
277 new_slot->start = | |
278 (intptr_t) get_uint32 (&sec->u.section_64.offset[0]); | |
279 new_slot->len = | |
280 (size_t) get_uint64 (&sec->u.section_64.size[0]); | |
281 } | |
282 else | |
283 { | |
284 new_slot->start = | |
285 (intptr_t) get_uint32 (&sec->u.section_32.offset[0]); | |
286 new_slot->len = | |
287 (size_t) get_uint32 (&sec->u.section_32.size[0]); | |
288 } | |
289 | |
290 *slot = new_slot; | |
291 } | |
292 else | |
293 { | |
294 error ("two or more sections for %s:", new_name); | |
295 goto done; | |
296 } | |
297 } | |
298 | |
299 done: | |
300 if (strtab) | |
301 free (strtab); | |
302 return section_hash_table; | |
303 } | |
304 | |
305 | |
306 /* Begin a new Mach-O section named NAME in the current output file. */ | |
307 | |
308 void | |
309 lto_obj_begin_section (const char *name) | |
310 { | |
311 lto_mach_o_file *file; | |
312 | |
313 if (strncmp (name, LTO_SECTION_NAME_PREFIX, | |
314 strlen(LTO_SECTION_NAME_PREFIX)) != 0) | |
315 sorry ("not implemented: Mach-O writer for non-LTO sections"); | |
316 | |
317 /* Grab the current output file and do some basic assertion checking. */ | |
318 file = (lto_mach_o_file *) lto_get_current_out_file (), | |
319 gcc_assert (file && file->writable && !file->scn); | |
320 | |
321 /* Create a new section. */ | |
322 file->scn = mach_o_new_section (file, name); | |
323 if (!file->scn) | |
324 fatal_error ("could not create a new Mach-O section: %s", mach_o_errmsg (-1)); | |
325 } | |
326 | |
327 | |
328 /* Append DATA of length LEN to the current output section. BASE is a pointer | |
329 to the output page containing DATA. It is freed once the output file has | |
330 been written. */ | |
331 | |
332 void | |
333 lto_obj_append_data (const void *data, size_t len, void *block) | |
334 { | |
335 lto_mach_o_file *file; | |
336 lto_mach_o_data mach_o_data; | |
337 struct lto_char_ptr_base *base = (struct lto_char_ptr_base *) block; | |
338 | |
339 /* Grab the current output file and do some basic assertion checking. */ | |
340 file = (lto_mach_o_file *) lto_get_current_out_file (); | |
341 gcc_assert (file); | |
342 gcc_assert (file->scn); | |
343 | |
344 mach_o_data = mach_o_new_data (file->scn); | |
345 if (!mach_o_data) | |
346 fatal_error ("could not append data to Mach-O section: %s", mach_o_errmsg (-1)); | |
347 | |
348 mach_o_data->d_buf = CONST_CAST (void *, data); | |
349 mach_o_data->d_size = len; | |
350 | |
351 /* Chain all data blocks (from all sections) on one singly-linked | |
352 list for freeing en masse after the file is closed. */ | |
353 base->ptr = (char *)file->data; | |
354 file->data = base; | |
355 } | |
356 | |
357 | |
358 /* End the current output section. This just does some assertion checking | |
359 and sets the current output file's scn member to NULL. */ | |
360 | |
361 void | |
362 lto_obj_end_section (void) | |
363 { | |
364 lto_mach_o_file *file; | |
365 | |
366 /* Grab the current output file and validate some basic assertions. */ | |
367 file = (lto_mach_o_file *) lto_get_current_out_file (); | |
368 gcc_assert (file); | |
369 gcc_assert (file->scn); | |
370 | |
371 file->scn = NULL; | |
372 } | |
373 | |
374 | |
375 /* Read a Mach-O header from MACH_O_FILE and validate it. | |
376 The file descriptor in MACH_O_FILE points at the start of the file. | |
377 If cached_mach_o_header is uninitialized, caches the results. | |
378 On succes, returns true and moves file pointer to the start of the | |
379 load commands. On failure, returns false. */ | |
380 | |
381 static bool | |
382 validate_mach_o_header (lto_mach_o_file *mach_o_file) | |
383 { | |
384 ssize_t i, n; | |
385 unsigned char magic[4]; | |
386 uint32_t cputype; | |
387 off_t startpos; | |
388 | |
389 /* Known header magics for validation, as an array. */ | |
390 static const unsigned int mach_o_known_formats[] = { | |
391 MACH_O_MH_MAGIC, | |
392 MACH_O_MH_CIGAM, | |
393 MACH_O_MH_MAGIC_64, | |
394 MACH_O_MH_CIGAM_64, | |
395 }; | |
396 #define MACH_O_NUM_KNOWN_FORMATS \ | |
397 ((ssize_t) ARRAY_SIZE (mach_o_known_formats)) | |
398 | |
399 startpos = lseek (mach_o_file->fd, 0, SEEK_CUR); | |
400 if (read (mach_o_file->fd, &magic, sizeof (magic)) != 4 | |
401 || lseek (mach_o_file->fd, -4, SEEK_CUR) != startpos) | |
402 { | |
403 error ("cannot read file %s", mach_o_file->base.filename); | |
404 return false; | |
405 } | |
406 | |
407 for (i = 0; i < MACH_O_NUM_KNOWN_FORMATS; ++i) | |
408 if (get_uint32 (&magic[0]) == mach_o_known_formats[i]) | |
409 break; | |
410 if (i == MACH_O_NUM_KNOWN_FORMATS) | |
411 goto not_for_target; | |
412 | |
413 /* Check the endian-ness. */ | |
414 if (BYTES_BIG_ENDIAN && magic[0] != 0xfe) | |
415 goto not_for_target; | |
416 | |
417 /* Set or check cached magic number. */ | |
418 if (cached_mach_o_magic == 0) | |
419 cached_mach_o_magic = get_uint32 (&magic[0]); | |
420 else if (cached_mach_o_magic != get_uint32 (&magic[0])) | |
421 goto not_for_target; | |
422 | |
423 n = mach_o_word_size () == 64 | |
424 ? sizeof (mach_o_header_64) : sizeof (mach_o_header_32); | |
425 if (read (mach_o_file->fd, &mach_o_file->u.header, n) != n) | |
426 goto not_for_target; | |
427 | |
428 /* Is this a supported CPU? */ | |
429 /* ??? Would be nice to validate the exact target architecture. */ | |
430 cputype = get_uint32 (&mach_o_file->u.header.cputype[0]); | |
431 if (cputype == MACH_O_CPU_TYPE_I386 | |
432 || cputype == MACH_O_CPU_TYPE_POWERPC) | |
433 { | |
434 if (mach_o_word_size () != 32) | |
435 goto not_for_target; | |
436 } | |
437 else if (cputype == MACH_O_CPU_TYPE_X86_64 | |
438 || cputype == MACH_O_CPU_TYPE_POWERPC_64) | |
439 { | |
440 if (mach_o_word_size () != 64) | |
441 goto not_for_target; | |
442 } | |
443 | |
444 /* Is this an MH_OBJECT file? */ | |
445 if (get_uint32 (&mach_o_file->u.header.filetype[0]) != MACH_O_MH_OBJECT) | |
446 error ("Mach-O file %s is not an MH_OBJECT file", | |
447 mach_o_file->base.filename); | |
448 | |
449 /* Save the header for future use. */ | |
450 memcpy (&cached_mach_o_header, &mach_o_file->u.header, | |
451 sizeof (cached_mach_o_header)); | |
452 | |
453 return true; | |
454 | |
455 not_for_target: | |
456 error ("file %s is not a Mach-O object file for target", | |
457 mach_o_file->base.filename); | |
458 return false; | |
459 } | |
460 | |
461 | |
462 /* Read a Mach-O LC_SEGMENT command (32 bits) from MACH_O_FILE and | |
463 validate it. | |
464 The file descriptor in MACH_O_FILE points at the start of the load | |
465 command. On sucess, returns true and advances the file pointer | |
466 past the end of the load command. On failure, returns false. */ | |
467 | |
468 static bool | |
469 validate_mach_o_segment_command_32 (lto_mach_o_file *mach_o_file) | |
470 { | |
471 mach_o_segment_command_32 seg_cmd_32; | |
472 unsigned int i; | |
473 ssize_t n; | |
474 off_t startpos; | |
475 | |
476 /* Fields we're interested in. */ | |
477 uint32_t cmd; | |
478 uint32_t cmdsize; | |
479 uint32_t nsects; | |
480 | |
481 startpos = lseek (mach_o_file->fd, 0, SEEK_CUR); | |
482 | |
483 n = sizeof (mach_o_segment_command_32); | |
484 if (read (mach_o_file->fd, (void *) &seg_cmd_32, n) != n) | |
485 goto fail; | |
486 | |
487 cmd = get_uint32 (&seg_cmd_32.cmd[0]); | |
488 cmdsize = get_uint32 (&seg_cmd_32.cmdsize[0]); | |
489 nsects = get_uint32 (&seg_cmd_32.nsects[0]); | |
490 gcc_assert (cmd == MACH_O_LC_SEGMENT); | |
491 | |
492 /* Validate section table entries. */ | |
493 for (i = 0; i < nsects; i++) | |
494 { | |
495 mach_o_section_32 sec_32; | |
496 lto_mach_o_section ltosec; | |
497 | |
498 n = sizeof (mach_o_section_32); | |
499 if (read (mach_o_file->fd, &sec_32, n) != n) | |
500 goto fail; | |
501 | |
502 /* ??? Perform some checks. */ | |
503 | |
504 /* Looks ok, so record its details. We don't read the | |
505 string table or set up names yet; we'll do that when | |
506 we build the hash table. */ | |
507 ltosec = mach_o_new_section (mach_o_file, NULL); | |
508 memcpy (<osec->u.section_32, &sec_32, sizeof (sec_32)); | |
509 } | |
510 | |
511 if (lseek (mach_o_file->fd, 0, SEEK_CUR) != startpos + cmdsize) | |
512 goto fail; | |
513 | |
514 return true; | |
515 | |
516 fail: | |
517 error ("could not read LC_SEGMENT command in Mach-O file %s", | |
518 mach_o_file->base.filename); | |
519 return false; | |
520 } | |
521 | |
522 | |
523 /* Read a Mach-O LC_SEGMENT_64 command from MACH_O_FILE and validate it. | |
524 The file descriptor in MACH_O_FILE points at the start of the load | |
525 command. On sucess, returns true and advances the file pointer | |
526 past the end of the load command. On failure, returns false. */ | |
527 | |
528 static bool | |
529 validate_mach_o_segment_command_64 (lto_mach_o_file *mach_o_file) | |
530 { | |
531 mach_o_segment_command_64 seg_cmd_64; | |
532 unsigned int i; | |
533 ssize_t n; | |
534 off_t startpos; | |
535 | |
536 /* Fields we're interested in. */ | |
537 uint32_t cmd; | |
538 uint32_t cmdsize; | |
539 uint32_t nsects; | |
540 | |
541 startpos = lseek (mach_o_file->fd, 0, SEEK_CUR); | |
542 | |
543 n = sizeof (mach_o_segment_command_64); | |
544 if (read (mach_o_file->fd, (void *) &seg_cmd_64, n) != n) | |
545 goto fail; | |
546 | |
547 cmd = get_uint32 (&seg_cmd_64.cmd[0]); | |
548 cmdsize = get_uint32 (&seg_cmd_64.cmdsize[0]); | |
549 nsects = get_uint32 (&seg_cmd_64.nsects[0]); | |
550 gcc_assert (cmd == MACH_O_LC_SEGMENT_64); | |
551 | |
552 /* Validate section table entries. */ | |
553 for (i = 0; i < nsects; i++) | |
554 { | |
555 mach_o_section_64 sec_64; | |
556 lto_mach_o_section ltosec; | |
557 | |
558 n = sizeof (mach_o_section_64); | |
559 if (read (mach_o_file->fd, &sec_64, n) != n) | |
560 goto fail; | |
561 | |
562 /* ??? Perform some checks. */ | |
563 | |
564 /* Looks ok, so record its details. We don't read the | |
565 string table or set up names yet; we'll do that when | |
566 we build the hash table. */ | |
567 ltosec = mach_o_new_section (mach_o_file, NULL); | |
568 memcpy (<osec->u.section_64, &sec_64, sizeof (sec_64)); | |
569 } | |
570 | |
571 if (lseek (mach_o_file->fd, 0, SEEK_CUR) != startpos + cmdsize) | |
572 goto fail; | |
573 | |
574 return true; | |
575 | |
576 fail: | |
577 error ("could not read LC_SEGMENT_64 command in Mach-O file %s", | |
578 mach_o_file->base.filename); | |
579 return false; | |
580 } | |
581 | |
582 /* Read a Mach-O load commands from MACH_O_FILE and validate it. | |
583 The file descriptor in MACH_O_FILE points at the start of the load | |
584 command. On sucess, returns true and advances the file pointer | |
585 past the end of the load command. On failure, returns false. */ | |
586 | |
587 static bool | |
588 validate_mach_o_load_command (lto_mach_o_file *mach_o_file) | |
589 { | |
590 mach_o_load_command load_command; | |
591 uint32_t cmd; | |
592 uint32_t cmdsize; | |
593 ssize_t n; | |
594 | |
595 n = sizeof (load_command); | |
596 if (read (mach_o_file->fd, &load_command, n) != n) | |
597 { | |
598 error ("could not read load commands in Mach-O file %s", | |
599 mach_o_file->base.filename); | |
600 return false; | |
601 } | |
602 lseek (mach_o_file->fd, -1 * (off_t) sizeof (load_command), SEEK_CUR); | |
603 | |
604 cmd = get_uint32 (&load_command.cmd[0]); | |
605 cmdsize = get_uint32 (&load_command.cmdsize[0]); | |
606 switch (cmd) | |
607 { | |
608 case MACH_O_LC_SEGMENT: | |
609 return validate_mach_o_segment_command_32 (mach_o_file); | |
610 case MACH_O_LC_SEGMENT_64: | |
611 return validate_mach_o_segment_command_64 (mach_o_file); | |
612 | |
613 default: | |
614 /* Just skip over it. */ | |
615 lseek (mach_o_file->fd, cmdsize, SEEK_CUR); | |
616 return true; | |
617 } | |
618 } | |
619 | |
620 /* Validate's MACH_O_FILE's executable header and, if cached_mach_o_header is | |
621 uninitialized, caches the results. Also records the section header string | |
622 table's section index. Returns true on success, false on failure. */ | |
623 | |
624 static bool | |
625 validate_file (lto_mach_o_file *mach_o_file) | |
626 { | |
627 uint32_t i, ncmds; | |
628 | |
629 /* Read and sanity check the raw header. */ | |
630 if (! validate_mach_o_header (mach_o_file)) | |
631 return false; | |
632 | |
633 ncmds = get_uint32 (&mach_o_file->u.header.ncmds[0]); | |
634 for (i = 0; i < ncmds; ++i) | |
635 if (! validate_mach_o_load_command (mach_o_file)) | |
636 return false; | |
637 | |
638 return true; | |
639 } | |
640 | |
641 /* Initialize MACH_O_FILE's executable header using cached data from previously | |
642 read files. */ | |
643 | |
644 static void | |
645 init_mach_o_header (lto_mach_o_file *mach_o_file) | |
646 { | |
647 gcc_assert (cached_mach_o_magic != 0); | |
648 memcpy (&mach_o_file->u.header, | |
649 &cached_mach_o_header, | |
650 sizeof (mach_o_file->u.header)); | |
651 put_uint32 (&mach_o_file->u.header.ncmds[0], 0); | |
652 put_uint32 (&mach_o_file->u.header.sizeofcmds[0], 0); | |
653 } | |
654 | |
655 /* Open Mach-O file FILENAME. If WRITABLE is true, the file is opened for write | |
656 and, if necessary, created. Otherwise, the file is opened for reading. | |
657 Returns the opened file. */ | |
658 | |
659 lto_file * | |
660 lto_obj_file_open (const char *filename, bool writable) | |
661 { | |
662 lto_mach_o_file *mach_o_file; | |
663 lto_file *result = NULL; | |
664 off_t offset; | |
665 const char *offset_p; | |
666 char *fname; | |
667 struct stat statbuf; | |
668 | |
669 offset_p = strchr (filename, '@'); | |
670 if (!offset_p) | |
671 { | |
672 fname = xstrdup (filename); | |
673 offset = 0; | |
674 } | |
675 else | |
676 { | |
677 /* The file started with '@' is a file containing command line | |
678 options. Stop if it doesn't exist. */ | |
679 if (offset_p == filename) | |
680 fatal_error ("command line option file '%s' does not exist", | |
681 filename); | |
682 | |
683 fname = (char *) xmalloc (offset_p - filename + 1); | |
684 memcpy (fname, filename, offset_p - filename); | |
685 fname[offset_p - filename] = '\0'; | |
686 offset_p += 3; /* skip the @0x */ | |
687 offset = lto_parse_hex (offset_p); | |
688 } | |
689 | |
690 /* Set up. */ | |
691 mach_o_file = XCNEW (lto_mach_o_file); | |
692 result = (lto_file *) mach_o_file; | |
693 lto_file_init (result, fname, offset); | |
694 mach_o_file->fd = -1; | |
695 mach_o_file->writable = writable; | |
696 | |
697 /* Open the file. */ | |
698 mach_o_file->fd = open (fname, | |
699 O_BINARY | (writable ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY), 0666); | |
700 | |
701 if (mach_o_file->fd == -1) | |
702 { | |
703 error ("could not open file %s", fname); | |
704 goto fail; | |
705 } | |
706 | |
707 if (stat (fname, &statbuf) < 0) | |
708 { | |
709 error ("could not stat file %s", fname); | |
710 goto fail; | |
711 } | |
712 | |
713 mach_o_file->file_size = statbuf.st_size; | |
714 | |
715 /* If the object is in an archive, get it out. */ | |
716 if (offset != 0) | |
717 { | |
718 char ar_tail[12]; | |
719 int size; | |
720 | |
721 /* Surely not? */ | |
722 gcc_assert (!writable); | |
723 | |
724 /* Seek to offset, or error. */ | |
725 if (lseek (mach_o_file->fd, offset, SEEK_SET) != (ssize_t) offset) | |
726 { | |
727 error ("could not find archive member @0x%lx", (long) offset); | |
728 goto fail; | |
729 } | |
730 | |
731 /* Now seek back 12 chars and read the tail of the AR header to | |
732 find the length of the member file. */ | |
733 if (lseek (mach_o_file->fd, -12, SEEK_CUR) < 0 | |
734 || read (mach_o_file->fd, ar_tail, 12) != 12 | |
735 || lseek (mach_o_file->fd, 0, SEEK_CUR) != (ssize_t) offset | |
736 || ar_tail[10] != '`' || ar_tail[11] != '\n') | |
737 { | |
738 error ("could not find archive header @0x%lx", (long) offset); | |
739 goto fail; | |
740 } | |
741 | |
742 ar_tail[11] = 0; | |
743 if (sscanf (ar_tail, "%d", &size) != 1) | |
744 { | |
745 error ("invalid archive header @0x%lx", (long) offset); | |
746 goto fail; | |
747 } | |
748 mach_o_file->file_size = size; | |
749 } | |
750 | |
751 if (writable) | |
752 { | |
753 init_mach_o_header (mach_o_file); | |
754 } | |
755 else | |
756 if (! validate_file (mach_o_file)) | |
757 goto fail; | |
758 | |
759 return result; | |
760 | |
761 fail: | |
762 if (result) | |
763 lto_obj_file_close (result); | |
764 return NULL; | |
765 } | |
766 | |
767 | |
768 /* Write the data in MACH_O_FILE to a real Mach-O binary object. | |
769 We write a header, a segment load command, and section data. */ | |
770 | |
771 static bool | |
772 mach_o_write_object_file (lto_mach_o_file *mach_o_file) | |
773 { | |
774 lto_mach_o_section sec, snsec; | |
775 lto_mach_o_data snsec_data; | |
776 ssize_t hdrsize, cmdsize, secsize; | |
777 size_t num_sections, snsec_size, total_sec_size; | |
778 unsigned int sec_offs, strtab_offs; | |
779 int i; | |
780 bool write_err = false; | |
781 | |
782 /* The number of sections we will write is the number of sections added by | |
783 the streamer, plus 1 for the section names section. */ | |
784 num_sections = VEC_length (lto_mach_o_section, mach_o_file->section_vec) + 1; | |
785 | |
786 /* Calculate the size of the basic data structures on disk. */ | |
787 if (mach_o_word_size () == 64) | |
788 { | |
789 hdrsize = sizeof (mach_o_header_64); | |
790 secsize = sizeof (mach_o_section_64); | |
791 cmdsize = sizeof (mach_o_segment_command_64) + num_sections * secsize; | |
792 } | |
793 else | |
794 { | |
795 hdrsize = sizeof (mach_o_header_32); | |
796 secsize = sizeof (mach_o_section_32); | |
797 cmdsize = sizeof (mach_o_segment_command_32) + num_sections * secsize; | |
798 } | |
799 | |
800 /* Allocate the section names section. */ | |
801 snsec_size = 0; | |
802 for (i = 0; | |
803 VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec); | |
804 i++) | |
805 snsec_size += strlen (sec->name) + 1; | |
806 snsec = mach_o_new_section (mach_o_file, NULL); | |
807 snsec->name = LTO_NAMES_SECTION; | |
808 snsec_data = mach_o_new_data (snsec); | |
809 snsec_data->d_buf = XCNEWVEC (char, snsec_size); | |
810 snsec_data->d_size = snsec_size; | |
811 | |
812 /* Position all the sections, and fill out their headers. */ | |
813 sec_offs = hdrsize + cmdsize; | |
814 strtab_offs = 0; | |
815 total_sec_size = 0; | |
816 for (i = 0; | |
817 VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec); | |
818 i++) | |
819 { | |
820 lto_mach_o_data data; | |
821 size_t data_size; | |
822 /* Put the section and segment names. Add the section name to the | |
823 section names section (unless, of course, this *is* the section | |
824 names section). */ | |
825 if (sec == snsec) | |
826 snprintf (sec->u.section.sectname, 16, "%s", LTO_NAMES_SECTION); | |
827 else | |
828 { | |
829 sprintf (sec->u.section.sectname, "__%08X", strtab_offs); | |
830 memcpy ((char *) snsec_data->d_buf + strtab_offs, sec->name, strlen (sec->name)); | |
831 } | |
832 memcpy (&sec->u.section.segname[0], | |
833 LTO_SEGMENT_NAME, strlen (LTO_SEGMENT_NAME)); | |
834 | |
835 /* Add layout and attributes. */ | |
836 for (data = sec->data_chain, data_size = 0; data; data = data->next) | |
837 data_size += data->d_size; | |
838 if (mach_o_word_size () == 64) | |
839 { | |
840 put_uint64 (&sec->u.section_64.addr[0], total_sec_size); | |
841 put_uint64 (&sec->u.section_64.size[0], data_size); | |
842 put_uint32 (&sec->u.section_64.offset[0], sec_offs); | |
843 put_uint32 (&sec->u.section_64.flags[0], MACH_O_S_ATTR_DEBUG); | |
844 } | |
845 else | |
846 { | |
847 put_uint32 (&sec->u.section_64.addr[0], total_sec_size); | |
848 put_uint32 (&sec->u.section_32.size[0], data_size); | |
849 put_uint32 (&sec->u.section_32.offset[0], sec_offs); | |
850 put_uint32 (&sec->u.section_32.flags[0], MACH_O_S_ATTR_DEBUG); | |
851 } | |
852 | |
853 sec_offs += data_size; | |
854 total_sec_size += data_size; | |
855 strtab_offs += strlen (sec->name) + 1; | |
856 } | |
857 | |
858 /* We can write the data now. As there's no way to indicate an error return | |
859 from this hook, error handling is limited to not wasting our time doing | |
860 any more writes in the event that any one fails. */ | |
861 | |
862 /* Write the header. */ | |
863 put_uint32 (&mach_o_file->u.header.ncmds[0], 1); | |
864 put_uint32 (&mach_o_file->u.header.sizeofcmds[0], cmdsize); | |
865 write_err = (write (mach_o_file->fd, | |
866 &mach_o_file->u.header, hdrsize) != hdrsize); | |
867 /* Write the segment load command. */ | |
868 if (mach_o_word_size () == 64) | |
869 { | |
870 mach_o_segment_command_64 lc; | |
871 ssize_t lc_size = sizeof (lc); | |
872 memset (&lc, 0, lc_size); | |
873 put_uint32 (&lc.cmd[0], MACH_O_LC_SEGMENT_64); | |
874 put_uint32 (&lc.cmdsize[0], cmdsize); | |
875 put_uint64 (&lc.fileoff[0], hdrsize + cmdsize); | |
876 put_uint64 (&lc.filesize[0], total_sec_size); | |
877 put_uint32 (&lc.nsects[0], num_sections); | |
878 write_err = (write (mach_o_file->fd, &lc, lc_size) != lc_size); | |
879 } | |
880 else | |
881 { | |
882 mach_o_segment_command_32 lc; | |
883 ssize_t lc_size = sizeof (lc); | |
884 memset (&lc, 0, lc_size); | |
885 put_uint32 (&lc.cmd[0], MACH_O_LC_SEGMENT); | |
886 put_uint32 (&lc.cmdsize[0], cmdsize); | |
887 put_uint32 (&lc.fileoff[0], hdrsize + cmdsize); | |
888 put_uint32 (&lc.filesize[0], total_sec_size); | |
889 put_uint32 (&lc.nsects[0], num_sections); | |
890 write_err = (write (mach_o_file->fd, &lc, lc_size) != lc_size); | |
891 } | |
892 for (i = 0; | |
893 !write_err | |
894 && VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec); | |
895 i++) | |
896 write_err = (write (mach_o_file->fd, | |
897 &sec->u.section, secsize) != secsize); | |
898 | |
899 gcc_assert (lseek (mach_o_file->fd, 0, SEEK_CUR) == hdrsize + cmdsize); | |
900 | |
901 /* Write the section data. */ | |
902 for (i = 0; | |
903 !write_err | |
904 && VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec); | |
905 i++) | |
906 { | |
907 lto_mach_o_data data; | |
908 | |
909 for (data = sec->data_chain; data; data = data->next) | |
910 { | |
911 if (!write_err) | |
912 write_err = (write (mach_o_file->fd, data->d_buf, data->d_size) | |
913 != data->d_size); | |
914 else | |
915 break; | |
916 } | |
917 } | |
918 | |
919 return !write_err; | |
920 } | |
921 | |
922 /* Close Mach-O file FILE and clean up any associated data structures. If FILE | |
923 was opened for writing, the file's Mach-O data is written at this time. Any | |
924 cached data buffers are freed. */ | |
925 | |
926 void | |
927 lto_obj_file_close (lto_file *file) | |
928 { | |
929 lto_mach_o_file *mach_o_file = (lto_mach_o_file *) file; | |
930 struct lto_char_ptr_base *cur, *tmp; | |
931 lto_mach_o_section sec; | |
932 bool write_err = false; | |
933 int i; | |
934 | |
935 /* If this file is open for writing, write a Mach-O object file. */ | |
936 if (mach_o_file->writable) | |
937 { | |
938 if (! mach_o_write_object_file (mach_o_file)) | |
939 fatal_error ("cannot write Mach-O object file"); | |
940 } | |
941 | |
942 /* Close the file, we're done. */ | |
943 if (mach_o_file->fd != -1) | |
944 close (mach_o_file->fd); | |
945 | |
946 /* Free any data buffers. */ | |
947 cur = mach_o_file->data; | |
948 while (cur) | |
949 { | |
950 tmp = cur; | |
951 cur = (struct lto_char_ptr_base *) cur->ptr; | |
952 free (tmp); | |
953 } | |
954 | |
955 /* Free any sections and their data chains. */ | |
956 for (i = 0; | |
957 VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec); | |
958 i++) | |
959 { | |
960 lto_mach_o_data curdata, nextdata; | |
961 curdata = sec->data_chain; | |
962 while (curdata) | |
963 { | |
964 nextdata = curdata->next; | |
965 free (curdata); | |
966 curdata = nextdata; | |
967 } | |
968 free (sec); | |
969 } | |
970 VEC_free (lto_mach_o_section, heap, mach_o_file->section_vec); | |
971 | |
972 free (file); | |
973 | |
974 /* If there was an error, mention it. */ | |
975 if (write_err) | |
976 error ("I/O error writing Mach-O output file"); | |
977 } | |
978 |