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