OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / libiberty / simple-object-mach-o.c
1 /* 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    0 - LC_SEGMENT/LC_SEGMENT64
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                                                       0 /*secaddr*/,
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                                                       0 /*secaddr*/,
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                                                       0 /*secaddr*/,
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 };