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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libiberty/] [simple-object-mach-o.c] - Blame information for rev 736

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 736 jeremybenn
/* simple-object-mach-o.c -- routines to manipulate Mach-O object files.
2
   Copyright 2010, 2011 Free Software Foundation, Inc.
3
   Written by Ian Lance Taylor, Google.
4
 
5
This program is free software; you can redistribute it and/or modify it
6
under the terms of the GNU General Public License as published by the
7
Free Software Foundation; either version 2, or (at your option) any
8
later version.
9
 
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14
 
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, 51 Franklin Street - Fifth Floor,
18
Boston, MA 02110-1301, USA.  */
19
 
20
#include "config.h"
21
#include "libiberty.h"
22
#include "simple-object.h"
23
 
24
#include <stddef.h>
25
 
26
#ifdef HAVE_STDLIB_H
27
#include <stdlib.h>
28
#endif
29
 
30
#ifdef HAVE_STDINT_H
31
#include <stdint.h>
32
#endif
33
 
34
#ifdef HAVE_STRING_H
35
#include <string.h>
36
#endif
37
 
38
#ifdef HAVE_INTTYPES_H
39
#include <inttypes.h>
40
#endif
41
 
42
#include "simple-object-common.h"
43
 
44
/* Mach-O structures and constants.  */
45
 
46
/* Mach-O header (32-bit version).  */
47
 
48
struct mach_o_header_32
49
{
50
  unsigned char magic[4];       /* Magic number.  */
51
  unsigned char cputype[4];     /* CPU that this object is for.  */
52
  unsigned char cpusubtype[4];  /* CPU subtype.  */
53
  unsigned char filetype[4];    /* Type of file.  */
54
  unsigned char ncmds[4];       /* Number of load commands.  */
55
  unsigned char sizeofcmds[4];  /* Total size of load commands.  */
56
  unsigned char flags[4];       /* Flags for special featues.  */
57
};
58
 
59
/* Mach-O header (64-bit version).  */
60
 
61
struct mach_o_header_64
62
{
63
  unsigned char magic[4];       /* Magic number.  */
64
  unsigned char cputype[4];     /* CPU that this object is for.  */
65
  unsigned char cpusubtype[4];  /* CPU subtype.  */
66
  unsigned char filetype[4];    /* Type of file.  */
67
  unsigned char ncmds[4];       /* Number of load commands.  */
68
  unsigned char sizeofcmds[4];  /* Total size of load commands.  */
69
  unsigned char flags[4];       /* Flags for special featues.  */
70
  unsigned char reserved[4];    /* Reserved.  Duh.  */
71
};
72
 
73
/* For magic field in header.  */
74
 
75
#define MACH_O_MH_MAGIC                 0xfeedface
76
#define MACH_O_MH_MAGIC_64              0xfeedfacf
77
 
78
/* For filetype field in header.  */
79
 
80
#define MACH_O_MH_OBJECT                0x01
81
 
82
/* A Mach-O file is a list of load commands.  This is the header of a
83
   load command.  */
84
 
85
struct mach_o_load_command
86
{
87
  unsigned char cmd[4];         /* The type of load command.  */
88
  unsigned char cmdsize[4];     /* Size in bytes of entire command.  */
89
};
90
 
91
/* For cmd field in load command.   */
92
 
93
#define MACH_O_LC_SEGMENT               0x01
94
#define MACH_O_LC_SEGMENT_64            0x19
95
 
96
/* LC_SEGMENT load command.  */
97
 
98
struct mach_o_segment_command_32
99
{
100
  unsigned char cmd[4];         /* The type of load command (LC_SEGMENT).  */
101
  unsigned char cmdsize[4];     /* Size in bytes of entire command.  */
102
  unsigned char segname[16];    /* Name of this segment.  */
103
  unsigned char vmaddr[4];      /* Virtual memory address of this segment.  */
104
  unsigned char vmsize[4];      /* Size there, in bytes.  */
105
  unsigned char fileoff[4];     /* Offset in bytes of the data to be mapped.  */
106
  unsigned char filesize[4];    /* Size in bytes on disk.  */
107
  unsigned char maxprot[4];     /* Maximum permitted vmem protection.  */
108
  unsigned char initprot[4];    /* Initial vmem protection.  */
109
  unsigned char nsects[4];      /* Number of sections in this segment.  */
110
  unsigned char flags[4];       /* Flags that affect the loading.  */
111
};
112
 
113
/* LC_SEGMENT_64 load command.  */
114
 
115
struct mach_o_segment_command_64
116
{
117
  unsigned char cmd[4];         /* The type of load command (LC_SEGMENT_64).  */
118
  unsigned char cmdsize[4];     /* Size in bytes of entire command.  */
119
  unsigned char segname[16];    /* Name of this segment.  */
120
  unsigned char vmaddr[8];      /* Virtual memory address of this segment.  */
121
  unsigned char vmsize[8];      /* Size there, in bytes.  */
122
  unsigned char fileoff[8];     /* Offset in bytes of the data to be mapped.  */
123
  unsigned char filesize[8];    /* Size in bytes on disk.  */
124
  unsigned char maxprot[4];     /* Maximum permitted vmem protection.  */
125
  unsigned char initprot[4];    /* Initial vmem protection.  */
126
  unsigned char nsects[4];      /* Number of sections in this segment.  */
127
  unsigned char flags[4];       /* Flags that affect the loading.  */
128
};
129
 
130
/* 32-bit section header.  */
131
 
132
struct mach_o_section_32
133
{
134
  unsigned char sectname[16];   /* Section name.  */
135
  unsigned char segname[16];    /* Segment that the section belongs to.  */
136
  unsigned char addr[4];        /* Address of this section in memory.  */
137
  unsigned char size[4];        /* Size in bytes of this section.  */
138
  unsigned char offset[4];      /* File offset of this section.  */
139
  unsigned char align[4];       /* log2 of this section's alignment.  */
140
  unsigned char reloff[4];      /* File offset of this section's relocs.  */
141
  unsigned char nreloc[4];      /* Number of relocs for this section.  */
142
  unsigned char flags[4];       /* Section flags/attributes.  */
143
  unsigned char reserved1[4];
144
  unsigned char reserved2[4];
145
};
146
 
147
/* 64-bit section header.  */
148
 
149
struct mach_o_section_64
150
{
151
  unsigned char sectname[16];   /* Section name.  */
152
  unsigned char segname[16];    /* Segment that the section belongs to.  */
153
  unsigned char addr[8];        /* Address of this section in memory.  */
154
  unsigned char size[8];        /* Size in bytes of this section.  */
155
  unsigned char offset[4];      /* File offset of this section.  */
156
  unsigned char align[4];       /* log2 of this section's alignment.  */
157
  unsigned char reloff[4];      /* File offset of this section's relocs.  */
158
  unsigned char nreloc[4];      /* Number of relocs for this section.  */
159
  unsigned char flags[4];       /* Section flags/attributes.  */
160
  unsigned char reserved1[4];
161
  unsigned char reserved2[4];
162
  unsigned char reserved3[4];
163
};
164
 
165
/* Flags for Mach-O sections.  */
166
 
167
#define MACH_O_S_ATTR_DEBUG                     0x02000000
168
 
169
/* The length of a segment or section name.  */
170
 
171
#define MACH_O_NAME_LEN (16)
172
 
173
/* A GNU specific extension for long section names.  */
174
 
175
#define GNU_SECTION_NAMES "__section_names"
176
 
177
/* A GNU-specific extension to wrap multiple sections using three
178
   mach-o sections within a given segment.  The section '__wrapper_sects'
179
   is subdivided according to the index '__wrapper_index' and each sub
180
   sect is named according to the names supplied in '__wrapper_names'.  */
181
 
182
#define GNU_WRAPPER_SECTS "__wrapper_sects"
183
#define GNU_WRAPPER_INDEX "__wrapper_index"
184
#define GNU_WRAPPER_NAMES "__wrapper_names"
185
 
186
/* Private data for an simple_object_read.  */
187
 
188
struct simple_object_mach_o_read
189
{
190
  /* User specified segment name.  */
191
  char *segment_name;
192
  /* Magic number.  */
193
  unsigned int magic;
194
  /* Whether this file is big-endian.  */
195
  int is_big_endian;
196
  /* CPU type from header.  */
197
  unsigned int cputype;
198
  /* CPU subtype from header.  */
199
  unsigned int cpusubtype;
200
  /* Number of commands, from header.  */
201
  unsigned int ncmds;
202
  /* Flags from header.  */
203
  unsigned int flags;
204
  /* Reserved field from header, only used on 64-bit.  */
205
  unsigned int reserved;
206
};
207
 
208
/* Private data for an simple_object_attributes.  */
209
 
210
struct simple_object_mach_o_attributes
211
{
212
  /* Magic number.  */
213
  unsigned int magic;
214
  /* Whether this file is big-endian.  */
215
  int is_big_endian;
216
  /* CPU type from header.  */
217
  unsigned int cputype;
218
  /* CPU subtype from header.  */
219
  unsigned int cpusubtype;
220
  /* Flags from header.  */
221
  unsigned int flags;
222
  /* Reserved field from header, only used on 64-bit.  */
223
  unsigned int reserved;
224
};
225
 
226
/* See if we have a Mach-O MH_OBJECT file:
227
 
228
   A standard MH_OBJECT (from as) will have three load commands:
229
 
230
   1 - LC_SYMTAB
231
   2 - LC_DYSYMTAB
232
 
233
   The LC_SEGMENT/LC_SEGMENT64 will introduce a single anonymous segment
234
   containing all the sections.
235
 
236
   Files written by simple-object will have only the segment command
237
   (no symbol tables).  */
238
 
239
static void *
240
simple_object_mach_o_match (
241
    unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
242
    int descriptor,
243
    off_t offset,
244
    const char *segment_name,
245
    const char **errmsg,
246
    int *err)
247
{
248
  unsigned int magic;
249
  int is_big_endian;
250
  unsigned int (*fetch_32) (const unsigned char *);
251
  unsigned int filetype;
252
  struct simple_object_mach_o_read *omr;
253
  unsigned char buf[sizeof (struct mach_o_header_64)];
254
  unsigned char *b;
255
 
256
  magic = simple_object_fetch_big_32 (header);
257
  if (magic == MACH_O_MH_MAGIC || magic == MACH_O_MH_MAGIC_64)
258
    is_big_endian = 1;
259
  else
260
    {
261
      magic = simple_object_fetch_little_32 (header);
262
      if (magic == MACH_O_MH_MAGIC || magic == MACH_O_MH_MAGIC_64)
263
        is_big_endian = 0;
264
      else
265
        {
266
          *errmsg = NULL;
267
          *err = 0;
268
          return NULL;
269
        }
270
    }
271
 
272
#ifndef UNSIGNED_64BIT_TYPE
273
  if (magic == MACH_O_MH_MAGIC_64)
274
    {
275
      *errmsg = "64-bit Mach-O objects not supported";
276
      *err = 0;
277
      return NULL;
278
    }
279
#endif
280
 
281
  /* We require the user to provide a segment name.  This is
282
     unfortunate but I don't see any good choices here.  */
283
 
284
  if (segment_name == NULL)
285
    {
286
      *errmsg = "Mach-O file found but no segment name specified";
287
      *err = 0;
288
      return NULL;
289
    }
290
 
291
  if (strlen (segment_name) > MACH_O_NAME_LEN)
292
    {
293
      *errmsg = "Mach-O segment name too long";
294
      *err = 0;
295
      return NULL;
296
    }
297
 
298
  /* The 32-bit and 64-bit headers are similar enough that we can use
299
     the same code.  */
300
 
301
  fetch_32 = (is_big_endian
302
              ? simple_object_fetch_big_32
303
              : simple_object_fetch_little_32);
304
 
305
  if (!simple_object_internal_read (descriptor, offset, buf,
306
                                    (magic == MACH_O_MH_MAGIC
307
                                     ? sizeof (struct mach_o_header_32)
308
                                     : sizeof (struct mach_o_header_64)),
309
                                    errmsg, err))
310
    return NULL;
311
 
312
  b = &buf[0];
313
 
314
  filetype = (*fetch_32) (b + offsetof (struct mach_o_header_32, filetype));
315
  if (filetype != MACH_O_MH_OBJECT)
316
    {
317
      *errmsg = "Mach-O file is not object file";
318
      *err = 0;
319
      return NULL;
320
    }
321
 
322
  omr = XNEW (struct simple_object_mach_o_read);
323
  omr->segment_name = xstrdup (segment_name);
324
  omr->magic = magic;
325
  omr->is_big_endian = is_big_endian;
326
  omr->cputype = (*fetch_32) (b + offsetof (struct mach_o_header_32, cputype));
327
  omr->cpusubtype = (*fetch_32) (b
328
                                 + offsetof (struct mach_o_header_32,
329
                                             cpusubtype));
330
  omr->ncmds = (*fetch_32) (b + offsetof (struct mach_o_header_32, ncmds));
331
  omr->flags = (*fetch_32) (b + offsetof (struct mach_o_header_32, flags));
332
  if (magic == MACH_O_MH_MAGIC)
333
    omr->reserved = 0;
334
  else
335
    omr->reserved = (*fetch_32) (b
336
                                 + offsetof (struct mach_o_header_64,
337
                                             reserved));
338
 
339
  return (void *) omr;
340
}
341
 
342
/* Get the file offset and size from a section header.  */
343
 
344
static void
345
simple_object_mach_o_section_info (int is_big_endian, int is_32,
346
                                   const unsigned char *sechdr, off_t *offset,
347
                                   size_t *size)
348
{
349
  unsigned int (*fetch_32) (const unsigned char *);
350
  ulong_type (*fetch_64) (const unsigned char *);
351
 
352
  fetch_32 = (is_big_endian
353
              ? simple_object_fetch_big_32
354
              : simple_object_fetch_little_32);
355
 
356
  fetch_64 = NULL;
357
#ifdef UNSIGNED_64BIT_TYPE
358
  fetch_64 = (is_big_endian
359
              ? simple_object_fetch_big_64
360
              : simple_object_fetch_little_64);
361
#endif
362
 
363
  if (is_32)
364
    {
365
      *offset = fetch_32 (sechdr
366
                          + offsetof (struct mach_o_section_32, offset));
367
      *size = fetch_32 (sechdr
368
                        + offsetof (struct mach_o_section_32, size));
369
    }
370
  else
371
    {
372
      *offset = fetch_32 (sechdr
373
                          + offsetof (struct mach_o_section_64, offset));
374
      *size = fetch_64 (sechdr
375
                        + offsetof (struct mach_o_section_64, size));
376
    }
377
}
378
 
379
/* Handle a segment in a Mach-O Object file.
380
 
381
   This will callback to the function pfn for each "section found" the meaning
382
   of which depends on gnu extensions to mach-o:
383
 
384
   If we find mach-o sections (with the segment name as specified) which also
385
   contain: a 'sects' wrapper, an index, and a  name table, we expand this into
386
   as many sections as are specified in the index.  In this case, there will
387
   be a callback for each of these.
388
 
389
   We will also allow an extension that permits long names (more than 16
390
   characters) to be used with mach-o.  In this case, the section name has
391
   a specific format embedding an index into a name table, and the file must
392
   contain such name table.
393
 
394
   Return 1 if we should continue, 0 if the caller should return.  */
395
 
396
#define SOMO_SECTS_PRESENT 0x01
397
#define SOMO_INDEX_PRESENT 0x02
398
#define SOMO_NAMES_PRESENT 0x04
399
#define SOMO_LONGN_PRESENT 0x08
400
#define SOMO_WRAPPING (SOMO_SECTS_PRESENT | SOMO_INDEX_PRESENT \
401
                       | SOMO_NAMES_PRESENT)
402
 
403
static int
404
simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
405
                              const unsigned char *segbuf,
406
                              int (*pfn) (void *, const char *, off_t offset,
407
                                          off_t length),
408
                              void *data,
409
                              const char **errmsg, int *err)
410
{
411
  struct simple_object_mach_o_read *omr =
412
    (struct simple_object_mach_o_read *) sobj->data;
413
  unsigned int (*fetch_32) (const unsigned char *);
414
  int is_32;
415
  size_t seghdrsize;
416
  size_t sechdrsize;
417
  size_t segname_offset;
418
  size_t sectname_offset;
419
  unsigned int nsects;
420
  unsigned char *secdata;
421
  unsigned int i;
422
  unsigned int gnu_sections_found;
423
  unsigned int strtab_index;
424
  unsigned int index_index;
425
  unsigned int nametab_index;
426
  unsigned int sections_index;
427
  char *strtab;
428
  char *nametab;
429
  unsigned char *index;
430
  size_t strtab_size;
431
  size_t nametab_size;
432
  size_t index_size;
433
  unsigned int n_wrapped_sects;
434
  size_t wrapper_sect_size;
435
  off_t wrapper_sect_offset;
436
 
437
  fetch_32 = (omr->is_big_endian
438
              ? simple_object_fetch_big_32
439
              : simple_object_fetch_little_32);
440
 
441
  is_32 = omr->magic == MACH_O_MH_MAGIC;
442
 
443
  if (is_32)
444
    {
445
      seghdrsize = sizeof (struct mach_o_segment_command_32);
446
      sechdrsize = sizeof (struct mach_o_section_32);
447
      segname_offset = offsetof (struct mach_o_section_32, segname);
448
      sectname_offset = offsetof (struct mach_o_section_32, sectname);
449
      nsects = (*fetch_32) (segbuf
450
                            + offsetof (struct mach_o_segment_command_32,
451
                                        nsects));
452
    }
453
  else
454
    {
455
      seghdrsize = sizeof (struct mach_o_segment_command_64);
456
      sechdrsize = sizeof (struct mach_o_section_64);
457
      segname_offset = offsetof (struct mach_o_section_64, segname);
458
      sectname_offset = offsetof (struct mach_o_section_64, sectname);
459
      nsects = (*fetch_32) (segbuf
460
                            + offsetof (struct mach_o_segment_command_64,
461
                                        nsects));
462
    }
463
 
464
  /* Fetch the section headers from the segment command.  */
465
 
466
  secdata = XNEWVEC (unsigned char, nsects * sechdrsize);
467
  if (!simple_object_internal_read (sobj->descriptor, offset + seghdrsize,
468
                                    secdata, nsects * sechdrsize, errmsg, err))
469
    {
470
      XDELETEVEC (secdata);
471
      return 0;
472
    }
473
 
474
  /* Scan for special sections that signal GNU extensions to the format.  */
475
 
476
  gnu_sections_found = 0;
477
  index_index = nsects;
478
  sections_index = nsects;
479
  strtab_index = nsects;
480
  nametab_index = nsects;
481
  for (i = 0; i < nsects; ++i)
482
    {
483
      size_t nameoff;
484
 
485
      nameoff = i * sechdrsize + segname_offset;
486
      if (strcmp ((char *) secdata + nameoff, omr->segment_name) != 0)
487
        continue;
488
 
489
      nameoff = i * sechdrsize + sectname_offset;
490
      if (strcmp ((char *) secdata + nameoff, GNU_WRAPPER_NAMES) == 0)
491
        {
492
          nametab_index = i;
493
          gnu_sections_found |= SOMO_NAMES_PRESENT;
494
        }
495
      else if (strcmp ((char *) secdata + nameoff, GNU_WRAPPER_INDEX) == 0)
496
        {
497
          index_index = i;
498
          gnu_sections_found |= SOMO_INDEX_PRESENT;
499
        }
500
      else if (strcmp ((char *) secdata + nameoff, GNU_WRAPPER_SECTS) == 0)
501
        {
502
          sections_index = i;
503
          gnu_sections_found |= SOMO_SECTS_PRESENT;
504
        }
505
      else if (strcmp ((char *) secdata + nameoff, GNU_SECTION_NAMES) == 0)
506
        {
507
          strtab_index = i;
508
          gnu_sections_found |= SOMO_LONGN_PRESENT;
509
        }
510
    }
511
 
512
  /* If any of the special wrapper section components is present, then
513
     they all should be.  */
514
 
515
  if ((gnu_sections_found & SOMO_WRAPPING) != 0)
516
    {
517
      off_t nametab_offset;
518
      off_t index_offset;
519
 
520
      if ((gnu_sections_found & SOMO_WRAPPING) != SOMO_WRAPPING)
521
        {
522
          *errmsg = "GNU Mach-o section wrapper: required section missing";
523
          *err = 0; /* No useful errno.  */
524
          XDELETEVEC (secdata);
525
          return 0;
526
        }
527
 
528
      /* Fetch the name table.  */
529
 
530
      simple_object_mach_o_section_info (omr->is_big_endian, is_32,
531
                                         secdata + nametab_index * sechdrsize,
532
                                         &nametab_offset, &nametab_size);
533
      nametab = XNEWVEC (char, nametab_size);
534
      if (!simple_object_internal_read (sobj->descriptor,
535
                                        sobj->offset + nametab_offset,
536
                                        (unsigned char *) nametab, nametab_size,
537
                                        errmsg, err))
538
        {
539
          XDELETEVEC (nametab);
540
          XDELETEVEC (secdata);
541
          return 0;
542
        }
543
 
544
      /* Fetch the index.  */
545
 
546
      simple_object_mach_o_section_info (omr->is_big_endian, is_32,
547
                                         secdata + index_index * sechdrsize,
548
                                         &index_offset, &index_size);
549
      index = XNEWVEC (unsigned char, index_size);
550
      if (!simple_object_internal_read (sobj->descriptor,
551
                                        sobj->offset + index_offset,
552
                                        index, index_size,
553
                                        errmsg, err))
554
        {
555
          XDELETEVEC (index);
556
          XDELETEVEC (nametab);
557
          XDELETEVEC (secdata);
558
          return 0;
559
        }
560
 
561
      /* The index contains 4 unsigned ints per sub-section:
562
         sub-section offset/length, sub-section name/length.
563
         We fix this for both 32 and 64 bit mach-o for now, since
564
         other fields limit the maximum size of an object to 4G.  */
565
      n_wrapped_sects = index_size / 16;
566
 
567
      /* Get the parameters for the wrapper too.  */
568
      simple_object_mach_o_section_info (omr->is_big_endian, is_32,
569
                                         secdata + sections_index * sechdrsize,
570
                                         &wrapper_sect_offset,
571
                                         &wrapper_sect_size);
572
    }
573
  else
574
    {
575
      index = NULL;
576
      index_size = 0;
577
      nametab = NULL;
578
      nametab_size = 0;
579
      n_wrapped_sects = 0;
580
    }
581
 
582
  /* If we have a long names section, fetch it.  */
583
 
584
  if ((gnu_sections_found & SOMO_LONGN_PRESENT) != 0)
585
    {
586
      off_t strtab_offset;
587
 
588
      simple_object_mach_o_section_info (omr->is_big_endian, is_32,
589
                                         secdata + strtab_index * sechdrsize,
590
                                         &strtab_offset, &strtab_size);
591
      strtab = XNEWVEC (char, strtab_size);
592
      if (!simple_object_internal_read (sobj->descriptor,
593
                                        sobj->offset + strtab_offset,
594
                                        (unsigned char *) strtab, strtab_size,
595
                                        errmsg, err))
596
        {
597
          XDELETEVEC (strtab);
598
          XDELETEVEC (index);
599
          XDELETEVEC (nametab);
600
          XDELETEVEC (secdata);
601
          return 0;
602
        }
603
    }
604
  else
605
    {
606
      strtab = NULL;
607
      strtab_size = 0;
608
      strtab_index = nsects;
609
    }
610
 
611
  /* Process the sections.  */
612
 
613
  for (i = 0; i < nsects; ++i)
614
    {
615
      const unsigned char *sechdr;
616
      char namebuf[MACH_O_NAME_LEN * 2 + 2];
617
      char *name;
618
      off_t secoffset;
619
      size_t secsize;
620
      int l;
621
 
622
      sechdr = secdata + i * sechdrsize;
623
 
624
      /* We've already processed the long section names.  */
625
 
626
      if ((gnu_sections_found & SOMO_LONGN_PRESENT) != 0
627
          && i == strtab_index)
628
        continue;
629
 
630
      /* We only act on the segment named.  */
631
 
632
      if (strcmp ((char *) sechdr + segname_offset, omr->segment_name) != 0)
633
        continue;
634
 
635
      /* Process sections associated with the wrapper.  */
636
 
637
      if ((gnu_sections_found & SOMO_WRAPPING) != 0)
638
        {
639
          if (i == nametab_index || i == index_index)
640
            continue;
641
 
642
          if (i == sections_index)
643
            {
644
              unsigned int j;
645
              for (j = 0; j < n_wrapped_sects; ++j)
646
                {
647
                  unsigned int subsect_offset, subsect_length, name_offset;
648
                  subsect_offset = (*fetch_32) (index + 16 * j);
649
                  subsect_length = (*fetch_32) (index + 16 * j + 4);
650
                  name_offset = (*fetch_32) (index + 16 * j + 8);
651
                  /* We don't need the name_length yet.  */
652
 
653
                  secoffset = wrapper_sect_offset + subsect_offset;
654
                  secsize = subsect_length;
655
                  name = nametab + name_offset;
656
 
657
                  if (!(*pfn) (data, name, secoffset, secsize))
658
                    {
659
                      *errmsg = NULL;
660
                      *err = 0;
661
                      XDELETEVEC (index);
662
                      XDELETEVEC (nametab);
663
                      XDELETEVEC (strtab);
664
                      XDELETEVEC (secdata);
665
                      return 0;
666
                    }
667
                }
668
              continue;
669
            }
670
        }
671
 
672
      if ((gnu_sections_found & SOMO_LONGN_PRESENT) != 0)
673
        {
674
          memcpy (namebuf, sechdr + sectname_offset, MACH_O_NAME_LEN);
675
          namebuf[MACH_O_NAME_LEN] = '\0';
676
 
677
          name = &namebuf[0];
678
          if (strtab != NULL && name[0] == '_' && name[1] == '_')
679
            {
680
              unsigned long stringoffset;
681
 
682
              if (sscanf (name + 2, "%08lX", &stringoffset) == 1)
683
                {
684
                  if (stringoffset >= strtab_size)
685
                    {
686
                      *errmsg = "section name offset out of range";
687
                      *err = 0;
688
                      XDELETEVEC (index);
689
                      XDELETEVEC (nametab);
690
                      XDELETEVEC (strtab);
691
                      XDELETEVEC (secdata);
692
                      return 0;
693
                    }
694
 
695
                  name = strtab + stringoffset;
696
                }
697
          }
698
        }
699
      else
700
        {
701
           /* Otherwise, make a name like __segment,__section as per the
702
              convention in mach-o asm.  */
703
          name = &namebuf[0];
704
          memset (namebuf, 0, MACH_O_NAME_LEN * 2 + 2);
705
          memcpy (namebuf, (char *) sechdr + segname_offset, MACH_O_NAME_LEN);
706
          l = strlen (namebuf);
707
          namebuf[l] = ',';
708
          memcpy (namebuf + l + 1, (char *) sechdr + sectname_offset,
709
                  MACH_O_NAME_LEN);
710
        }
711
 
712
      simple_object_mach_o_section_info (omr->is_big_endian, is_32, sechdr,
713
                                         &secoffset, &secsize);
714
 
715
      if (!(*pfn) (data, name, secoffset, secsize))
716
        {
717
          *errmsg = NULL;
718
          *err = 0;
719
          XDELETEVEC (index);
720
          XDELETEVEC (nametab);
721
          XDELETEVEC (strtab);
722
          XDELETEVEC (secdata);
723
          return 0;
724
        }
725
    }
726
 
727
  XDELETEVEC (index);
728
  XDELETEVEC (nametab);
729
  XDELETEVEC (strtab);
730
  XDELETEVEC (secdata);
731
 
732
  return 1;
733
}
734
 
735
/* Find all sections in a Mach-O file.  */
736
 
737
static const char *
738
simple_object_mach_o_find_sections (simple_object_read *sobj,
739
                                    int (*pfn) (void *, const char *,
740
                                                off_t offset, off_t length),
741
                                    void *data,
742
                                    int *err)
743
{
744
  struct simple_object_mach_o_read *omr =
745
    (struct simple_object_mach_o_read *) sobj->data;
746
  off_t offset;
747
  size_t seghdrsize;
748
  unsigned int (*fetch_32) (const unsigned char *);
749
  const char *errmsg;
750
  unsigned int i;
751
 
752
  if (omr->magic == MACH_O_MH_MAGIC)
753
    {
754
      offset = sizeof (struct mach_o_header_32);
755
      seghdrsize = sizeof (struct mach_o_segment_command_32);
756
    }
757
  else
758
    {
759
      offset = sizeof (struct mach_o_header_64);
760
      seghdrsize = sizeof (struct mach_o_segment_command_64);
761
    }
762
 
763
  fetch_32 = (omr->is_big_endian
764
              ? simple_object_fetch_big_32
765
              : simple_object_fetch_little_32);
766
 
767
  for (i = 0; i < omr->ncmds; ++i)
768
    {
769
      unsigned char loadbuf[sizeof (struct mach_o_load_command)];
770
      unsigned int cmd;
771
      unsigned int cmdsize;
772
 
773
      if (!simple_object_internal_read (sobj->descriptor,
774
                                        sobj->offset + offset,
775
                                        loadbuf,
776
                                        sizeof (struct mach_o_load_command),
777
                                        &errmsg, err))
778
        return errmsg;
779
 
780
      cmd = (*fetch_32) (loadbuf + offsetof (struct mach_o_load_command, cmd));
781
      cmdsize = (*fetch_32) (loadbuf
782
                             + offsetof (struct mach_o_load_command, cmdsize));
783
 
784
      if (cmd == MACH_O_LC_SEGMENT || cmd == MACH_O_LC_SEGMENT_64)
785
        {
786
          unsigned char segbuf[sizeof (struct mach_o_segment_command_64)];
787
          int r;
788
 
789
          if (!simple_object_internal_read (sobj->descriptor,
790
                                            sobj->offset + offset,
791
                                            segbuf, seghdrsize, &errmsg, err))
792
            return errmsg;
793
 
794
          r = simple_object_mach_o_segment (sobj, offset, segbuf, pfn,
795
                                            data, &errmsg, err);
796
          if (!r)
797
            return errmsg;
798
        }
799
 
800
      offset += cmdsize;
801
    }
802
 
803
  return NULL;
804
}
805
 
806
/* Fetch the attributes for an simple_object_read.  */
807
 
808
static void *
809
simple_object_mach_o_fetch_attributes (simple_object_read *sobj,
810
                                       const char **errmsg ATTRIBUTE_UNUSED,
811
                                       int *err ATTRIBUTE_UNUSED)
812
{
813
  struct simple_object_mach_o_read *omr =
814
    (struct simple_object_mach_o_read *) sobj->data;
815
  struct simple_object_mach_o_attributes *ret;
816
 
817
  ret = XNEW (struct simple_object_mach_o_attributes);
818
  ret->magic = omr->magic;
819
  ret->is_big_endian = omr->is_big_endian;
820
  ret->cputype = omr->cputype;
821
  ret->cpusubtype = omr->cpusubtype;
822
  ret->flags = omr->flags;
823
  ret->reserved = omr->reserved;
824
  return ret;
825
}
826
 
827
/* Release the private data for an simple_object_read.  */
828
 
829
static void
830
simple_object_mach_o_release_read (void *data)
831
{
832
  struct simple_object_mach_o_read *omr =
833
    (struct simple_object_mach_o_read *) data;
834
 
835
  free (omr->segment_name);
836
  XDELETE (omr);
837
}
838
 
839
/* Compare two attributes structures.  */
840
 
841
static const char *
842
simple_object_mach_o_attributes_merge (void *todata, void *fromdata, int *err)
843
{
844
  struct simple_object_mach_o_attributes *to =
845
    (struct simple_object_mach_o_attributes *) todata;
846
  struct simple_object_mach_o_attributes *from =
847
    (struct simple_object_mach_o_attributes *) fromdata;
848
 
849
  if (to->magic != from->magic
850
      || to->is_big_endian != from->is_big_endian
851
      || to->cputype != from->cputype)
852
    {
853
      *err = 0;
854
      return "Mach-O object format mismatch";
855
    }
856
  return NULL;
857
}
858
 
859
/* Release the private data for an attributes structure.  */
860
 
861
static void
862
simple_object_mach_o_release_attributes (void *data)
863
{
864
  XDELETE (data);
865
}
866
 
867
/* Prepare to write out a file.  */
868
 
869
static void *
870
simple_object_mach_o_start_write (void *attributes_data,
871
                                  const char **errmsg ATTRIBUTE_UNUSED,
872
                                  int *err ATTRIBUTE_UNUSED)
873
{
874
  struct simple_object_mach_o_attributes *attrs =
875
    (struct simple_object_mach_o_attributes *) attributes_data;
876
  struct simple_object_mach_o_attributes *ret;
877
 
878
  /* We're just going to record the attributes, but we need to make a
879
     copy because the user may delete them.  */
880
  ret = XNEW (struct simple_object_mach_o_attributes);
881
  *ret = *attrs;
882
  return ret;
883
}
884
 
885
/* Write out the header of a Mach-O file.  */
886
 
887
static int
888
simple_object_mach_o_write_header (simple_object_write *sobj, int descriptor,
889
                                   size_t nsects, const char **errmsg,
890
                                   int *err)
891
{
892
  struct simple_object_mach_o_attributes *attrs =
893
    (struct simple_object_mach_o_attributes *) sobj->data;
894
  void (*set_32) (unsigned char *, unsigned int);
895
  unsigned char hdrbuf[sizeof (struct mach_o_header_64)];
896
  unsigned char *hdr;
897
  size_t wrsize;
898
 
899
  set_32 = (attrs->is_big_endian
900
            ? simple_object_set_big_32
901
            : simple_object_set_little_32);
902
 
903
  memset (hdrbuf, 0, sizeof hdrbuf);
904
 
905
  /* The 32-bit and 64-bit headers start out the same.  */
906
 
907
  hdr = &hdrbuf[0];
908
  set_32 (hdr + offsetof (struct mach_o_header_32, magic), attrs->magic);
909
  set_32 (hdr + offsetof (struct mach_o_header_32, cputype), attrs->cputype);
910
  set_32 (hdr + offsetof (struct mach_o_header_32, cpusubtype),
911
          attrs->cpusubtype);
912
  set_32 (hdr + offsetof (struct mach_o_header_32, filetype), MACH_O_MH_OBJECT);
913
  set_32 (hdr + offsetof (struct mach_o_header_32, ncmds), 1);
914
  set_32 (hdr + offsetof (struct mach_o_header_32, flags), attrs->flags);
915
  if (attrs->magic == MACH_O_MH_MAGIC)
916
    {
917
      wrsize = sizeof (struct mach_o_header_32);
918
      set_32 (hdr + offsetof (struct mach_o_header_32, sizeofcmds),
919
              (sizeof (struct mach_o_segment_command_32)
920
               + nsects * sizeof (struct mach_o_section_32)));
921
    }
922
  else
923
    {
924
      set_32 (hdr + offsetof (struct mach_o_header_64, sizeofcmds),
925
              (sizeof (struct mach_o_segment_command_64)
926
               + nsects * sizeof (struct mach_o_section_64)));
927
      set_32 (hdr + offsetof (struct mach_o_header_64, reserved),
928
              attrs->reserved);
929
      wrsize = sizeof (struct mach_o_header_64);
930
    }
931
 
932
  return simple_object_internal_write (descriptor, 0, hdrbuf, wrsize,
933
                                       errmsg, err);
934
}
935
 
936
/* Write a Mach-O section header.  */
937
 
938
static int
939
simple_object_mach_o_write_section_header (simple_object_write *sobj,
940
                                           int descriptor,
941
                                           size_t sechdr_offset,
942
                                           const char *name, const char *segn,
943
                                           size_t secaddr, size_t secsize,
944
                                           size_t offset, unsigned int align,
945
                                           const char **errmsg, int *err)
946
{
947
  struct simple_object_mach_o_attributes *attrs =
948
    (struct simple_object_mach_o_attributes *) sobj->data;
949
  void (*set_32) (unsigned char *, unsigned int);
950
  unsigned char hdrbuf[sizeof (struct mach_o_section_64)];
951
  unsigned char *hdr;
952
  size_t sechdrsize;
953
 
954
  set_32 = (attrs->is_big_endian
955
            ? simple_object_set_big_32
956
            : simple_object_set_little_32);
957
 
958
  memset (hdrbuf, 0, sizeof hdrbuf);
959
 
960
  hdr = &hdrbuf[0];
961
  if (attrs->magic == MACH_O_MH_MAGIC)
962
    {
963
      strncpy ((char *) hdr + offsetof (struct mach_o_section_32, sectname),
964
               name, MACH_O_NAME_LEN);
965
      strncpy ((char *) hdr + offsetof (struct mach_o_section_32, segname),
966
               segn, MACH_O_NAME_LEN);
967
      set_32 (hdr + offsetof (struct mach_o_section_32, addr), secaddr);
968
      set_32 (hdr + offsetof (struct mach_o_section_32, size), secsize);
969
      set_32 (hdr + offsetof (struct mach_o_section_32, offset), offset);
970
      set_32 (hdr + offsetof (struct mach_o_section_32, align), align);
971
      /* reloff left as zero.  */
972
      /* nreloc left as zero.  */
973
      set_32 (hdr + offsetof (struct mach_o_section_32, flags),
974
              MACH_O_S_ATTR_DEBUG);
975
      /* reserved1 left as zero.  */
976
      /* reserved2 left as zero.  */
977
      sechdrsize = sizeof (struct mach_o_section_32);
978
    }
979
  else
980
    {
981
#ifdef UNSIGNED_64BIT_TYPE
982
      void (*set_64) (unsigned char *, ulong_type);
983
 
984
      set_64 = (attrs->is_big_endian
985
                ? simple_object_set_big_64
986
                : simple_object_set_little_64);
987
 
988
      strncpy ((char *) hdr + offsetof (struct mach_o_section_64, sectname),
989
               name, MACH_O_NAME_LEN);
990
      strncpy ((char *) hdr + offsetof (struct mach_o_section_64, segname),
991
               segn, MACH_O_NAME_LEN);
992
      set_64 (hdr + offsetof (struct mach_o_section_64, addr), secaddr);
993
      set_64 (hdr + offsetof (struct mach_o_section_64, size), secsize);
994
      set_32 (hdr + offsetof (struct mach_o_section_64, offset), offset);
995
      set_32 (hdr + offsetof (struct mach_o_section_64, align), align);
996
      /* reloff left as zero.  */
997
      /* nreloc left as zero.  */
998
      set_32 (hdr + offsetof (struct mach_o_section_64, flags),
999
              MACH_O_S_ATTR_DEBUG);
1000
      /* reserved1 left as zero.  */
1001
      /* reserved2 left as zero.  */
1002
      /* reserved3 left as zero.  */
1003
#endif
1004
      sechdrsize = sizeof (struct mach_o_section_64);
1005
    }
1006
 
1007
  return simple_object_internal_write (descriptor, sechdr_offset, hdr,
1008
                                       sechdrsize, errmsg, err);
1009
}
1010
 
1011
/* Write out the single (anonymous) segment containing the sections of a Mach-O
1012
   Object file.
1013
 
1014
   As a GNU extension to mach-o, when the caller specifies a segment name in
1015
   sobj->segment_name, all the sections passed will be output under a single
1016
   mach-o section header.  The caller's sections are indexed within this
1017
   'wrapper' section by a table stored in a second mach-o section.  Finally,
1018
   arbitrary length section names are permitted by the extension and these are
1019
   stored in a table in a third mach-o section.
1020
 
1021
   Note that this is only likely to make any sense for the __GNU_LTO segment
1022
   at present.
1023
 
1024
   If the wrapper extension is not in force, we assume that the section name
1025
   is in the form __SEGMENT_NAME,__section_name as per Mach-O asm.  */
1026
 
1027
static int
1028
simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
1029
                                    size_t *nsects, const char **errmsg,
1030
                                    int *err)
1031
{
1032
  struct simple_object_mach_o_attributes *attrs =
1033
    (struct simple_object_mach_o_attributes *) sobj->data;
1034
  void (*set_32) (unsigned char *, unsigned int);
1035
  size_t hdrsize;
1036
  size_t seghdrsize;
1037
  size_t sechdrsize;
1038
  size_t cmdsize;
1039
  size_t offset;
1040
  size_t sechdr_offset;
1041
  size_t secaddr;
1042
  unsigned int name_offset;
1043
  simple_object_write_section *section;
1044
  unsigned char hdrbuf[sizeof (struct mach_o_segment_command_64)];
1045
  unsigned char *hdr;
1046
  size_t nsects_in;
1047
  unsigned int *index;
1048
  char *snames;
1049
  unsigned int sect;
1050
 
1051
  set_32 = (attrs->is_big_endian
1052
            ? simple_object_set_big_32
1053
            : simple_object_set_little_32);
1054
 
1055
  /* Write out the sections first.  */
1056
 
1057
  if (attrs->magic == MACH_O_MH_MAGIC)
1058
    {
1059
      hdrsize = sizeof (struct mach_o_header_32);
1060
      seghdrsize = sizeof (struct mach_o_segment_command_32);
1061
      sechdrsize = sizeof (struct mach_o_section_32);
1062
    }
1063
  else
1064
    {
1065
      hdrsize = sizeof (struct mach_o_header_64);
1066
      seghdrsize = sizeof (struct mach_o_segment_command_64);
1067
      sechdrsize = sizeof (struct mach_o_section_64);
1068
    }
1069
 
1070
  name_offset = 0;
1071
  *nsects = nsects_in = 0;
1072
 
1073
  /* Count the number of sections we start with.  */
1074
 
1075
  for (section = sobj->sections; section != NULL; section = section->next)
1076
    nsects_in++;
1077
 
1078
  if (sobj->segment_name != NULL)
1079
    {
1080
      /* We will only write 3 sections: wrapped data, index and names.  */
1081
 
1082
      *nsects = 3;
1083
 
1084
      /* The index has four entries per wrapped section:
1085
           Section Offset, length,  Name offset, length.
1086
         Where the offsets are based at the start of the wrapper and name
1087
         sections respectively.
1088
         The values are stored as 32 bit int for both 32 and 64 bit mach-o
1089
         since the size of a mach-o MH_OBJECT cannot exceed 4G owing to
1090
         other constraints.  */
1091
 
1092
      index = XNEWVEC (unsigned int, nsects_in * 4);
1093
 
1094
      /* We now need to figure out the size of the names section.  This just
1095
         stores the names as null-terminated c strings, packed without any
1096
         alignment padding.  */
1097
 
1098
      for (section = sobj->sections, sect = 0; section != NULL;
1099
           section = section->next, sect++)
1100
        {
1101
          index[sect*4+2] = name_offset;
1102
          index[sect*4+3] = strlen (section->name) + 1;
1103
          name_offset += strlen (section->name) + 1;
1104
        }
1105
      snames = XNEWVEC (char, name_offset);
1106
    }
1107
  else
1108
    {
1109
      *nsects = nsects_in;
1110
      index = NULL;
1111
      snames = NULL;
1112
    }
1113
 
1114
  sechdr_offset = hdrsize + seghdrsize;
1115
  cmdsize = seghdrsize + *nsects * sechdrsize;
1116
  offset = hdrsize + cmdsize;
1117
  secaddr = 0;
1118
 
1119
  for (section = sobj->sections, sect = 0;
1120
       section != NULL; section = section->next, sect++)
1121
    {
1122
      size_t mask;
1123
      size_t new_offset;
1124
      size_t secsize;
1125
      struct simple_object_write_section_buffer *buffer;
1126
 
1127
      mask = (1U << section->align) - 1;
1128
      new_offset = offset + mask;
1129
      new_offset &= ~ mask;
1130
      while (new_offset > offset)
1131
        {
1132
          unsigned char zeroes[16];
1133
          size_t write;
1134
 
1135
          memset (zeroes, 0, sizeof zeroes);
1136
          write = new_offset - offset;
1137
          if (write > sizeof zeroes)
1138
            write = sizeof zeroes;
1139
          if (!simple_object_internal_write (descriptor, offset, zeroes, write,
1140
                                             errmsg, err))
1141
            return 0;
1142
          offset += write;
1143
        }
1144
 
1145
      secsize = 0;
1146
      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
1147
        {
1148
          if (!simple_object_internal_write (descriptor, offset + secsize,
1149
                                             ((const unsigned char *)
1150
                                              buffer->buffer),
1151
                                             buffer->size, errmsg, err))
1152
            return 0;
1153
          secsize += buffer->size;
1154
        }
1155
 
1156
      if (sobj->segment_name != NULL)
1157
        {
1158
          index[sect*4+0] = (unsigned int) offset;
1159
          index[sect*4+1] = secsize;
1160
          /* Stash the section name in our table.  */
1161
          memcpy (snames + index[sect * 4 + 2], section->name,
1162
                  index[sect * 4 + 3]);
1163
        }
1164
      else
1165
        {
1166
          char namebuf[MACH_O_NAME_LEN + 1];
1167
          char segnbuf[MACH_O_NAME_LEN + 1];
1168
          char *comma;
1169
 
1170
          /* Try to extract segment,section from the input name.  */
1171
 
1172
          memset (namebuf, 0, sizeof namebuf);
1173
          memset (segnbuf, 0, sizeof segnbuf);
1174
          comma = strchr (section->name, ',');
1175
          if (comma != NULL)
1176
            {
1177
              int len = comma - section->name;
1178
              len = len > MACH_O_NAME_LEN ? MACH_O_NAME_LEN : len;
1179
              strncpy (namebuf, section->name, len);
1180
              strncpy (segnbuf, comma + 1, MACH_O_NAME_LEN);
1181
            }
1182
          else /* just try to copy the name, leave segment blank.  */
1183
            strncpy (namebuf, section->name, MACH_O_NAME_LEN);
1184
 
1185
          if (!simple_object_mach_o_write_section_header (sobj, descriptor,
1186
                                                          sechdr_offset,
1187
                                                          namebuf, segnbuf,
1188
                                                          secaddr, secsize,
1189
                                                          offset,
1190
                                                          section->align,
1191
                                                          errmsg, err))
1192
            return 0;
1193
          sechdr_offset += sechdrsize;
1194
        }
1195
 
1196
      offset += secsize;
1197
      secaddr += secsize;
1198
    }
1199
 
1200
  if (sobj->segment_name != NULL)
1201
    {
1202
      size_t secsize;
1203
      unsigned int i;
1204
 
1205
      /* Write the section header for the wrapper.  */
1206
      /* Account for any initial aligment - which becomes the alignment for this
1207
         created section.  */
1208
 
1209
      secsize = (offset - index[0]);
1210
      if (!simple_object_mach_o_write_section_header (sobj, descriptor,
1211
                                                      sechdr_offset,
1212
                                                      GNU_WRAPPER_SECTS,
1213
                                                      sobj->segment_name,
1214
 
1215
                                                      secsize, index[0],
1216
                                                      sobj->sections->align,
1217
                                                      errmsg, err))
1218
        return 0;
1219
 
1220
      /* Subtract the wrapper section start from the begining of each sub
1221
         section.  */
1222
 
1223
      for (i = 1; i < nsects_in; ++i)
1224
        index[4 * i] -= index[0];
1225
      index[0] = 0;
1226
 
1227
      sechdr_offset += sechdrsize;
1228
 
1229
      /* Write out the section names.
1230
         ... the header ...
1231
         name_offset contains the length of the section.  It is not aligned.  */
1232
 
1233
      if (!simple_object_mach_o_write_section_header (sobj, descriptor,
1234
                                                      sechdr_offset,
1235
                                                      GNU_WRAPPER_NAMES,
1236
                                                      sobj->segment_name,
1237
 
1238
                                                      name_offset,
1239
                                                      offset,
1240
                                                      0, errmsg, err))
1241
        return 0;
1242
 
1243
      /* ... and the content.. */
1244
      if (!simple_object_internal_write (descriptor, offset,
1245
                                         (const unsigned char *) snames,
1246
                                         name_offset, errmsg, err))
1247
        return 0;
1248
 
1249
      sechdr_offset += sechdrsize;
1250
      secaddr += name_offset;
1251
      offset += name_offset;
1252
 
1253
      /* Now do the index, we'll align this to 4 bytes although the read code
1254
         will handle unaligned.  */
1255
 
1256
      offset += 3;
1257
      offset &= ~0x03;
1258
      if (!simple_object_mach_o_write_section_header (sobj, descriptor,
1259
                                                      sechdr_offset,
1260
                                                      GNU_WRAPPER_INDEX,
1261
                                                      sobj->segment_name,
1262
 
1263
                                                      nsects_in * 16,
1264
                                                      offset,
1265
                                                      2, errmsg, err))
1266
        return 0;
1267
 
1268
      /* ... and the content.. */
1269
      if (!simple_object_internal_write (descriptor, offset,
1270
                                         (const unsigned char *) index,
1271
                                         nsects_in*16, errmsg, err))
1272
        return 0;
1273
 
1274
      XDELETEVEC (index);
1275
      XDELETEVEC (snames);
1276
    }
1277
 
1278
  /* Write out the segment header.  */
1279
 
1280
  memset (hdrbuf, 0, sizeof hdrbuf);
1281
 
1282
  hdr = &hdrbuf[0];
1283
  if (attrs->magic == MACH_O_MH_MAGIC)
1284
    {
1285
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmd),
1286
              MACH_O_LC_SEGMENT);
1287
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmdsize),
1288
              cmdsize);
1289
     /* MH_OBJECTS have a single, anonymous, segment - so the segment name
1290
         is left empty.  */
1291
      /* vmaddr left as zero.  */
1292
      /* vmsize left as zero.  */
1293
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, fileoff),
1294
              hdrsize + cmdsize);
1295
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, filesize),
1296
              offset - (hdrsize + cmdsize));
1297
      /* maxprot left as zero.  */
1298
      /* initprot left as zero.  */
1299
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, nsects),
1300
              *nsects);
1301
      /* flags left as zero.  */
1302
    }
1303
  else
1304
    {
1305
#ifdef UNSIGNED_64BIT_TYPE
1306
      void (*set_64) (unsigned char *, ulong_type);
1307
 
1308
      set_64 = (attrs->is_big_endian
1309
                ? simple_object_set_big_64
1310
                : simple_object_set_little_64);
1311
 
1312
      set_32 (hdr + offsetof (struct mach_o_segment_command_64, cmd),
1313
              MACH_O_LC_SEGMENT);
1314
      set_32 (hdr + offsetof (struct mach_o_segment_command_64, cmdsize),
1315
              cmdsize);
1316
      /* MH_OBJECTS have a single, anonymous, segment - so the segment name
1317
         is left empty.  */
1318
      /* vmaddr left as zero.  */
1319
      /* vmsize left as zero.  */
1320
      set_64 (hdr + offsetof (struct mach_o_segment_command_64, fileoff),
1321
              hdrsize + cmdsize);
1322
      set_64 (hdr + offsetof (struct mach_o_segment_command_64, filesize),
1323
              offset - (hdrsize + cmdsize));
1324
      /* maxprot left as zero.  */
1325
      /* initprot left as zero.  */
1326
      set_32 (hdr + offsetof (struct mach_o_segment_command_64, nsects),
1327
              *nsects);
1328
      /* flags left as zero.  */
1329
#endif
1330
    }
1331
 
1332
  return simple_object_internal_write (descriptor, hdrsize, hdr, seghdrsize,
1333
                                       errmsg, err);
1334
}
1335
 
1336
/* Write out a complete Mach-O file.  */
1337
 
1338
static const char *
1339
simple_object_mach_o_write_to_file (simple_object_write *sobj, int descriptor,
1340
                                    int *err)
1341
{
1342
  size_t nsects = 0;
1343
  const char *errmsg;
1344
 
1345
  if (!simple_object_mach_o_write_segment (sobj, descriptor, &nsects,
1346
                                           &errmsg, err))
1347
    return errmsg;
1348
 
1349
  if (!simple_object_mach_o_write_header (sobj, descriptor, nsects,
1350
                                          &errmsg, err))
1351
    return errmsg;
1352
 
1353
  return NULL;
1354
}
1355
 
1356
/* Release the private data for an simple_object_write structure.  */
1357
 
1358
static void
1359
simple_object_mach_o_release_write (void *data)
1360
{
1361
  XDELETE (data);
1362
}
1363
 
1364
/* The Mach-O functions.  */
1365
 
1366
const struct simple_object_functions simple_object_mach_o_functions =
1367
{
1368
  simple_object_mach_o_match,
1369
  simple_object_mach_o_find_sections,
1370
  simple_object_mach_o_fetch_attributes,
1371
  simple_object_mach_o_release_read,
1372
  simple_object_mach_o_attributes_merge,
1373
  simple_object_mach_o_release_attributes,
1374
  simple_object_mach_o_start_write,
1375
  simple_object_mach_o_write_to_file,
1376
  simple_object_mach_o_release_write
1377
};

powered by: WebSVN 2.1.0

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