Import GCC-8 to a new vendor branch
[dragonfly.git] / contrib / gcc-8.0 / libiberty / simple-object-mach-o.c
1 /* simple-object-mach-o.c -- routines to manipulate Mach-O object files.
2    Copyright (C) 2010-2018 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 = 0;
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           memcpy (namebuf, (char *) sechdr + segname_offset, MACH_O_NAME_LEN);
705           namebuf[MACH_O_NAME_LEN] = '\0';
706           l = strlen (namebuf);
707           namebuf[l] = ',';
708           memcpy (namebuf + l + 1, (char *) sechdr + sectname_offset,
709                   MACH_O_NAME_LEN);
710           namebuf[l + 1 + MACH_O_NAME_LEN] = '\0';
711         }
712
713       simple_object_mach_o_section_info (omr->is_big_endian, is_32, sechdr,
714                                          &secoffset, &secsize);
715
716       if (!(*pfn) (data, name, secoffset, secsize))
717         {
718           *errmsg = NULL;
719           *err = 0;
720           XDELETEVEC (index);
721           XDELETEVEC (nametab);
722           XDELETEVEC (strtab);
723           XDELETEVEC (secdata);
724           return 0;
725         }
726     }
727
728   XDELETEVEC (index);
729   XDELETEVEC (nametab);
730   XDELETEVEC (strtab);
731   XDELETEVEC (secdata);
732
733   return 1;
734 }
735
736 /* Find all sections in a Mach-O file.  */
737
738 static const char *
739 simple_object_mach_o_find_sections (simple_object_read *sobj,
740                                     int (*pfn) (void *, const char *,
741                                                 off_t offset, off_t length),
742                                     void *data,
743                                     int *err)
744 {
745   struct simple_object_mach_o_read *omr =
746     (struct simple_object_mach_o_read *) sobj->data;
747   off_t offset;
748   size_t seghdrsize;
749   unsigned int (*fetch_32) (const unsigned char *);
750   const char *errmsg;
751   unsigned int i;
752
753   if (omr->magic == MACH_O_MH_MAGIC)
754     {
755       offset = sizeof (struct mach_o_header_32);
756       seghdrsize = sizeof (struct mach_o_segment_command_32);
757     }
758   else
759     {
760       offset = sizeof (struct mach_o_header_64);
761       seghdrsize = sizeof (struct mach_o_segment_command_64);
762     }
763
764   fetch_32 = (omr->is_big_endian
765               ? simple_object_fetch_big_32
766               : simple_object_fetch_little_32);
767
768   for (i = 0; i < omr->ncmds; ++i)
769     {
770       unsigned char loadbuf[sizeof (struct mach_o_load_command)];
771       unsigned int cmd;
772       unsigned int cmdsize;
773
774       if (!simple_object_internal_read (sobj->descriptor,
775                                         sobj->offset + offset,
776                                         loadbuf,
777                                         sizeof (struct mach_o_load_command),
778                                         &errmsg, err))
779         return errmsg;
780
781       cmd = (*fetch_32) (loadbuf + offsetof (struct mach_o_load_command, cmd));
782       cmdsize = (*fetch_32) (loadbuf
783                              + offsetof (struct mach_o_load_command, cmdsize));
784
785       if (cmd == MACH_O_LC_SEGMENT || cmd == MACH_O_LC_SEGMENT_64)
786         {
787           unsigned char segbuf[sizeof (struct mach_o_segment_command_64)];
788           int r;
789
790           if (!simple_object_internal_read (sobj->descriptor,
791                                             sobj->offset + offset,
792                                             segbuf, seghdrsize, &errmsg, err))
793             return errmsg;
794
795           r = simple_object_mach_o_segment (sobj, offset, segbuf, pfn,
796                                             data, &errmsg, err);
797           if (!r)
798             return errmsg;
799         }
800
801       offset += cmdsize;
802     }
803
804   return NULL;
805 }
806
807 /* Fetch the attributes for an simple_object_read.  */
808
809 static void *
810 simple_object_mach_o_fetch_attributes (simple_object_read *sobj,
811                                        const char **errmsg ATTRIBUTE_UNUSED,
812                                        int *err ATTRIBUTE_UNUSED)
813 {
814   struct simple_object_mach_o_read *omr =
815     (struct simple_object_mach_o_read *) sobj->data;
816   struct simple_object_mach_o_attributes *ret;
817
818   ret = XNEW (struct simple_object_mach_o_attributes);
819   ret->magic = omr->magic;
820   ret->is_big_endian = omr->is_big_endian;
821   ret->cputype = omr->cputype;
822   ret->cpusubtype = omr->cpusubtype;
823   ret->flags = omr->flags;
824   ret->reserved = omr->reserved;
825   return ret;
826 }
827
828 /* Release the private data for an simple_object_read.  */
829
830 static void
831 simple_object_mach_o_release_read (void *data)
832 {
833   struct simple_object_mach_o_read *omr =
834     (struct simple_object_mach_o_read *) data;
835
836   free (omr->segment_name);
837   XDELETE (omr);
838 }
839
840 /* Compare two attributes structures.  */
841
842 static const char *
843 simple_object_mach_o_attributes_merge (void *todata, void *fromdata, int *err)
844 {
845   struct simple_object_mach_o_attributes *to =
846     (struct simple_object_mach_o_attributes *) todata;
847   struct simple_object_mach_o_attributes *from =
848     (struct simple_object_mach_o_attributes *) fromdata;
849
850   if (to->magic != from->magic
851       || to->is_big_endian != from->is_big_endian
852       || to->cputype != from->cputype)
853     {
854       *err = 0;
855       return "Mach-O object format mismatch";
856     }
857   return NULL;
858 }
859
860 /* Release the private data for an attributes structure.  */
861
862 static void
863 simple_object_mach_o_release_attributes (void *data)
864 {
865   XDELETE (data);
866 }
867
868 /* Prepare to write out a file.  */
869
870 static void *
871 simple_object_mach_o_start_write (void *attributes_data,
872                                   const char **errmsg ATTRIBUTE_UNUSED,
873                                   int *err ATTRIBUTE_UNUSED)
874 {
875   struct simple_object_mach_o_attributes *attrs =
876     (struct simple_object_mach_o_attributes *) attributes_data;
877   struct simple_object_mach_o_attributes *ret;
878
879   /* We're just going to record the attributes, but we need to make a
880      copy because the user may delete them.  */
881   ret = XNEW (struct simple_object_mach_o_attributes);
882   *ret = *attrs;
883   return ret;
884 }
885
886 /* Write out the header of a Mach-O file.  */
887
888 static int
889 simple_object_mach_o_write_header (simple_object_write *sobj, int descriptor,
890                                    size_t nsects, const char **errmsg,
891                                    int *err)
892 {
893   struct simple_object_mach_o_attributes *attrs =
894     (struct simple_object_mach_o_attributes *) sobj->data;
895   void (*set_32) (unsigned char *, unsigned int);
896   unsigned char hdrbuf[sizeof (struct mach_o_header_64)];
897   unsigned char *hdr;
898   size_t wrsize;
899
900   set_32 = (attrs->is_big_endian
901             ? simple_object_set_big_32
902             : simple_object_set_little_32);
903
904   memset (hdrbuf, 0, sizeof hdrbuf);
905
906   /* The 32-bit and 64-bit headers start out the same.  */
907
908   hdr = &hdrbuf[0];
909   set_32 (hdr + offsetof (struct mach_o_header_32, magic), attrs->magic);
910   set_32 (hdr + offsetof (struct mach_o_header_32, cputype), attrs->cputype);
911   set_32 (hdr + offsetof (struct mach_o_header_32, cpusubtype),
912           attrs->cpusubtype);
913   set_32 (hdr + offsetof (struct mach_o_header_32, filetype), MACH_O_MH_OBJECT);
914   set_32 (hdr + offsetof (struct mach_o_header_32, ncmds), 1);
915   set_32 (hdr + offsetof (struct mach_o_header_32, flags), attrs->flags);
916   if (attrs->magic == MACH_O_MH_MAGIC)
917     {
918       wrsize = sizeof (struct mach_o_header_32);
919       set_32 (hdr + offsetof (struct mach_o_header_32, sizeofcmds),
920               (sizeof (struct mach_o_segment_command_32)
921                + nsects * sizeof (struct mach_o_section_32)));
922     }
923   else
924     {
925       set_32 (hdr + offsetof (struct mach_o_header_64, sizeofcmds),
926               (sizeof (struct mach_o_segment_command_64)
927                + nsects * sizeof (struct mach_o_section_64)));
928       set_32 (hdr + offsetof (struct mach_o_header_64, reserved),
929               attrs->reserved);
930       wrsize = sizeof (struct mach_o_header_64);
931     }
932
933   return simple_object_internal_write (descriptor, 0, hdrbuf, wrsize,
934                                        errmsg, err);
935 }
936
937 /* Write a Mach-O section header.  */
938
939 static int
940 simple_object_mach_o_write_section_header (simple_object_write *sobj,
941                                            int descriptor,
942                                            size_t sechdr_offset,
943                                            const char *name, const char *segn,
944                                            size_t secaddr, size_t secsize,
945                                            size_t offset, unsigned int align,
946                                            const char **errmsg, int *err)
947 {
948   struct simple_object_mach_o_attributes *attrs =
949     (struct simple_object_mach_o_attributes *) sobj->data;
950   void (*set_32) (unsigned char *, unsigned int);
951   unsigned char hdrbuf[sizeof (struct mach_o_section_64)];
952   unsigned char *hdr;
953   size_t sechdrsize;
954
955   set_32 = (attrs->is_big_endian
956             ? simple_object_set_big_32
957             : simple_object_set_little_32);
958
959   memset (hdrbuf, 0, sizeof hdrbuf);
960
961   hdr = &hdrbuf[0];
962   if (attrs->magic == MACH_O_MH_MAGIC)
963     {
964       strncpy ((char *) hdr + offsetof (struct mach_o_section_32, sectname),
965                name, MACH_O_NAME_LEN);
966       strncpy ((char *) hdr + offsetof (struct mach_o_section_32, segname),
967                segn, MACH_O_NAME_LEN);
968       set_32 (hdr + offsetof (struct mach_o_section_32, addr), secaddr);
969       set_32 (hdr + offsetof (struct mach_o_section_32, size), secsize);
970       set_32 (hdr + offsetof (struct mach_o_section_32, offset), offset);
971       set_32 (hdr + offsetof (struct mach_o_section_32, align), align);
972       /* reloff left as zero.  */
973       /* nreloc left as zero.  */
974       set_32 (hdr + offsetof (struct mach_o_section_32, flags),
975               MACH_O_S_ATTR_DEBUG);
976       /* reserved1 left as zero.  */
977       /* reserved2 left as zero.  */
978       sechdrsize = sizeof (struct mach_o_section_32);
979     }
980   else
981     {
982 #ifdef UNSIGNED_64BIT_TYPE
983       void (*set_64) (unsigned char *, ulong_type);
984
985       set_64 = (attrs->is_big_endian
986                 ? simple_object_set_big_64
987                 : simple_object_set_little_64);
988
989       strncpy ((char *) hdr + offsetof (struct mach_o_section_64, sectname),
990                name, MACH_O_NAME_LEN);
991       strncpy ((char *) hdr + offsetof (struct mach_o_section_64, segname),
992                segn, MACH_O_NAME_LEN);
993       set_64 (hdr + offsetof (struct mach_o_section_64, addr), secaddr);
994       set_64 (hdr + offsetof (struct mach_o_section_64, size), secsize);
995       set_32 (hdr + offsetof (struct mach_o_section_64, offset), offset);
996       set_32 (hdr + offsetof (struct mach_o_section_64, align), align);
997       /* reloff left as zero.  */
998       /* nreloc left as zero.  */
999       set_32 (hdr + offsetof (struct mach_o_section_64, flags),
1000               MACH_O_S_ATTR_DEBUG);
1001       /* reserved1 left as zero.  */
1002       /* reserved2 left as zero.  */
1003       /* reserved3 left as zero.  */
1004 #endif
1005       sechdrsize = sizeof (struct mach_o_section_64);
1006     }
1007
1008   return simple_object_internal_write (descriptor, sechdr_offset, hdr,
1009                                        sechdrsize, errmsg, err);
1010 }
1011
1012 /* Write out the single (anonymous) segment containing the sections of a Mach-O
1013    Object file.
1014
1015    As a GNU extension to mach-o, when the caller specifies a segment name in
1016    sobj->segment_name, all the sections passed will be output under a single
1017    mach-o section header.  The caller's sections are indexed within this
1018    'wrapper' section by a table stored in a second mach-o section.  Finally,
1019    arbitrary length section names are permitted by the extension and these are
1020    stored in a table in a third mach-o section.
1021
1022    Note that this is only likely to make any sense for the __GNU_LTO segment
1023    at present.
1024
1025    If the wrapper extension is not in force, we assume that the section name
1026    is in the form __SEGMENT_NAME,__section_name as per Mach-O asm.  */
1027
1028 static int
1029 simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
1030                                     size_t *nsects, const char **errmsg,
1031                                     int *err)
1032 {
1033   struct simple_object_mach_o_attributes *attrs =
1034     (struct simple_object_mach_o_attributes *) sobj->data;
1035   void (*set_32) (unsigned char *, unsigned int);
1036   size_t hdrsize;
1037   size_t seghdrsize;
1038   size_t sechdrsize;
1039   size_t cmdsize;
1040   size_t offset;
1041   size_t sechdr_offset;
1042   size_t secaddr;
1043   unsigned int name_offset;
1044   simple_object_write_section *section;
1045   unsigned char hdrbuf[sizeof (struct mach_o_segment_command_64)];
1046   unsigned char *hdr;
1047   size_t nsects_in;
1048   unsigned int *index;
1049   char *snames;
1050   unsigned int sect;
1051
1052   set_32 = (attrs->is_big_endian
1053             ? simple_object_set_big_32
1054             : simple_object_set_little_32);
1055
1056   /* Write out the sections first.  */
1057
1058   if (attrs->magic == MACH_O_MH_MAGIC)
1059     {
1060       hdrsize = sizeof (struct mach_o_header_32);
1061       seghdrsize = sizeof (struct mach_o_segment_command_32);
1062       sechdrsize = sizeof (struct mach_o_section_32);
1063     }
1064   else
1065     {
1066       hdrsize = sizeof (struct mach_o_header_64);
1067       seghdrsize = sizeof (struct mach_o_segment_command_64);
1068       sechdrsize = sizeof (struct mach_o_section_64);
1069     }
1070
1071   name_offset = 0;
1072   *nsects = nsects_in = 0;
1073
1074   /* Count the number of sections we start with.  */
1075
1076   for (section = sobj->sections; section != NULL; section = section->next)
1077     nsects_in++;
1078
1079   if (sobj->segment_name != NULL)
1080     {
1081       /* We will only write 3 sections: wrapped data, index and names.  */
1082
1083       *nsects = 3;
1084
1085       /* The index has four entries per wrapped section:
1086            Section Offset, length,  Name offset, length.
1087          Where the offsets are based at the start of the wrapper and name
1088          sections respectively.
1089          The values are stored as 32 bit int for both 32 and 64 bit mach-o
1090          since the size of a mach-o MH_OBJECT cannot exceed 4G owing to
1091          other constraints.  */
1092
1093       index = XNEWVEC (unsigned int, nsects_in * 4);
1094
1095       /* We now need to figure out the size of the names section.  This just
1096          stores the names as null-terminated c strings, packed without any
1097          alignment padding.  */
1098
1099       for (section = sobj->sections, sect = 0; section != NULL;
1100            section = section->next, sect++)
1101         {
1102           index[sect*4+2] = name_offset;
1103           index[sect*4+3] = strlen (section->name) + 1;
1104           name_offset += strlen (section->name) + 1;
1105         }
1106       snames = XNEWVEC (char, name_offset);
1107     }
1108   else
1109     {
1110       *nsects = nsects_in;
1111       index = NULL;
1112       snames = NULL;
1113     }
1114
1115   sechdr_offset = hdrsize + seghdrsize;
1116   cmdsize = seghdrsize + *nsects * sechdrsize;
1117   offset = hdrsize + cmdsize;
1118   secaddr = 0;
1119
1120   for (section = sobj->sections, sect = 0;
1121        section != NULL; section = section->next, sect++)
1122     {
1123       size_t mask;
1124       size_t new_offset;
1125       size_t secsize;
1126       struct simple_object_write_section_buffer *buffer;
1127
1128       mask = (1U << section->align) - 1;
1129       new_offset = offset + mask;
1130       new_offset &= ~ mask;
1131       while (new_offset > offset)
1132         {
1133           unsigned char zeroes[16];
1134           size_t write;
1135
1136           memset (zeroes, 0, sizeof zeroes);
1137           write = new_offset - offset;
1138           if (write > sizeof zeroes)
1139             write = sizeof zeroes;
1140           if (!simple_object_internal_write (descriptor, offset, zeroes, write,
1141                                              errmsg, err))
1142             return 0;
1143           offset += write;
1144         }
1145
1146       secsize = 0;
1147       for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
1148         {
1149           if (!simple_object_internal_write (descriptor, offset + secsize,
1150                                              ((const unsigned char *)
1151                                               buffer->buffer),
1152                                              buffer->size, errmsg, err))
1153             return 0;
1154           secsize += buffer->size;
1155         }
1156
1157       if (sobj->segment_name != NULL)
1158         {
1159           index[sect*4+0] = (unsigned int) offset;
1160           index[sect*4+1] = secsize;
1161           /* Stash the section name in our table.  */
1162           memcpy (snames + index[sect * 4 + 2], section->name,
1163                   index[sect * 4 + 3]);
1164         }
1165       else
1166         {
1167           char namebuf[MACH_O_NAME_LEN + 1];
1168           char segnbuf[MACH_O_NAME_LEN + 1];
1169           char *comma;
1170
1171           /* Try to extract segment,section from the input name.  */
1172
1173           memset (namebuf, 0, sizeof namebuf);
1174           memset (segnbuf, 0, sizeof segnbuf);
1175           comma = strchr (section->name, ',');
1176           if (comma != NULL)
1177             {
1178               int len = comma - section->name;
1179               len = len > MACH_O_NAME_LEN ? MACH_O_NAME_LEN : len;
1180               strncpy (namebuf, section->name, len);
1181               strncpy (segnbuf, comma + 1, MACH_O_NAME_LEN);
1182             }
1183           else /* just try to copy the name, leave segment blank.  */
1184             strncpy (namebuf, section->name, MACH_O_NAME_LEN);
1185
1186           if (!simple_object_mach_o_write_section_header (sobj, descriptor,
1187                                                           sechdr_offset,
1188                                                           namebuf, segnbuf,
1189                                                           secaddr, secsize,
1190                                                           offset,
1191                                                           section->align,
1192                                                           errmsg, err))
1193             return 0;
1194           sechdr_offset += sechdrsize;
1195         }
1196
1197       offset += secsize;
1198       secaddr += secsize;
1199     }
1200
1201   if (sobj->segment_name != NULL)
1202     {
1203       size_t secsize;
1204       unsigned int i;
1205
1206       /* Write the section header for the wrapper.  */
1207       /* Account for any initial aligment - which becomes the alignment for this
1208          created section.  */
1209
1210       secsize = (offset - index[0]);
1211       if (!simple_object_mach_o_write_section_header (sobj, descriptor,
1212                                                       sechdr_offset,
1213                                                       GNU_WRAPPER_SECTS,
1214                                                       sobj->segment_name,
1215                                                       0 /*secaddr*/,
1216                                                       secsize, index[0],
1217                                                       sobj->sections->align,
1218                                                       errmsg, err))
1219         return 0;
1220
1221       /* Subtract the wrapper section start from the begining of each sub
1222          section.  */
1223
1224       for (i = 1; i < nsects_in; ++i)
1225         index[4 * i] -= index[0];
1226       index[0] = 0;
1227
1228       sechdr_offset += sechdrsize;
1229
1230       /* Write out the section names.
1231          ... the header ...
1232          name_offset contains the length of the section.  It is not aligned.  */
1233
1234       if (!simple_object_mach_o_write_section_header (sobj, descriptor,
1235                                                       sechdr_offset,
1236                                                       GNU_WRAPPER_NAMES,
1237                                                       sobj->segment_name,
1238                                                       0 /*secaddr*/,
1239                                                       name_offset,
1240                                                       offset,
1241                                                       0, errmsg, err))
1242         return 0;
1243
1244       /* ... and the content.. */
1245       if (!simple_object_internal_write (descriptor, offset,
1246                                          (const unsigned char *) snames,
1247                                          name_offset, errmsg, err))
1248         return 0;
1249
1250       sechdr_offset += sechdrsize;
1251       secaddr += name_offset;
1252       offset += name_offset;
1253
1254       /* Now do the index, we'll align this to 4 bytes although the read code
1255          will handle unaligned.  */
1256
1257       offset += 3;
1258       offset &= ~0x03;
1259       if (!simple_object_mach_o_write_section_header (sobj, descriptor,
1260                                                       sechdr_offset,
1261                                                       GNU_WRAPPER_INDEX,
1262                                                       sobj->segment_name,
1263                                                       0 /*secaddr*/,
1264                                                       nsects_in * 16,
1265                                                       offset,
1266                                                       2, errmsg, err))
1267         return 0;
1268
1269       /* ... and the content.. */
1270       if (!simple_object_internal_write (descriptor, offset,
1271                                          (const unsigned char *) index,
1272                                          nsects_in*16, errmsg, err))
1273         return 0;
1274
1275       XDELETEVEC (index);
1276       XDELETEVEC (snames);
1277     }
1278
1279   /* Write out the segment header.  */
1280
1281   memset (hdrbuf, 0, sizeof hdrbuf);
1282
1283   hdr = &hdrbuf[0];
1284   if (attrs->magic == MACH_O_MH_MAGIC)
1285     {
1286       set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmd),
1287               MACH_O_LC_SEGMENT);
1288       set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmdsize),
1289               cmdsize);
1290      /* MH_OBJECTS have a single, anonymous, segment - so the segment name
1291          is left empty.  */
1292       /* vmaddr left as zero.  */
1293       /* vmsize left as zero.  */
1294       set_32 (hdr + offsetof (struct mach_o_segment_command_32, fileoff),
1295               hdrsize + cmdsize);
1296       set_32 (hdr + offsetof (struct mach_o_segment_command_32, filesize),
1297               offset - (hdrsize + cmdsize));
1298       /* maxprot left as zero.  */
1299       /* initprot left as zero.  */
1300       set_32 (hdr + offsetof (struct mach_o_segment_command_32, nsects),
1301               *nsects);
1302       /* flags left as zero.  */
1303     }
1304   else
1305     {
1306 #ifdef UNSIGNED_64BIT_TYPE
1307       void (*set_64) (unsigned char *, ulong_type);
1308
1309       set_64 = (attrs->is_big_endian
1310                 ? simple_object_set_big_64
1311                 : simple_object_set_little_64);
1312
1313       set_32 (hdr + offsetof (struct mach_o_segment_command_64, cmd),
1314               MACH_O_LC_SEGMENT);
1315       set_32 (hdr + offsetof (struct mach_o_segment_command_64, cmdsize),
1316               cmdsize);
1317       /* MH_OBJECTS have a single, anonymous, segment - so the segment name
1318          is left empty.  */
1319       /* vmaddr left as zero.  */
1320       /* vmsize left as zero.  */
1321       set_64 (hdr + offsetof (struct mach_o_segment_command_64, fileoff),
1322               hdrsize + cmdsize);
1323       set_64 (hdr + offsetof (struct mach_o_segment_command_64, filesize),
1324               offset - (hdrsize + cmdsize));
1325       /* maxprot left as zero.  */
1326       /* initprot left as zero.  */
1327       set_32 (hdr + offsetof (struct mach_o_segment_command_64, nsects),
1328               *nsects);
1329       /* flags left as zero.  */
1330 #endif
1331     }
1332
1333   return simple_object_internal_write (descriptor, hdrsize, hdr, seghdrsize,
1334                                        errmsg, err);
1335 }
1336
1337 /* Write out a complete Mach-O file.  */
1338
1339 static const char *
1340 simple_object_mach_o_write_to_file (simple_object_write *sobj, int descriptor,
1341                                     int *err)
1342 {
1343   size_t nsects = 0;
1344   const char *errmsg;
1345
1346   if (!simple_object_mach_o_write_segment (sobj, descriptor, &nsects,
1347                                            &errmsg, err))
1348     return errmsg;
1349
1350   if (!simple_object_mach_o_write_header (sobj, descriptor, nsects,
1351                                           &errmsg, err))
1352     return errmsg;
1353
1354   return NULL;
1355 }
1356
1357 /* Release the private data for an simple_object_write structure.  */
1358
1359 static void
1360 simple_object_mach_o_release_write (void *data)
1361 {
1362   XDELETE (data);
1363 }
1364
1365 /* The Mach-O functions.  */
1366
1367 const struct simple_object_functions simple_object_mach_o_functions =
1368 {
1369   simple_object_mach_o_match,
1370   simple_object_mach_o_find_sections,
1371   simple_object_mach_o_fetch_attributes,
1372   simple_object_mach_o_release_read,
1373   simple_object_mach_o_attributes_merge,
1374   simple_object_mach_o_release_attributes,
1375   simple_object_mach_o_start_write,
1376   simple_object_mach_o_write_to_file,
1377   simple_object_mach_o_release_write,
1378   NULL
1379 };