Home | History | Annotate | Line # | Download | only in libiberty
simple-object.c revision 1.1.1.5
      1      1.1  christos /* simple-object.c -- simple routines to read and write object files.
      2  1.1.1.4  christos    Copyright (C) 2010-2018 Free Software Foundation, Inc.
      3      1.1  christos    Written by Ian Lance Taylor, Google.
      4      1.1  christos 
      5      1.1  christos This program is free software; you can redistribute it and/or modify it
      6      1.1  christos under the terms of the GNU General Public License as published by the
      7      1.1  christos Free Software Foundation; either version 2, or (at your option) any
      8      1.1  christos later version.
      9      1.1  christos 
     10      1.1  christos This program is distributed in the hope that it will be useful,
     11      1.1  christos but WITHOUT ANY WARRANTY; without even the implied warranty of
     12      1.1  christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13      1.1  christos GNU General Public License for more details.
     14      1.1  christos 
     15      1.1  christos You should have received a copy of the GNU General Public License
     16      1.1  christos along with this program; if not, write to the Free Software
     17      1.1  christos Foundation, 51 Franklin Street - Fifth Floor,
     18      1.1  christos Boston, MA 02110-1301, USA.  */
     19      1.1  christos 
     20      1.1  christos #include "config.h"
     21      1.1  christos #include "libiberty.h"
     22      1.1  christos #include "simple-object.h"
     23      1.1  christos 
     24      1.1  christos #include <errno.h>
     25  1.1.1.4  christos #include <fcntl.h>
     26      1.1  christos 
     27      1.1  christos #ifdef HAVE_STDLIB_H
     28      1.1  christos #include <stdlib.h>
     29      1.1  christos #endif
     30      1.1  christos 
     31      1.1  christos #ifdef HAVE_STDINT_H
     32      1.1  christos #include <stdint.h>
     33      1.1  christos #endif
     34      1.1  christos 
     35      1.1  christos #ifdef HAVE_STRING_H
     36      1.1  christos #include <string.h>
     37      1.1  christos #endif
     38      1.1  christos 
     39      1.1  christos #ifdef HAVE_INTTYPES_H
     40      1.1  christos #include <inttypes.h>
     41      1.1  christos #endif
     42      1.1  christos 
     43      1.1  christos #ifndef SEEK_SET
     44      1.1  christos #define SEEK_SET 0
     45      1.1  christos #endif
     46      1.1  christos 
     47      1.1  christos #include "simple-object-common.h"
     48      1.1  christos 
     49      1.1  christos /* The known object file formats.  */
     50      1.1  christos 
     51      1.1  christos static const struct simple_object_functions * const format_functions[] =
     52      1.1  christos {
     53      1.1  christos   &simple_object_elf_functions,
     54      1.1  christos   &simple_object_mach_o_functions,
     55  1.1.1.3  christos   &simple_object_coff_functions,
     56  1.1.1.3  christos   &simple_object_xcoff_functions
     57      1.1  christos };
     58      1.1  christos 
     59      1.1  christos /* Read data from a file using the simple_object error reporting
     60      1.1  christos    conventions.  */
     61      1.1  christos 
     62      1.1  christos int
     63      1.1  christos simple_object_internal_read (int descriptor, off_t offset,
     64      1.1  christos 			     unsigned char *buffer, size_t size,
     65      1.1  christos 			     const char **errmsg, int *err)
     66      1.1  christos {
     67      1.1  christos   if (lseek (descriptor, offset, SEEK_SET) < 0)
     68      1.1  christos     {
     69      1.1  christos       *errmsg = "lseek";
     70      1.1  christos       *err = errno;
     71      1.1  christos       return 0;
     72      1.1  christos     }
     73      1.1  christos 
     74  1.1.1.3  christos   do
     75      1.1  christos     {
     76  1.1.1.3  christos       ssize_t got = read (descriptor, buffer, size);
     77  1.1.1.3  christos       if (got == 0)
     78  1.1.1.3  christos 	break;
     79  1.1.1.3  christos       else if (got > 0)
     80  1.1.1.3  christos 	{
     81  1.1.1.3  christos 	  buffer += got;
     82  1.1.1.3  christos 	  size -= got;
     83  1.1.1.3  christos 	}
     84  1.1.1.3  christos       else if (errno != EINTR)
     85  1.1.1.3  christos 	{
     86  1.1.1.3  christos 	  *errmsg = "read";
     87  1.1.1.3  christos 	  *err = errno;
     88  1.1.1.3  christos 	  return 0;
     89  1.1.1.3  christos 	}
     90      1.1  christos     }
     91  1.1.1.3  christos   while (size > 0);
     92      1.1  christos 
     93  1.1.1.3  christos   if (size > 0)
     94      1.1  christos     {
     95      1.1  christos       *errmsg = "file too short";
     96      1.1  christos       *err = 0;
     97      1.1  christos       return 0;
     98      1.1  christos     }
     99      1.1  christos 
    100      1.1  christos   return 1;
    101      1.1  christos }
    102      1.1  christos 
    103      1.1  christos /* Write data to a file using the simple_object error reporting
    104      1.1  christos    conventions.  */
    105      1.1  christos 
    106      1.1  christos int
    107      1.1  christos simple_object_internal_write (int descriptor, off_t offset,
    108      1.1  christos 			      const unsigned char *buffer, size_t size,
    109      1.1  christos 			      const char **errmsg, int *err)
    110      1.1  christos {
    111      1.1  christos   if (lseek (descriptor, offset, SEEK_SET) < 0)
    112      1.1  christos     {
    113      1.1  christos       *errmsg = "lseek";
    114      1.1  christos       *err = errno;
    115      1.1  christos       return 0;
    116      1.1  christos     }
    117      1.1  christos 
    118  1.1.1.3  christos   do
    119      1.1  christos     {
    120  1.1.1.3  christos       ssize_t wrote = write (descriptor, buffer, size);
    121  1.1.1.3  christos       if (wrote == 0)
    122  1.1.1.3  christos 	break;
    123  1.1.1.3  christos       else if (wrote > 0)
    124  1.1.1.3  christos 	{
    125  1.1.1.3  christos 	  buffer += wrote;
    126  1.1.1.3  christos 	  size -= wrote;
    127  1.1.1.3  christos 	}
    128  1.1.1.3  christos       else if (errno != EINTR)
    129  1.1.1.3  christos 	{
    130  1.1.1.3  christos 	  *errmsg = "write";
    131  1.1.1.3  christos 	  *err = errno;
    132  1.1.1.3  christos 	  return 0;
    133  1.1.1.3  christos 	}
    134      1.1  christos     }
    135  1.1.1.3  christos   while (size > 0);
    136      1.1  christos 
    137  1.1.1.3  christos   if (size > 0)
    138      1.1  christos     {
    139      1.1  christos       *errmsg = "short write";
    140      1.1  christos       *err = 0;
    141      1.1  christos       return 0;
    142      1.1  christos     }
    143      1.1  christos 
    144      1.1  christos   return 1;
    145      1.1  christos }
    146      1.1  christos 
    147      1.1  christos /* Open for read.  */
    148      1.1  christos 
    149      1.1  christos simple_object_read *
    150      1.1  christos simple_object_start_read (int descriptor, off_t offset,
    151      1.1  christos 			  const char *segment_name, const char **errmsg,
    152      1.1  christos 			  int *err)
    153      1.1  christos {
    154      1.1  christos   unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN];
    155      1.1  christos   size_t len, i;
    156      1.1  christos 
    157      1.1  christos   if (!simple_object_internal_read (descriptor, offset, header,
    158      1.1  christos 				    SIMPLE_OBJECT_MATCH_HEADER_LEN,
    159      1.1  christos 				    errmsg, err))
    160      1.1  christos     return NULL;
    161      1.1  christos 
    162      1.1  christos   len = sizeof (format_functions) / sizeof (format_functions[0]);
    163      1.1  christos   for (i = 0; i < len; ++i)
    164      1.1  christos     {
    165      1.1  christos       void *data;
    166      1.1  christos 
    167      1.1  christos       data = format_functions[i]->match (header, descriptor, offset,
    168      1.1  christos 					 segment_name, errmsg, err);
    169      1.1  christos       if (data != NULL)
    170      1.1  christos 	{
    171      1.1  christos 	  simple_object_read *ret;
    172      1.1  christos 
    173      1.1  christos 	  ret = XNEW (simple_object_read);
    174      1.1  christos 	  ret->descriptor = descriptor;
    175      1.1  christos 	  ret->offset = offset;
    176      1.1  christos 	  ret->functions = format_functions[i];
    177      1.1  christos 	  ret->data = data;
    178      1.1  christos 	  return ret;
    179      1.1  christos 	}
    180      1.1  christos     }
    181      1.1  christos 
    182      1.1  christos   *errmsg = "file not recognized";
    183      1.1  christos   *err = 0;
    184      1.1  christos   return NULL;
    185      1.1  christos }
    186      1.1  christos 
    187      1.1  christos /* Find all sections.  */
    188      1.1  christos 
    189      1.1  christos const char *
    190      1.1  christos simple_object_find_sections (simple_object_read *sobj,
    191      1.1  christos 			     int (*pfn) (void *, const char *, off_t, off_t),
    192      1.1  christos 			     void *data,
    193      1.1  christos 			     int *err)
    194      1.1  christos {
    195      1.1  christos   return sobj->functions->find_sections (sobj, pfn, data, err);
    196      1.1  christos }
    197      1.1  christos 
    198      1.1  christos /* Internal data passed to find_one_section.  */
    199      1.1  christos 
    200      1.1  christos struct find_one_section_data
    201      1.1  christos {
    202      1.1  christos   /* The section we are looking for.  */
    203      1.1  christos   const char *name;
    204      1.1  christos   /* Where to store the section offset.  */
    205      1.1  christos   off_t *offset;
    206      1.1  christos   /* Where to store the section length.  */
    207      1.1  christos   off_t *length;
    208      1.1  christos   /* Set if the name is found.  */
    209      1.1  christos   int found;
    210      1.1  christos };
    211      1.1  christos 
    212      1.1  christos /* Internal function passed to find_sections.  */
    213      1.1  christos 
    214      1.1  christos static int
    215      1.1  christos find_one_section (void *data, const char *name, off_t offset, off_t length)
    216      1.1  christos {
    217      1.1  christos   struct find_one_section_data *fosd = (struct find_one_section_data *) data;
    218      1.1  christos 
    219      1.1  christos   if (strcmp (name, fosd->name) != 0)
    220      1.1  christos     return 1;
    221      1.1  christos 
    222      1.1  christos   *fosd->offset = offset;
    223      1.1  christos   *fosd->length = length;
    224      1.1  christos   fosd->found = 1;
    225      1.1  christos 
    226      1.1  christos   /* Stop iteration.  */
    227      1.1  christos   return 0;
    228      1.1  christos }
    229      1.1  christos 
    230      1.1  christos /* Find a section.  */
    231      1.1  christos 
    232      1.1  christos int
    233      1.1  christos simple_object_find_section (simple_object_read *sobj, const char *name,
    234      1.1  christos 			    off_t *offset, off_t *length,
    235      1.1  christos 			    const char **errmsg, int *err)
    236      1.1  christos {
    237      1.1  christos   struct find_one_section_data fosd;
    238      1.1  christos 
    239      1.1  christos   fosd.name = name;
    240      1.1  christos   fosd.offset = offset;
    241      1.1  christos   fosd.length = length;
    242      1.1  christos   fosd.found = 0;
    243      1.1  christos 
    244      1.1  christos   *errmsg = simple_object_find_sections (sobj, find_one_section,
    245      1.1  christos 					 (void *) &fosd, err);
    246      1.1  christos   if (*errmsg != NULL)
    247      1.1  christos     return 0;
    248      1.1  christos   if (!fosd.found)
    249      1.1  christos     return 0;
    250      1.1  christos   return 1;
    251      1.1  christos }
    252      1.1  christos 
    253  1.1.1.4  christos /* Callback to identify and rename LTO debug sections by name.
    254  1.1.1.5  christos    Returns non-NULL if NAME is a LTO debug section, NULL if not.
    255  1.1.1.5  christos    If RENAME is true it will rename LTO debug sections to non-LTO
    256  1.1.1.5  christos    ones.  */
    257  1.1.1.4  christos 
    258  1.1.1.5  christos static char *
    259  1.1.1.5  christos handle_lto_debug_sections (const char *name, int rename)
    260  1.1.1.4  christos {
    261  1.1.1.5  christos   char *newname = rename ? XCNEWVEC (char, strlen (name) + 1)
    262  1.1.1.5  christos 	  	         : xstrdup (name);
    263  1.1.1.5  christos 
    264  1.1.1.4  christos   /* ???  So we can't use .gnu.lto_ prefixed sections as the assembler
    265  1.1.1.4  christos      complains about bogus section flags.  Which means we need to arrange
    266  1.1.1.4  christos      for that to be fixed or .gnu.debuglto_ marked as SHF_EXCLUDE (to make
    267  1.1.1.4  christos      fat lto object tooling work for the fat part).  */
    268  1.1.1.5  christos   /* Also include corresponding reloc sections.  */
    269  1.1.1.5  christos   if (strncmp (name, ".rela", sizeof (".rela") - 1) == 0)
    270  1.1.1.5  christos     {
    271  1.1.1.5  christos       if (rename)
    272  1.1.1.5  christos         strncpy (newname, name, sizeof (".rela") - 1);
    273  1.1.1.5  christos       name += sizeof (".rela") - 1;
    274  1.1.1.5  christos     }
    275  1.1.1.5  christos   else if (strncmp (name, ".rel", sizeof (".rel") - 1) == 0)
    276  1.1.1.5  christos     {
    277  1.1.1.5  christos       if (rename)
    278  1.1.1.5  christos         strncpy (newname, name, sizeof (".rel") - 1);
    279  1.1.1.5  christos       name += sizeof (".rel") - 1;
    280  1.1.1.5  christos     }
    281  1.1.1.4  christos   /* ???  For now this handles both .gnu.lto_ and .gnu.debuglto_ prefixed
    282  1.1.1.4  christos      sections.  */
    283  1.1.1.4  christos   /* Copy LTO debug sections and rename them to their non-LTO name.  */
    284  1.1.1.5  christos   if (strncmp (name, ".gnu.debuglto_", sizeof (".gnu.debuglto_") - 1) == 0)
    285  1.1.1.5  christos     return rename ? strcat (newname, name + sizeof (".gnu.debuglto_") - 1) : newname;
    286  1.1.1.5  christos   else if (strncmp (name, ".gnu.lto_.debug_",
    287  1.1.1.5  christos 		    sizeof (".gnu.lto_.debug_") -1) == 0)
    288  1.1.1.5  christos     return rename ? strcat (newname, name + sizeof (".gnu.lto_") - 1) : newname;
    289  1.1.1.4  christos   /* Copy over .note.GNU-stack section under the same name if present.  */
    290  1.1.1.5  christos   else if (strcmp (name, ".note.GNU-stack") == 0)
    291  1.1.1.5  christos     return strcpy (newname, name);
    292  1.1.1.5  christos   /* Copy over .comment section under the same name if present.  Solaris
    293  1.1.1.5  christos      ld uses them to relax its checking of ELF gABI access rules for
    294  1.1.1.5  christos      COMDAT sections in objects produced by GCC.  */
    295  1.1.1.5  christos   else if (strcmp (name, ".comment") == 0)
    296  1.1.1.5  christos     return strcpy (newname, name);
    297  1.1.1.5  christos   free (newname);
    298  1.1.1.5  christos   return NULL;
    299  1.1.1.5  christos }
    300  1.1.1.5  christos 
    301  1.1.1.5  christos /* Wrapper for handle_lto_debug_sections.  */
    302  1.1.1.5  christos 
    303  1.1.1.5  christos static char *
    304  1.1.1.5  christos handle_lto_debug_sections_rename (const char *name)
    305  1.1.1.5  christos {
    306  1.1.1.5  christos   return handle_lto_debug_sections (name, 1);
    307  1.1.1.5  christos }
    308  1.1.1.5  christos 
    309  1.1.1.5  christos /* Wrapper for handle_lto_debug_sections.  */
    310  1.1.1.5  christos 
    311  1.1.1.5  christos static char *
    312  1.1.1.5  christos handle_lto_debug_sections_norename (const char *name)
    313  1.1.1.5  christos {
    314  1.1.1.5  christos   return handle_lto_debug_sections (name, 0);
    315  1.1.1.4  christos }
    316  1.1.1.4  christos 
    317  1.1.1.4  christos /* Copy LTO debug sections.  */
    318  1.1.1.4  christos 
    319  1.1.1.4  christos const char *
    320  1.1.1.4  christos simple_object_copy_lto_debug_sections (simple_object_read *sobj,
    321  1.1.1.5  christos 				       const char *dest, int *err, int rename)
    322  1.1.1.4  christos {
    323  1.1.1.4  christos   const char *errmsg;
    324  1.1.1.4  christos   simple_object_write *dest_sobj;
    325  1.1.1.4  christos   simple_object_attributes *attrs;
    326  1.1.1.4  christos   int outfd;
    327  1.1.1.4  christos 
    328  1.1.1.4  christos   if (! sobj->functions->copy_lto_debug_sections)
    329  1.1.1.4  christos     {
    330  1.1.1.4  christos       *err = EINVAL;
    331  1.1.1.4  christos       return "simple_object_copy_lto_debug_sections not implemented";
    332  1.1.1.4  christos     }
    333  1.1.1.4  christos 
    334  1.1.1.4  christos   attrs = simple_object_fetch_attributes (sobj, &errmsg, err);
    335  1.1.1.4  christos   if (! attrs)
    336  1.1.1.4  christos     return errmsg;
    337  1.1.1.4  christos   dest_sobj = simple_object_start_write (attrs, NULL, &errmsg, err);
    338  1.1.1.4  christos   simple_object_release_attributes (attrs);
    339  1.1.1.4  christos   if (! dest_sobj)
    340  1.1.1.4  christos     return errmsg;
    341  1.1.1.4  christos 
    342  1.1.1.5  christos   errmsg = sobj->functions->copy_lto_debug_sections
    343  1.1.1.5  christos 	 	 (sobj, dest_sobj,
    344  1.1.1.5  christos 		  rename ? handle_lto_debug_sections_rename
    345  1.1.1.5  christos 			 : handle_lto_debug_sections_norename,  err);
    346  1.1.1.4  christos   if (errmsg)
    347  1.1.1.4  christos     {
    348  1.1.1.4  christos       simple_object_release_write (dest_sobj);
    349  1.1.1.4  christos       return errmsg;
    350  1.1.1.4  christos     }
    351  1.1.1.4  christos 
    352  1.1.1.4  christos   outfd = creat (dest, 00777);
    353  1.1.1.4  christos   if (outfd == -1)
    354  1.1.1.4  christos     {
    355  1.1.1.4  christos       *err = errno;
    356  1.1.1.4  christos       simple_object_release_write (dest_sobj);
    357  1.1.1.4  christos       return "open failed";
    358  1.1.1.4  christos     }
    359  1.1.1.4  christos 
    360  1.1.1.4  christos   errmsg = simple_object_write_to_file (dest_sobj, outfd, err);
    361  1.1.1.4  christos   close (outfd);
    362  1.1.1.4  christos   if (errmsg)
    363  1.1.1.4  christos     {
    364  1.1.1.4  christos       simple_object_release_write (dest_sobj);
    365  1.1.1.4  christos       return errmsg;
    366  1.1.1.4  christos     }
    367  1.1.1.4  christos 
    368  1.1.1.4  christos   simple_object_release_write (dest_sobj);
    369  1.1.1.4  christos   return NULL;
    370  1.1.1.4  christos }
    371  1.1.1.4  christos 
    372      1.1  christos /* Fetch attributes.  */
    373      1.1  christos 
    374      1.1  christos simple_object_attributes *
    375      1.1  christos simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg,
    376      1.1  christos 				int *err)
    377      1.1  christos {
    378      1.1  christos   void *data;
    379      1.1  christos   simple_object_attributes *ret;
    380      1.1  christos 
    381      1.1  christos   data = sobj->functions->fetch_attributes (sobj, errmsg, err);
    382      1.1  christos   if (data == NULL)
    383      1.1  christos     return NULL;
    384      1.1  christos   ret = XNEW (simple_object_attributes);
    385      1.1  christos   ret->functions = sobj->functions;
    386      1.1  christos   ret->data = data;
    387      1.1  christos   return ret;
    388      1.1  christos }
    389      1.1  christos 
    390      1.1  christos /* Release an simple_object_read.  */
    391      1.1  christos 
    392      1.1  christos void
    393      1.1  christos simple_object_release_read (simple_object_read *sobj)
    394      1.1  christos {
    395      1.1  christos   sobj->functions->release_read (sobj->data);
    396      1.1  christos   XDELETE (sobj);
    397      1.1  christos }
    398      1.1  christos 
    399  1.1.1.2  christos /* Merge attributes.  */
    400      1.1  christos 
    401      1.1  christos const char *
    402  1.1.1.2  christos simple_object_attributes_merge (simple_object_attributes *to,
    403  1.1.1.2  christos 				simple_object_attributes *from,
    404  1.1.1.2  christos 				int *err)
    405      1.1  christos {
    406  1.1.1.2  christos   if (to->functions != from->functions)
    407      1.1  christos     {
    408      1.1  christos       *err = 0;
    409      1.1  christos       return "different object file format";
    410      1.1  christos     }
    411  1.1.1.2  christos   return to->functions->attributes_merge (to->data, from->data, err);
    412      1.1  christos }
    413      1.1  christos 
    414      1.1  christos /* Release an attributes structure.  */
    415      1.1  christos 
    416      1.1  christos void
    417      1.1  christos simple_object_release_attributes (simple_object_attributes *attrs)
    418      1.1  christos {
    419      1.1  christos   attrs->functions->release_attributes (attrs->data);
    420      1.1  christos   XDELETE (attrs);
    421      1.1  christos }
    422      1.1  christos 
    423      1.1  christos /* Start creating an object file.  */
    424      1.1  christos 
    425      1.1  christos simple_object_write *
    426      1.1  christos simple_object_start_write (simple_object_attributes *attrs,
    427      1.1  christos 			   const char *segment_name, const char **errmsg,
    428      1.1  christos 			   int *err)
    429      1.1  christos {
    430      1.1  christos   void *data;
    431      1.1  christos   simple_object_write *ret;
    432      1.1  christos 
    433      1.1  christos   data = attrs->functions->start_write (attrs->data, errmsg, err);
    434      1.1  christos   if (data == NULL)
    435      1.1  christos     return NULL;
    436      1.1  christos   ret = XNEW (simple_object_write);
    437      1.1  christos   ret->functions = attrs->functions;
    438  1.1.1.4  christos   ret->segment_name = segment_name ? xstrdup (segment_name) : NULL;
    439      1.1  christos   ret->sections = NULL;
    440      1.1  christos   ret->last_section = NULL;
    441      1.1  christos   ret->data = data;
    442      1.1  christos   return ret;
    443      1.1  christos }
    444      1.1  christos 
    445      1.1  christos /* Start creating a section.  */
    446      1.1  christos 
    447      1.1  christos simple_object_write_section *
    448      1.1  christos simple_object_write_create_section (simple_object_write *sobj, const char *name,
    449      1.1  christos 				    unsigned int align,
    450      1.1  christos 				    const char **errmsg ATTRIBUTE_UNUSED,
    451      1.1  christos 				    int *err ATTRIBUTE_UNUSED)
    452      1.1  christos {
    453      1.1  christos   simple_object_write_section *ret;
    454      1.1  christos 
    455      1.1  christos   ret = XNEW (simple_object_write_section);
    456      1.1  christos   ret->next = NULL;
    457      1.1  christos   ret->name = xstrdup (name);
    458      1.1  christos   ret->align = align;
    459      1.1  christos   ret->buffers = NULL;
    460      1.1  christos   ret->last_buffer = NULL;
    461      1.1  christos 
    462      1.1  christos   if (sobj->last_section == NULL)
    463      1.1  christos     {
    464      1.1  christos       sobj->sections = ret;
    465      1.1  christos       sobj->last_section = ret;
    466      1.1  christos     }
    467      1.1  christos   else
    468      1.1  christos     {
    469      1.1  christos       sobj->last_section->next = ret;
    470      1.1  christos       sobj->last_section = ret;
    471      1.1  christos     }
    472      1.1  christos 
    473      1.1  christos   return ret;
    474      1.1  christos }
    475      1.1  christos 
    476      1.1  christos /* Add data to a section.  */
    477      1.1  christos 
    478      1.1  christos const char *
    479      1.1  christos simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED,
    480      1.1  christos 			      simple_object_write_section *section,
    481      1.1  christos 			      const void *buffer,
    482      1.1  christos 			      size_t size, int copy,
    483      1.1  christos 			      int *err ATTRIBUTE_UNUSED)
    484      1.1  christos {
    485      1.1  christos   struct simple_object_write_section_buffer *wsb;
    486      1.1  christos 
    487      1.1  christos   wsb = XNEW (struct simple_object_write_section_buffer);
    488      1.1  christos   wsb->next = NULL;
    489      1.1  christos   wsb->size = size;
    490      1.1  christos 
    491      1.1  christos   if (!copy)
    492      1.1  christos     {
    493      1.1  christos       wsb->buffer = buffer;
    494      1.1  christos       wsb->free_buffer = NULL;
    495      1.1  christos     }
    496      1.1  christos   else
    497      1.1  christos     {
    498      1.1  christos       wsb->free_buffer = (void *) XNEWVEC (char, size);
    499      1.1  christos       memcpy (wsb->free_buffer, buffer, size);
    500      1.1  christos       wsb->buffer = wsb->free_buffer;
    501      1.1  christos     }
    502      1.1  christos 
    503      1.1  christos   if (section->last_buffer == NULL)
    504      1.1  christos     {
    505      1.1  christos       section->buffers = wsb;
    506      1.1  christos       section->last_buffer = wsb;
    507      1.1  christos     }
    508      1.1  christos   else
    509      1.1  christos     {
    510      1.1  christos       section->last_buffer->next = wsb;
    511      1.1  christos       section->last_buffer = wsb;
    512      1.1  christos     }
    513      1.1  christos 
    514      1.1  christos   return NULL;
    515      1.1  christos }
    516      1.1  christos 
    517      1.1  christos /* Write the complete object file.  */
    518      1.1  christos 
    519      1.1  christos const char *
    520      1.1  christos simple_object_write_to_file (simple_object_write *sobj, int descriptor,
    521      1.1  christos 			     int *err)
    522      1.1  christos {
    523      1.1  christos   return sobj->functions->write_to_file (sobj, descriptor, err);
    524      1.1  christos }
    525      1.1  christos 
    526      1.1  christos /* Release an simple_object_write.  */
    527      1.1  christos 
    528      1.1  christos void
    529      1.1  christos simple_object_release_write (simple_object_write *sobj)
    530      1.1  christos {
    531      1.1  christos   simple_object_write_section *section;
    532      1.1  christos 
    533      1.1  christos   free (sobj->segment_name);
    534      1.1  christos 
    535      1.1  christos   section = sobj->sections;
    536      1.1  christos   while (section != NULL)
    537      1.1  christos     {
    538      1.1  christos       struct simple_object_write_section_buffer *buffer;
    539      1.1  christos       simple_object_write_section *next_section;
    540      1.1  christos 
    541      1.1  christos       buffer = section->buffers;
    542      1.1  christos       while (buffer != NULL)
    543      1.1  christos 	{
    544      1.1  christos 	  struct simple_object_write_section_buffer *next_buffer;
    545      1.1  christos 
    546      1.1  christos 	  if (buffer->free_buffer != NULL)
    547      1.1  christos 	    XDELETEVEC (buffer->free_buffer);
    548      1.1  christos 	  next_buffer = buffer->next;
    549      1.1  christos 	  XDELETE (buffer);
    550      1.1  christos 	  buffer = next_buffer;
    551      1.1  christos 	}
    552      1.1  christos 
    553      1.1  christos       next_section = section->next;
    554      1.1  christos       free (section->name);
    555      1.1  christos       XDELETE (section);
    556      1.1  christos       section = next_section;
    557      1.1  christos     }
    558      1.1  christos 
    559      1.1  christos   sobj->functions->release_write (sobj->data);
    560      1.1  christos   XDELETE (sobj);
    561      1.1  christos }
    562