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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [libiberty/] [simple-object-mach-o.c] - Diff between revs 21 and 163

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 21 Rev 163
Line 1... Line 1...
/* simple-object-mach-o.c -- routines to manipulate Mach-O object files.
/* simple-object-mach-o.c -- routines to manipulate Mach-O object files.
   Copyright 2010 Free Software Foundation, Inc.
   Copyright 2010, 2011 Free Software Foundation, Inc.
   Written by Ian Lance Taylor, Google.
   Written by Ian Lance Taylor, Google.
 
 
This program is free software; you can redistribute it and/or modify it
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
Free Software Foundation; either version 2, or (at your option) any
Line 172... Line 172...
 
 
/* A GNU specific extension for long section names.  */
/* A GNU specific extension for long section names.  */
 
 
#define GNU_SECTION_NAMES "__section_names"
#define GNU_SECTION_NAMES "__section_names"
 
 
 
/* A GNU-specific extension to wrap multiple sections using three
 
   mach-o sections within a given segment.  The section '__wrapper_sects'
 
   is subdivided according to the index '__wrapper_index' and each sub
 
   sect is named according to the names supplied in '__wrapper_names'.  */
 
 
 
#define GNU_WRAPPER_SECTS "__wrapper_sects"
 
#define GNU_WRAPPER_INDEX "__wrapper_index"
 
#define GNU_WRAPPER_NAMES "__wrapper_names"
 
 
/* Private data for an simple_object_read.  */
/* Private data for an simple_object_read.  */
 
 
struct simple_object_mach_o_read
struct simple_object_mach_o_read
{
{
  /* User specified segment name.  */
  /* User specified segment name.  */
Line 212... Line 221...
  unsigned int flags;
  unsigned int flags;
  /* Reserved field from header, only used on 64-bit.  */
  /* Reserved field from header, only used on 64-bit.  */
  unsigned int reserved;
  unsigned int reserved;
};
};
 
 
/* See if we have a Mach-O file.  */
/* See if we have a Mach-O MH_OBJECT file:
 
 
 
   A standard MH_OBJECT (from as) will have three load commands:
 
   0 - LC_SEGMENT/LC_SEGMENT64
 
   1 - LC_SYMTAB
 
   2 - LC_DYSYMTAB
 
 
 
   The LC_SEGMENT/LC_SEGMENT64 will introduce a single anonymous segment
 
   containing all the sections.
 
 
 
   Files written by simple-object will have only the segment command
 
   (no symbol tables).  */
 
 
static void *
static void *
simple_object_mach_o_match (
simple_object_mach_o_match (
    unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
    unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
    int descriptor,
    int descriptor,
Line 354... Line 374...
      *size = fetch_64 (sechdr
      *size = fetch_64 (sechdr
                        + offsetof (struct mach_o_section_64, size));
                        + offsetof (struct mach_o_section_64, size));
    }
    }
}
}
 
 
/* Handle a segment in a Mach-O file.  Return 1 if we should continue,
/* Handle a segment in a Mach-O Object file.
   0 if the caller should return.  */
 
 
   This will callback to the function pfn for each "section found" the meaning
 
   of which depends on gnu extensions to mach-o:
 
 
 
   If we find mach-o sections (with the segment name as specified) which also
 
   contain: a 'sects' wrapper, an index, and a  name table, we expand this into
 
   as many sections as are specified in the index.  In this case, there will
 
   be a callback for each of these.
 
 
 
   We will also allow an extension that permits long names (more than 16
 
   characters) to be used with mach-o.  In this case, the section name has
 
   a specific format embedding an index into a name table, and the file must
 
   contain such name table.
 
 
 
   Return 1 if we should continue, 0 if the caller should return.  */
 
 
 
#define SOMO_SECTS_PRESENT 0x01
 
#define SOMO_INDEX_PRESENT 0x02
 
#define SOMO_NAMES_PRESENT 0x04
 
#define SOMO_LONGN_PRESENT 0x08
 
#define SOMO_WRAPPING (SOMO_SECTS_PRESENT | SOMO_INDEX_PRESENT \
 
                       | SOMO_NAMES_PRESENT)
 
 
static int
static int
simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
                              const unsigned char *segbuf,
                              const unsigned char *segbuf,
                              int (*pfn) (void *, const char *, off_t offset,
                              int (*pfn) (void *, const char *, off_t offset,
Line 376... Line 417...
  size_t segname_offset;
  size_t segname_offset;
  size_t sectname_offset;
  size_t sectname_offset;
  unsigned int nsects;
  unsigned int nsects;
  unsigned char *secdata;
  unsigned char *secdata;
  unsigned int i;
  unsigned int i;
 
  unsigned int gnu_sections_found;
  unsigned int strtab_index;
  unsigned int strtab_index;
 
  unsigned int index_index;
 
  unsigned int nametab_index;
 
  unsigned int sections_index;
  char *strtab;
  char *strtab;
 
  char *nametab;
 
  unsigned char *index;
  size_t strtab_size;
  size_t strtab_size;
 
  size_t nametab_size;
 
  size_t index_size;
 
  unsigned int n_wrapped_sects;
 
  size_t wrapper_sect_size;
 
  off_t wrapper_sect_offset;
 
 
  fetch_32 = (omr->is_big_endian
  fetch_32 = (omr->is_big_endian
              ? simple_object_fetch_big_32
              ? simple_object_fetch_big_32
              : simple_object_fetch_little_32);
              : simple_object_fetch_little_32);
 
 
Line 407... Line 459...
      nsects = (*fetch_32) (segbuf
      nsects = (*fetch_32) (segbuf
                            + offsetof (struct mach_o_segment_command_64,
                            + offsetof (struct mach_o_segment_command_64,
                                        nsects));
                                        nsects));
    }
    }
 
 
 
  /* Fetch the section headers from the segment command.  */
 
 
  secdata = XNEWVEC (unsigned char, nsects * sechdrsize);
  secdata = XNEWVEC (unsigned char, nsects * sechdrsize);
  if (!simple_object_internal_read (sobj->descriptor, offset + seghdrsize,
  if (!simple_object_internal_read (sobj->descriptor, offset + seghdrsize,
                                    secdata, nsects * sechdrsize, errmsg, err))
                                    secdata, nsects * sechdrsize, errmsg, err))
    {
    {
      XDELETEVEC (secdata);
      XDELETEVEC (secdata);
      return 0;
      return 0;
    }
    }
 
 
  /* Scan for a __section_names section.  This is in effect a GNU
  /* Scan for special sections that signal GNU extensions to the format.  */
     extension that permits section names longer than 16 chars.  */
 
 
 
 
  gnu_sections_found = 0;
 
  index_index = nsects;
 
  sections_index = nsects;
 
  strtab_index = nsects;
 
  nametab_index = nsects;
  for (i = 0; i < nsects; ++i)
  for (i = 0; i < nsects; ++i)
    {
    {
      size_t nameoff;
      size_t nameoff;
 
 
      nameoff = i * sechdrsize + segname_offset;
      nameoff = i * sechdrsize + segname_offset;
      if (strcmp ((char *) secdata + nameoff, omr->segment_name) != 0)
      if (strcmp ((char *) secdata + nameoff, omr->segment_name) != 0)
        continue;
        continue;
 
 
      nameoff = i * sechdrsize + sectname_offset;
      nameoff = i * sechdrsize + sectname_offset;
      if (strcmp ((char *) secdata + nameoff, GNU_SECTION_NAMES) == 0)
      if (strcmp ((char *) secdata + nameoff, GNU_WRAPPER_NAMES) == 0)
        break;
        {
 
          nametab_index = i;
 
          gnu_sections_found |= SOMO_NAMES_PRESENT;
    }
    }
 
      else if (strcmp ((char *) secdata + nameoff, GNU_WRAPPER_INDEX) == 0)
 
        {
 
          index_index = i;
 
          gnu_sections_found |= SOMO_INDEX_PRESENT;
 
        }
 
      else if (strcmp ((char *) secdata + nameoff, GNU_WRAPPER_SECTS) == 0)
 
        {
 
          sections_index = i;
 
          gnu_sections_found |= SOMO_SECTS_PRESENT;
 
        }
 
      else if (strcmp ((char *) secdata + nameoff, GNU_SECTION_NAMES) == 0)
 
        {
  strtab_index = i;
  strtab_index = i;
  if (strtab_index >= nsects)
          gnu_sections_found |= SOMO_LONGN_PRESENT;
 
        }
 
    }
 
 
 
  /* If any of the special wrapper section components is present, then
 
     they all should be.  */
 
 
 
  if ((gnu_sections_found & SOMO_WRAPPING) != 0)
    {
    {
      strtab = NULL;
      off_t nametab_offset;
      strtab_size = 0;
      off_t index_offset;
 
 
 
      if ((gnu_sections_found & SOMO_WRAPPING) != SOMO_WRAPPING)
 
        {
 
          *errmsg = "GNU Mach-o section wrapper: required section missing";
 
          *err = 0; /* No useful errno.  */
 
          XDELETEVEC (secdata);
 
          return 0;
 
        }
 
 
 
      /* Fetch the name table.  */
 
 
 
      simple_object_mach_o_section_info (omr->is_big_endian, is_32,
 
                                         secdata + nametab_index * sechdrsize,
 
                                         &nametab_offset, &nametab_size);
 
      nametab = XNEWVEC (char, nametab_size);
 
      if (!simple_object_internal_read (sobj->descriptor,
 
                                        sobj->offset + nametab_offset,
 
                                        (unsigned char *) nametab, nametab_size,
 
                                        errmsg, err))
 
        {
 
          XDELETEVEC (nametab);
 
          XDELETEVEC (secdata);
 
          return 0;
 
        }
 
 
 
      /* Fetch the index.  */
 
 
 
      simple_object_mach_o_section_info (omr->is_big_endian, is_32,
 
                                         secdata + index_index * sechdrsize,
 
                                         &index_offset, &index_size);
 
      index = XNEWVEC (unsigned char, index_size);
 
      if (!simple_object_internal_read (sobj->descriptor,
 
                                        sobj->offset + index_offset,
 
                                        index, index_size,
 
                                        errmsg, err))
 
        {
 
          XDELETEVEC (index);
 
          XDELETEVEC (nametab);
 
          XDELETEVEC (secdata);
 
          return 0;
 
        }
 
 
 
      /* The index contains 4 unsigned ints per sub-section:
 
         sub-section offset/length, sub-section name/length.
 
         We fix this for both 32 and 64 bit mach-o for now, since
 
         other fields limit the maximum size of an object to 4G.  */
 
      n_wrapped_sects = index_size / 16;
 
 
 
      /* Get the parameters for the wrapper too.  */
 
      simple_object_mach_o_section_info (omr->is_big_endian, is_32,
 
                                         secdata + sections_index * sechdrsize,
 
                                         &wrapper_sect_offset,
 
                                         &wrapper_sect_size);
    }
    }
  else
  else
    {
    {
 
      index = NULL;
 
      index_size = 0;
 
      nametab = NULL;
 
      nametab_size = 0;
 
      n_wrapped_sects = 0;
 
    }
 
 
 
  /* If we have a long names section, fetch it.  */
 
 
 
  if ((gnu_sections_found & SOMO_LONGN_PRESENT) != 0)
 
    {
      off_t strtab_offset;
      off_t strtab_offset;
 
 
      simple_object_mach_o_section_info (omr->is_big_endian, is_32,
      simple_object_mach_o_section_info (omr->is_big_endian, is_32,
                                         secdata + strtab_index * sechdrsize,
                                         secdata + strtab_index * sechdrsize,
                                         &strtab_offset, &strtab_size);
                                         &strtab_offset, &strtab_size);
Line 450... Line 593...
                                        sobj->offset + strtab_offset,
                                        sobj->offset + strtab_offset,
                                        (unsigned char *) strtab, strtab_size,
                                        (unsigned char *) strtab, strtab_size,
                                        errmsg, err))
                                        errmsg, err))
        {
        {
          XDELETEVEC (strtab);
          XDELETEVEC (strtab);
 
          XDELETEVEC (index);
 
          XDELETEVEC (nametab);
          XDELETEVEC (secdata);
          XDELETEVEC (secdata);
          return 0;
          return 0;
        }
        }
    }
    }
 
  else
 
    {
 
      strtab = NULL;
 
      strtab_size = 0;
 
      strtab_index = nsects;
 
    }
 
 
  /* Process the sections.  */
  /* Process the sections.  */
 
 
  for (i = 0; i < nsects; ++i)
  for (i = 0; i < nsects; ++i)
    {
    {
      const unsigned char *sechdr;
      const unsigned char *sechdr;
      char namebuf[MACH_O_NAME_LEN + 1];
      char namebuf[MACH_O_NAME_LEN * 2 + 2];
      char *name;
      char *name;
      off_t secoffset;
      off_t secoffset;
      size_t secsize;
      size_t secsize;
 
      int l;
 
 
 
      sechdr = secdata + i * sechdrsize;
 
 
 
      /* We've already processed the long section names.  */
 
 
      if (i == strtab_index)
      if ((gnu_sections_found & SOMO_LONGN_PRESENT) != 0
 
          && i == strtab_index)
        continue;
        continue;
 
 
      sechdr = secdata + i * sechdrsize;
      /* We only act on the segment named.  */
 
 
      if (strcmp ((char *) sechdr + segname_offset, omr->segment_name) != 0)
      if (strcmp ((char *) sechdr + segname_offset, omr->segment_name) != 0)
        continue;
        continue;
 
 
 
      /* Process sections associated with the wrapper.  */
 
 
 
      if ((gnu_sections_found & SOMO_WRAPPING) != 0)
 
        {
 
          if (i == nametab_index || i == index_index)
 
            continue;
 
 
 
          if (i == sections_index)
 
            {
 
              unsigned int j;
 
              for (j = 0; j < n_wrapped_sects; ++j)
 
                {
 
                  unsigned int subsect_offset, subsect_length, name_offset;
 
                  subsect_offset = (*fetch_32) (index + 16 * j);
 
                  subsect_length = (*fetch_32) (index + 16 * j + 4);
 
                  name_offset = (*fetch_32) (index + 16 * j + 8);
 
                  /* We don't need the name_length yet.  */
 
 
 
                  secoffset = wrapper_sect_offset + subsect_offset;
 
                  secsize = subsect_length;
 
                  name = nametab + name_offset;
 
 
 
                  if (!(*pfn) (data, name, secoffset, secsize))
 
                    {
 
                      *errmsg = NULL;
 
                      *err = 0;
 
                      XDELETEVEC (index);
 
                      XDELETEVEC (nametab);
 
                      XDELETEVEC (strtab);
 
                      XDELETEVEC (secdata);
 
                      return 0;
 
                    }
 
                }
 
              continue;
 
            }
 
        }
 
 
 
      if ((gnu_sections_found & SOMO_LONGN_PRESENT) != 0)
 
        {
      memcpy (namebuf, sechdr + sectname_offset, MACH_O_NAME_LEN);
      memcpy (namebuf, sechdr + sectname_offset, MACH_O_NAME_LEN);
      namebuf[MACH_O_NAME_LEN] = '\0';
      namebuf[MACH_O_NAME_LEN] = '\0';
 
 
      name = &namebuf[0];
      name = &namebuf[0];
      if (strtab != NULL && name[0] == '_' && name[1] == '_')
      if (strtab != NULL && name[0] == '_' && name[1] == '_')
Line 487... Line 683...
            {
            {
              if (stringoffset >= strtab_size)
              if (stringoffset >= strtab_size)
                {
                {
                  *errmsg = "section name offset out of range";
                  *errmsg = "section name offset out of range";
                  *err = 0;
                  *err = 0;
 
                      XDELETEVEC (index);
 
                      XDELETEVEC (nametab);
                  XDELETEVEC (strtab);
                  XDELETEVEC (strtab);
                  XDELETEVEC (secdata);
                  XDELETEVEC (secdata);
                  return 0;
                  return 0;
                }
                }
 
 
              name = strtab + stringoffset;
              name = strtab + stringoffset;
            }
            }
        }
        }
 
        }
 
      else
 
        {
 
           /* Otherwise, make a name like __segment,__section as per the
 
              convention in mach-o asm.  */
 
          name = &namebuf[0];
 
          memset (namebuf, 0, MACH_O_NAME_LEN * 2 + 2);
 
          memcpy (namebuf, (char *) sechdr + segname_offset, MACH_O_NAME_LEN);
 
          l = strlen (namebuf);
 
          namebuf[l] = ',';
 
          memcpy (namebuf + l + 1, (char *) sechdr + sectname_offset,
 
                  MACH_O_NAME_LEN);
 
        }
 
 
      simple_object_mach_o_section_info (omr->is_big_endian, is_32, sechdr,
      simple_object_mach_o_section_info (omr->is_big_endian, is_32, sechdr,
                                         &secoffset, &secsize);
                                         &secoffset, &secsize);
 
 
      if (!(*pfn) (data, name, secoffset, secsize))
      if (!(*pfn) (data, name, secoffset, secsize))
        {
        {
          *errmsg = NULL;
          *errmsg = NULL;
          *err = 0;
          *err = 0;
 
          XDELETEVEC (index);
 
          XDELETEVEC (nametab);
          XDELETEVEC (strtab);
          XDELETEVEC (strtab);
          XDELETEVEC (secdata);
          XDELETEVEC (secdata);
          return 0;
          return 0;
        }
        }
    }
    }
 
 
 
  XDELETEVEC (index);
 
  XDELETEVEC (nametab);
  XDELETEVEC (strtab);
  XDELETEVEC (strtab);
  XDELETEVEC (secdata);
  XDELETEVEC (secdata);
 
 
  return 1;
  return 1;
}
}
Line 722... Line 937...
 
 
static int
static int
simple_object_mach_o_write_section_header (simple_object_write *sobj,
simple_object_mach_o_write_section_header (simple_object_write *sobj,
                                           int descriptor,
                                           int descriptor,
                                           size_t sechdr_offset,
                                           size_t sechdr_offset,
                                           const char *name, size_t secaddr,
                                           const char *name, const char *segn,
                                           size_t secsize, size_t offset,
                                           size_t secaddr, size_t secsize,
                                           unsigned int align,
                                           size_t offset, unsigned int align,
                                           const char **errmsg, int *err)
                                           const char **errmsg, int *err)
{
{
  struct simple_object_mach_o_attributes *attrs =
  struct simple_object_mach_o_attributes *attrs =
    (struct simple_object_mach_o_attributes *) sobj->data;
    (struct simple_object_mach_o_attributes *) sobj->data;
  void (*set_32) (unsigned char *, unsigned int);
  void (*set_32) (unsigned char *, unsigned int);
Line 746... Line 961...
  if (attrs->magic == MACH_O_MH_MAGIC)
  if (attrs->magic == MACH_O_MH_MAGIC)
    {
    {
      strncpy ((char *) hdr + offsetof (struct mach_o_section_32, sectname),
      strncpy ((char *) hdr + offsetof (struct mach_o_section_32, sectname),
               name, MACH_O_NAME_LEN);
               name, MACH_O_NAME_LEN);
      strncpy ((char *) hdr + offsetof (struct mach_o_section_32, segname),
      strncpy ((char *) hdr + offsetof (struct mach_o_section_32, segname),
               sobj->segment_name, MACH_O_NAME_LEN);
               segn, MACH_O_NAME_LEN);
      set_32 (hdr + offsetof (struct mach_o_section_32, addr), secaddr);
      set_32 (hdr + offsetof (struct mach_o_section_32, addr), secaddr);
      set_32 (hdr + offsetof (struct mach_o_section_32, size), secsize);
      set_32 (hdr + offsetof (struct mach_o_section_32, size), secsize);
      set_32 (hdr + offsetof (struct mach_o_section_32, offset), offset);
      set_32 (hdr + offsetof (struct mach_o_section_32, offset), offset);
      set_32 (hdr + offsetof (struct mach_o_section_32, align), align);
      set_32 (hdr + offsetof (struct mach_o_section_32, align), align);
      /* reloff left as zero.  */
      /* reloff left as zero.  */
Line 771... Line 986...
                : simple_object_set_little_64);
                : simple_object_set_little_64);
 
 
      strncpy ((char *) hdr + offsetof (struct mach_o_section_64, sectname),
      strncpy ((char *) hdr + offsetof (struct mach_o_section_64, sectname),
               name, MACH_O_NAME_LEN);
               name, MACH_O_NAME_LEN);
      strncpy ((char *) hdr + offsetof (struct mach_o_section_64, segname),
      strncpy ((char *) hdr + offsetof (struct mach_o_section_64, segname),
               sobj->segment_name, MACH_O_NAME_LEN);
               segn, MACH_O_NAME_LEN);
      set_64 (hdr + offsetof (struct mach_o_section_64, addr), secaddr);
      set_64 (hdr + offsetof (struct mach_o_section_64, addr), secaddr);
      set_64 (hdr + offsetof (struct mach_o_section_64, size), secsize);
      set_64 (hdr + offsetof (struct mach_o_section_64, size), secsize);
      set_32 (hdr + offsetof (struct mach_o_section_64, offset), offset);
      set_32 (hdr + offsetof (struct mach_o_section_64, offset), offset);
      set_32 (hdr + offsetof (struct mach_o_section_64, align), align);
      set_32 (hdr + offsetof (struct mach_o_section_64, align), align);
      /* reloff left as zero.  */
      /* reloff left as zero.  */
Line 791... Line 1006...
 
 
  return simple_object_internal_write (descriptor, sechdr_offset, hdr,
  return simple_object_internal_write (descriptor, sechdr_offset, hdr,
                                       sechdrsize, errmsg, err);
                                       sechdrsize, errmsg, err);
}
}
 
 
/* Write out the single segment and the sections of a Mach-O file.  */
/* Write out the single (anonymous) segment containing the sections of a Mach-O
 
   Object file.
 
 
 
   As a GNU extension to mach-o, when the caller specifies a segment name in
 
   sobj->segment_name, all the sections passed will be output under a single
 
   mach-o section header.  The caller's sections are indexed within this
 
   'wrapper' section by a table stored in a second mach-o section.  Finally,
 
   arbitrary length section names are permitted by the extension and these are
 
   stored in a table in a third mach-o section.
 
 
 
   Note that this is only likely to make any sense for the __GNU_LTO segment
 
   at present.
 
 
 
   If the wrapper extension is not in force, we assume that the section name
 
   is in the form __SEGMENT_NAME,__section_name as per Mach-O asm.  */
 
 
static int
static int
simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
                                    size_t nsects, const char **errmsg,
                                    size_t *nsects, const char **errmsg,
                                    int *err)
                                    int *err)
{
{
  struct simple_object_mach_o_attributes *attrs =
  struct simple_object_mach_o_attributes *attrs =
    (struct simple_object_mach_o_attributes *) sobj->data;
    (struct simple_object_mach_o_attributes *) sobj->data;
  void (*set_32) (unsigned char *, unsigned int);
  void (*set_32) (unsigned char *, unsigned int);
Line 812... Line 1041...
  size_t secaddr;
  size_t secaddr;
  unsigned int name_offset;
  unsigned int name_offset;
  simple_object_write_section *section;
  simple_object_write_section *section;
  unsigned char hdrbuf[sizeof (struct mach_o_segment_command_64)];
  unsigned char hdrbuf[sizeof (struct mach_o_segment_command_64)];
  unsigned char *hdr;
  unsigned char *hdr;
 
  size_t nsects_in;
 
  unsigned int *index;
 
  char *snames;
 
  unsigned int sect;
 
 
  set_32 = (attrs->is_big_endian
  set_32 = (attrs->is_big_endian
            ? simple_object_set_big_32
            ? simple_object_set_big_32
            : simple_object_set_little_32);
            : simple_object_set_little_32);
 
 
Line 832... Line 1065...
      hdrsize = sizeof (struct mach_o_header_64);
      hdrsize = sizeof (struct mach_o_header_64);
      seghdrsize = sizeof (struct mach_o_segment_command_64);
      seghdrsize = sizeof (struct mach_o_segment_command_64);
      sechdrsize = sizeof (struct mach_o_section_64);
      sechdrsize = sizeof (struct mach_o_section_64);
    }
    }
 
 
 
  name_offset = 0;
 
  *nsects = nsects_in = 0;
 
 
 
  /* Count the number of sections we start with.  */
 
 
 
  for (section = sobj->sections; section != NULL; section = section->next)
 
    nsects_in++;
 
 
 
  if (sobj->segment_name != NULL)
 
    {
 
      /* We will only write 3 sections: wrapped data, index and names.  */
 
 
 
      *nsects = 3;
 
 
 
      /* The index has four entries per wrapped section:
 
           Section Offset, length,  Name offset, length.
 
         Where the offsets are based at the start of the wrapper and name
 
         sections respectively.
 
         The values are stored as 32 bit int for both 32 and 64 bit mach-o
 
         since the size of a mach-o MH_OBJECT cannot exceed 4G owing to
 
         other constraints.  */
 
 
 
      index = XNEWVEC (unsigned int, nsects_in * 4);
 
 
 
      /* We now need to figure out the size of the names section.  This just
 
         stores the names as null-terminated c strings, packed without any
 
         alignment padding.  */
 
 
 
      for (section = sobj->sections, sect = 0; section != NULL;
 
           section = section->next, sect++)
 
        {
 
          index[sect*4+2] = name_offset;
 
          index[sect*4+3] = strlen (section->name) + 1;
 
          name_offset += strlen (section->name) + 1;
 
        }
 
      snames = XNEWVEC (char, name_offset);
 
    }
 
  else
 
    {
 
      *nsects = nsects_in;
 
      index = NULL;
 
      snames = NULL;
 
    }
 
 
  sechdr_offset = hdrsize + seghdrsize;
  sechdr_offset = hdrsize + seghdrsize;
  cmdsize = seghdrsize + nsects * sechdrsize;
  cmdsize = seghdrsize + *nsects * sechdrsize;
  offset = hdrsize + cmdsize;
  offset = hdrsize + cmdsize;
  name_offset = 0;
 
  secaddr = 0;
  secaddr = 0;
 
 
  for (section = sobj->sections; section != NULL; section = section->next)
  for (section = sobj->sections, sect = 0;
 
       section != NULL; section = section->next, sect++)
    {
    {
      size_t mask;
      size_t mask;
      size_t new_offset;
      size_t new_offset;
      size_t secsize;
      size_t secsize;
      struct simple_object_write_section_buffer *buffer;
      struct simple_object_write_section_buffer *buffer;
      char namebuf[MACH_O_NAME_LEN + 1];
 
 
 
      mask = (1U << section->align) - 1;
      mask = (1U << section->align) - 1;
      new_offset = offset + mask;
      new_offset = offset + mask;
      new_offset &= ~ mask;
      new_offset &= ~ mask;
      while (new_offset > offset)
      while (new_offset > offset)
Line 875... Line 1151...
                                             buffer->size, errmsg, err))
                                             buffer->size, errmsg, err))
            return 0;
            return 0;
          secsize += buffer->size;
          secsize += buffer->size;
        }
        }
 
 
      snprintf (namebuf, sizeof namebuf, "__%08X", name_offset);
      if (sobj->segment_name != NULL)
 
        {
 
          index[sect*4+0] = (unsigned int) offset;
 
          index[sect*4+1] = secsize;
 
          /* Stash the section name in our table.  */
 
          memcpy (snames + index[sect * 4 + 2], section->name,
 
                  index[sect * 4 + 3]);
 
        }
 
      else
 
        {
 
          char namebuf[MACH_O_NAME_LEN + 1];
 
          char segnbuf[MACH_O_NAME_LEN + 1];
 
          char *comma;
 
 
 
          /* Try to extract segment,section from the input name.  */
 
 
 
          memset (namebuf, 0, sizeof namebuf);
 
          memset (segnbuf, 0, sizeof segnbuf);
 
          comma = strchr (section->name, ',');
 
          if (comma != NULL)
 
            {
 
              int len = comma - section->name;
 
              len = len > MACH_O_NAME_LEN ? MACH_O_NAME_LEN : len;
 
              strncpy (namebuf, section->name, len);
 
              strncpy (segnbuf, comma + 1, MACH_O_NAME_LEN);
 
            }
 
          else /* just try to copy the name, leave segment blank.  */
 
            strncpy (namebuf, section->name, MACH_O_NAME_LEN);
 
 
      if (!simple_object_mach_o_write_section_header (sobj, descriptor,
      if (!simple_object_mach_o_write_section_header (sobj, descriptor,
                                                      sechdr_offset, namebuf,
                                                          sechdr_offset,
                                                      secaddr, secsize, offset,
                                                          namebuf, segnbuf,
 
                                                          secaddr, secsize,
 
                                                          offset,
                                                      section->align,
                                                      section->align,
                                                      errmsg, err))
                                                      errmsg, err))
        return 0;
        return 0;
 
 
      sechdr_offset += sechdrsize;
      sechdr_offset += sechdrsize;
 
        }
 
 
      offset += secsize;
      offset += secsize;
      name_offset += strlen (section->name) + 1;
 
      secaddr += secsize;
      secaddr += secsize;
    }
    }
 
 
  /* Write out the section names.  */
  if (sobj->segment_name != NULL)
 
    {
 
      size_t secsize;
 
      unsigned int i;
 
 
 
      /* Write the section header for the wrapper.  */
 
      /* Account for any initial aligment - which becomes the alignment for this
 
         created section.  */
 
 
 
      secsize = (offset - index[0]);
  if (!simple_object_mach_o_write_section_header (sobj, descriptor,
  if (!simple_object_mach_o_write_section_header (sobj, descriptor,
                                                  sechdr_offset,
                                                  sechdr_offset,
                                                  GNU_SECTION_NAMES, secaddr,
                                                      GNU_WRAPPER_SECTS,
                                                  name_offset, offset, 0,
                                                      sobj->segment_name,
 
                                                      0 /*secaddr*/,
 
                                                      secsize, index[0],
 
                                                      sobj->sections->align,
                                                  errmsg, err))
                                                  errmsg, err))
    return 0;
    return 0;
 
 
  for (section = sobj->sections; section != NULL; section = section->next)
      /* Subtract the wrapper section start from the begining of each sub
    {
         section.  */
      size_t namelen;
 
 
 
      namelen = strlen (section->name) + 1;
      for (i = 1; i < nsects_in; ++i)
 
        index[4 * i] -= index[0];
 
      index[0] = 0;
 
 
 
      sechdr_offset += sechdrsize;
 
 
 
      /* Write out the section names.
 
         ... the header ...
 
         name_offset contains the length of the section.  It is not aligned.  */
 
 
 
      if (!simple_object_mach_o_write_section_header (sobj, descriptor,
 
                                                      sechdr_offset,
 
                                                      GNU_WRAPPER_NAMES,
 
                                                      sobj->segment_name,
 
                                                      0 /*secaddr*/,
 
                                                      name_offset,
 
                                                      offset,
 
                                                      0, errmsg, err))
 
        return 0;
 
 
 
      /* ... and the content.. */
      if (!simple_object_internal_write (descriptor, offset,
      if (!simple_object_internal_write (descriptor, offset,
                                         (const unsigned char *) section->name,
                                         (const unsigned char *) snames,
                                         namelen, errmsg, err))
                                         name_offset, errmsg, err))
 
        return 0;
 
 
 
      sechdr_offset += sechdrsize;
 
      secaddr += name_offset;
 
      offset += name_offset;
 
 
 
      /* Now do the index, we'll align this to 4 bytes although the read code
 
         will handle unaligned.  */
 
 
 
      offset += 3;
 
      offset &= ~0x03;
 
      if (!simple_object_mach_o_write_section_header (sobj, descriptor,
 
                                                      sechdr_offset,
 
                                                      GNU_WRAPPER_INDEX,
 
                                                      sobj->segment_name,
 
                                                      0 /*secaddr*/,
 
                                                      nsects_in * 16,
 
                                                      offset,
 
                                                      2, errmsg, err))
        return 0;
        return 0;
      offset += namelen;
 
 
      /* ... and the content.. */
 
      if (!simple_object_internal_write (descriptor, offset,
 
                                         (const unsigned char *) index,
 
                                         nsects_in*16, errmsg, err))
 
        return 0;
 
 
 
      XDELETEVEC (index);
 
      XDELETEVEC (snames);
    }
    }
 
 
  /* Write out the segment header.  */
  /* Write out the segment header.  */
 
 
  memset (hdrbuf, 0, sizeof hdrbuf);
  memset (hdrbuf, 0, sizeof hdrbuf);
Line 921... Line 1284...
    {
    {
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmd),
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmd),
              MACH_O_LC_SEGMENT);
              MACH_O_LC_SEGMENT);
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmdsize),
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmdsize),
              cmdsize);
              cmdsize);
      strncpy (((char *) hdr
     /* MH_OBJECTS have a single, anonymous, segment - so the segment name
                + offsetof (struct mach_o_segment_command_32, segname)),
         is left empty.  */
               sobj->segment_name, MACH_O_NAME_LEN);
 
      /* vmaddr left as zero.  */
      /* vmaddr left as zero.  */
      /* vmsize left as zero.  */
      /* vmsize left as zero.  */
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, fileoff),
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, fileoff),
              hdrsize + cmdsize);
              hdrsize + cmdsize);
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, filesize),
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, filesize),
              offset - (hdrsize + cmdsize));
              offset - (hdrsize + cmdsize));
      /* maxprot left as zero.  */
      /* maxprot left as zero.  */
      /* initprot left as zero.  */
      /* initprot left as zero.  */
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, nsects),
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, nsects),
              nsects);
              *nsects);
      /* flags left as zero.  */
      /* flags left as zero.  */
    }
    }
  else
  else
    {
    {
#ifdef UNSIGNED_64BIT_TYPE
#ifdef UNSIGNED_64BIT_TYPE
Line 949... Line 1311...
 
 
      set_32 (hdr + offsetof (struct mach_o_segment_command_64, cmd),
      set_32 (hdr + offsetof (struct mach_o_segment_command_64, cmd),
              MACH_O_LC_SEGMENT);
              MACH_O_LC_SEGMENT);
      set_32 (hdr + offsetof (struct mach_o_segment_command_64, cmdsize),
      set_32 (hdr + offsetof (struct mach_o_segment_command_64, cmdsize),
              cmdsize);
              cmdsize);
      strncpy (((char *) hdr
      /* MH_OBJECTS have a single, anonymous, segment - so the segment name
                + offsetof (struct mach_o_segment_command_64, segname)),
         is left empty.  */
               sobj->segment_name, MACH_O_NAME_LEN);
 
      /* vmaddr left as zero.  */
      /* vmaddr left as zero.  */
      /* vmsize left as zero.  */
      /* vmsize left as zero.  */
      set_64 (hdr + offsetof (struct mach_o_segment_command_64, fileoff),
      set_64 (hdr + offsetof (struct mach_o_segment_command_64, fileoff),
              hdrsize + cmdsize);
              hdrsize + cmdsize);
      set_64 (hdr + offsetof (struct mach_o_segment_command_64, filesize),
      set_64 (hdr + offsetof (struct mach_o_segment_command_64, filesize),
              offset - (hdrsize + cmdsize));
              offset - (hdrsize + cmdsize));
      /* maxprot left as zero.  */
      /* maxprot left as zero.  */
      /* initprot left as zero.  */
      /* initprot left as zero.  */
      set_32 (hdr + offsetof (struct mach_o_segment_command_64, nsects),
      set_32 (hdr + offsetof (struct mach_o_segment_command_64, nsects),
              nsects);
              *nsects);
      /* flags left as zero.  */
      /* flags left as zero.  */
#endif
#endif
    }
    }
 
 
  return simple_object_internal_write (descriptor, hdrsize, hdr, seghdrsize,
  return simple_object_internal_write (descriptor, hdrsize, hdr, seghdrsize,
Line 976... Line 1337...
 
 
static const char *
static const char *
simple_object_mach_o_write_to_file (simple_object_write *sobj, int descriptor,
simple_object_mach_o_write_to_file (simple_object_write *sobj, int descriptor,
                                    int *err)
                                    int *err)
{
{
  size_t nsects;
  size_t nsects = 0;
  simple_object_write_section *section;
 
  const char *errmsg;
  const char *errmsg;
 
 
  /* Start at 1 for symbol_names section.  */
  if (!simple_object_mach_o_write_segment (sobj, descriptor, &nsects,
  nsects = 1;
 
  for (section = sobj->sections; section != NULL; section = section->next)
 
    ++nsects;
 
 
 
  if (!simple_object_mach_o_write_header (sobj, descriptor, nsects,
 
                                          &errmsg, err))
                                          &errmsg, err))
    return errmsg;
    return errmsg;
 
 
  if (!simple_object_mach_o_write_segment (sobj, descriptor, nsects,
  if (!simple_object_mach_o_write_header (sobj, descriptor, nsects,
                                           &errmsg, err))
                                           &errmsg, err))
    return errmsg;
    return errmsg;
 
 
  return NULL;
  return NULL;
}
}

powered by: WebSVN 2.1.0

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