OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [lto/] [lto-macho.c] - Blame information for rev 843

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 288 jeremybenn
/* 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
/* Returns a hash code for P.  */
144
 
145
static hashval_t
146
hash_name (const void *p)
147
{
148
  const struct lto_section_slot *s = (const struct lto_section_slot *) p;
149
  return (hashval_t) htab_hash_string (s->name);
150
}
151
 
152
/* Returns nonzero if P1 and P2 are equal.  */
153
 
154
static int
155
eq_name (const void *p1, const void *p2)
156
{
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;
161
 
162
  return strcmp (s1->name, s2->name) == 0;
163
}
164
 
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.  */
167
 
168
htab_t
169
lto_obj_build_section_table (lto_file *lto_file)
170
{
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;
178
 
179
  section_hash_table = htab_create (37, hash_name, eq_name, free);
180
 
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++)
187
    {
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;
192
    }
193
  if (! sec)
194
    {
195
      error ("invalid Mach-O LTO object file: no __section_names section found");
196
      goto done;
197
    }
198
  mach_o_file->section_names_section = sec;
199
 
200
  if (mach_o_word_size () == 64)
201
    {
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]);
204
    }
205
  else
206
    {
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]);
209
    }
210
 
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))
215
    {
216
      error ("altered or invalid Mach-O object file");
217
      goto done;
218
    }
219
 
220
  strtab = XNEWVEC (char, strtab_size);
221
  if (read (mach_o_file->fd, strtab, strtab_size) != strtab_size)
222
    {
223
      error ("invalid Mach-O LTO object file __section_names section");
224
      goto done;
225
    }
226
 
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++)
231
    {
232
      struct lto_section_slot s_slot;
233
      void **slot;
234
      char *new_name;
235
      unsigned long stringoffset;
236
      char name[17];
237
 
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;
244
 
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)
252
        {
253
          error ("invalid Mach-O LTO section name string: %s", name);
254
          continue;
255
        }
256
 
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)
262
        {
263
          struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
264
 
265
          new_slot->name = new_name;
266
          if (mach_o_word_size() == 64)
267
            {
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]);
272
            }
273
          else
274
            {
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]);
279
            }
280
 
281
          *slot = new_slot;
282
        }
283
      else
284
        {
285
          error ("two or more sections for %s:", new_name);
286
          goto done;
287
        }
288
    }
289
 
290
 done:
291
  if (strtab)
292
    free (strtab);
293
  return section_hash_table;
294
}
295
 
296
 
297
/* Begin a new Mach-O section named NAME in the current output file.  */
298
 
299
void
300
lto_obj_begin_section (const char *name)
301
{
302
  lto_mach_o_file *file;
303
 
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");
307
 
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);
311
 
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");
316
}
317
 
318
 
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.  */
322
 
323
void
324
lto_obj_append_data (const void *data, size_t len, void *block)
325
{
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;
329
 
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);
334
 
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");
338
 
339
  mach_o_data->d_buf = CONST_CAST (void *, data);
340
  mach_o_data->d_size = len;
341
 
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;
346
}
347
 
348
 
349
/* End the current output section.  This just does some assertion checking
350
   and sets the current output file's scn member to NULL.  */
351
 
352
void
353
lto_obj_end_section (void)
354
{
355
  lto_mach_o_file *file;
356
 
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);
361
 
362
  file->scn = NULL;
363
}
364
 
365
 
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.  */
371
 
372
static bool
373
validate_mach_o_header (lto_mach_o_file *mach_o_file)
374
{
375
  ssize_t i, n;
376
  unsigned char magic[4];
377
  uint32_t cputype;
378
  off_t startpos;
379
 
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,
386
  };
387
#define MACH_O_NUM_KNOWN_FORMATS \
388
  ((ssize_t) ARRAY_SIZE (mach_o_known_formats))
389
 
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)
393
    {
394
      error ("cannot read file %s", mach_o_file->base.filename);
395
      return false;
396
    }
397
 
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;
403
 
404
  /* Check the endian-ness.  */
405
  if (BYTES_BIG_ENDIAN && magic[0] != 0xfe)
406
    goto not_for_target;
407
 
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;
413
 
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;
418
 
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)
424
    {
425
      if (mach_o_word_size () != 32)
426
        goto not_for_target;
427
    }
428
  else if (cputype == MACH_O_CPU_TYPE_X86_64
429
           || cputype == MACH_O_CPU_TYPE_POWERPC_64)
430
    {
431
      if (mach_o_word_size () != 64)
432
        goto not_for_target;
433
    }
434
 
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);
439
 
440
  /* Save the header for future use.  */
441
  memcpy (&cached_mach_o_header, &mach_o_file->u.header,
442
          sizeof (cached_mach_o_header));
443
 
444
  return true;
445
 
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;
450
}
451
 
452
 
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.  */
458
 
459
static bool
460
validate_mach_o_segment_command_32 (lto_mach_o_file *mach_o_file)
461
{
462
  mach_o_segment_command_32 seg_cmd_32;
463
  unsigned int i;
464
  ssize_t n;
465
  off_t startpos;
466
 
467
  /* Fields we're interested in.  */
468
  uint32_t cmd;
469
  uint32_t cmdsize;
470
  uint32_t nsects;
471
 
472
  startpos = lseek (mach_o_file->fd, 0, SEEK_CUR);
473
 
474
  n = sizeof (mach_o_segment_command_32);
475
  if (read (mach_o_file->fd, (void *) &seg_cmd_32, n) != n)
476
    goto fail;
477
 
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);
482
 
483
  /* Validate section table entries.  */
484
  for (i = 0; i < nsects; i++)
485
    {
486
      mach_o_section_32 sec_32;
487
      lto_mach_o_section ltosec;
488
 
489
      n = sizeof (mach_o_section_32);
490
      if (read (mach_o_file->fd, &sec_32, n) != n)
491
        goto fail;
492
 
493
      /* ??? Perform some checks.  */
494
 
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));
500
    }
501
 
502
  if (lseek (mach_o_file->fd, 0, SEEK_CUR) != startpos + cmdsize)
503
    goto fail;
504
 
505
  return true;
506
 
507
 fail:
508
  error ("could not read LC_SEGMENT command in Mach-O file %s",
509
         mach_o_file->base.filename);
510
  return false;
511
}
512
 
513
 
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.  */
518
 
519
static bool
520
validate_mach_o_segment_command_64 (lto_mach_o_file *mach_o_file)
521
{
522
  mach_o_segment_command_64 seg_cmd_64;
523
  unsigned int i;
524
  ssize_t n;
525
  off_t startpos;
526
 
527
  /* Fields we're interested in.  */
528
  uint32_t cmd;
529
  uint32_t cmdsize;
530
  uint32_t nsects;
531
 
532
  startpos = lseek (mach_o_file->fd, 0, SEEK_CUR);
533
 
534
  n = sizeof (mach_o_segment_command_64);
535
  if (read (mach_o_file->fd, (void *) &seg_cmd_64, n) != n)
536
    goto fail;
537
 
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);
542
 
543
  /* Validate section table entries.  */
544
  for (i = 0; i < nsects; i++)
545
    {
546
      mach_o_section_64 sec_64;
547
      lto_mach_o_section ltosec;
548
 
549
      n = sizeof (mach_o_section_64);
550
      if (read (mach_o_file->fd, &sec_64, n) != n)
551
        goto fail;
552
 
553
      /* ??? Perform some checks.  */
554
 
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));
560
    }
561
 
562
  if (lseek (mach_o_file->fd, 0, SEEK_CUR) != startpos + cmdsize)
563
    goto fail;
564
 
565
  return true;
566
 
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;
571
}
572
 
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.  */
577
 
578
static bool
579
validate_mach_o_load_command (lto_mach_o_file *mach_o_file)
580
{
581
  mach_o_load_command load_command;
582
  uint32_t cmd;
583
  uint32_t cmdsize;
584
  ssize_t n;
585
 
586
  n = sizeof (load_command);
587
  if (read (mach_o_file->fd, &load_command, n) != n)
588
    {
589
      error ("could not read load commands in Mach-O file %s",
590
             mach_o_file->base.filename);
591
      return false;
592
    }
593
  lseek (mach_o_file->fd, -1 * (off_t) sizeof (load_command), SEEK_CUR);
594
 
595
  cmd = get_uint32 (&load_command.cmd[0]);
596
  cmdsize = get_uint32 (&load_command.cmdsize[0]);
597
  switch (cmd)
598
    {
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);
603
 
604
    default:
605
      /* Just skip over it.  */
606
      lseek (mach_o_file->fd, cmdsize, SEEK_CUR);
607
      return true;
608
    }
609
}
610
 
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.  */
614
 
615
static bool
616
validate_file (lto_mach_o_file *mach_o_file)
617
{
618
  uint32_t i, ncmds;
619
 
620
  /* Read and sanity check the raw header.  */
621
  if (! validate_mach_o_header (mach_o_file))
622
    return false;
623
 
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;
628
 
629
  return true;
630
}
631
 
632
/* Initialize MACH_O_FILE's executable header using cached data from previously
633
   read files.  */
634
 
635
static void
636
init_mach_o_header (lto_mach_o_file *mach_o_file)
637
{
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);
644
}
645
 
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.  */
649
 
650
lto_file *
651
lto_obj_file_open (const char *filename, bool writable)
652
{
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;
659
 
660
  offset_p = strchr (filename, '@');
661
  if (!offset_p)
662
    {
663
      fname = xstrdup (filename);
664
      offset = 0;
665
    }
666
  else
667
    {
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);
673
 
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);
679
    }
680
 
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;
687
 
688
  /* Open the file.  */
689
  mach_o_file->fd = open (fname,
690
    O_BINARY | (writable ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY), 0666);
691
 
692
  if (mach_o_file->fd == -1)
693
    {
694
      error ("could not open file %s", fname);
695
      goto fail;
696
    }
697
 
698
  if (stat (fname, &statbuf) < 0)
699
    {
700
      error ("could not stat file %s", fname);
701
      goto fail;
702
    }
703
 
704
  mach_o_file->file_size = statbuf.st_size;
705
 
706
  /* If the object is in an archive, get it out.  */
707
  if (offset != 0)
708
    {
709
      char ar_tail[12];
710
      int size;
711
 
712
      /* Surely not?  */
713
      gcc_assert (!writable);
714
 
715
      /* Seek to offset, or error.  */
716
      if (lseek (mach_o_file->fd, offset, SEEK_SET) != (ssize_t) offset)
717
        {
718
          error ("could not find archive member @0x%lx", (long) offset);
719
          goto fail;
720
        }
721
 
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')
728
        {
729
          error ("could not find archive header @0x%lx", (long) offset);
730
          goto fail;
731
        }
732
 
733
      ar_tail[11] = 0;
734
      if (sscanf (ar_tail, "%d", &size) != 1)
735
        {
736
          error ("invalid archive header @0x%lx", (long) offset);
737
          goto fail;
738
        }
739
      mach_o_file->file_size = size;
740
    }
741
 
742
  if (writable)
743
    {
744
      init_mach_o_header (mach_o_file);
745
    }
746
  else
747
    if (! validate_file (mach_o_file))
748
      goto fail;
749
 
750
  return result;
751
 
752
 fail:
753
  if (result)
754
    lto_obj_file_close (result);
755
  return NULL;
756
}
757
 
758
 
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.  */
761
 
762
static bool
763
mach_o_write_object_file (lto_mach_o_file *mach_o_file)
764
{
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;
772
 
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;
776
 
777
  /* Calculate the size of the basic data structures on disk.  */
778
  if (mach_o_word_size () == 64)
779
    {
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;
783
    }
784
  else
785
    {
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;
789
    }
790
 
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;
802
 
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++)
810
    {
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
819
        {
820
          sprintf (sec->u.section.sectname, "__%08X", strtab_offs);
821
          memcpy ((char *) snsec_data->d_buf + strtab_offs, sec->name, strlen (sec->name));
822
        }
823
      memcpy (&sec->u.section.segname[0],
824
              LTO_SEGMENT_NAME, strlen (LTO_SEGMENT_NAME));
825
 
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)
830
        {
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);
835
        }
836
      else
837
        {
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);
842
        }
843
 
844
      sec_offs += data_size;
845
      total_sec_size += data_size;
846
      strtab_offs += strlen (sec->name) + 1;
847
    }
848
 
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.  */
852
 
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)
860
    {
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);
870
    }
871
  else
872
    {
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);
882
    }
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);
889
 
890
  gcc_assert (lseek (mach_o_file->fd, 0, SEEK_CUR) == hdrsize + cmdsize);
891
 
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++)
897
    {
898
      lto_mach_o_data data;
899
 
900
      for (data = sec->data_chain; data; data = data->next)
901
        {
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;
907
        }
908
    }
909
 
910
  return !write_err;
911
}
912
 
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.  */
916
 
917
void
918
lto_obj_file_close (lto_file *file)
919
{
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;
925
 
926
  /* If this file is open for writing, write a Mach-O object file.  */
927
  if (mach_o_file->writable)
928
    {
929
      if (! mach_o_write_object_file (mach_o_file))
930
        fatal_error ("cannot write Mach-O object file");
931
    }
932
 
933
  /* Close the file, we're done.  */
934
  if (mach_o_file->fd != -1)
935
    close (mach_o_file->fd);
936
 
937
  /* Free any data buffers.  */
938
  cur = mach_o_file->data;
939
  while (cur)
940
    {
941
      tmp = cur;
942
      cur = (struct lto_char_ptr_base *) cur->ptr;
943
      free (tmp);
944
    }
945
 
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++)
950
    {
951
      lto_mach_o_data curdata, nextdata;
952
      curdata = sec->data_chain;
953
      while (curdata)
954
        {
955
          nextdata = curdata->next;
956
          free (curdata);
957
          curdata = nextdata;
958
        }
959
      free (sec);
960
    }
961
  VEC_free (lto_mach_o_section, heap, mach_o_file->section_vec);
962
 
963
  free (file);
964
 
965
  /* If there was an error, mention it.  */
966
  if (write_err)
967
    error ("I/O error writing Mach-O output file");
968
}
969
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.