Home | History | Annotate | Download | only in libiberty
      1 /* simple-object-mach-o.c -- routines to manipulate Mach-O object files.
      2    Copyright 2010, 2011, 2013 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 };
   1379