Home | History | Annotate | Line # | Download | only in libiberty
simple-object.c revision 1.1.1.3
      1      1.1  christos /* simple-object.c -- simple routines to read and write object files.
      2      1.1  christos    Copyright 2010 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  christos 
     26      1.1  christos #ifdef HAVE_STDLIB_H
     27      1.1  christos #include <stdlib.h>
     28      1.1  christos #endif
     29      1.1  christos 
     30      1.1  christos #ifdef HAVE_STDINT_H
     31      1.1  christos #include <stdint.h>
     32      1.1  christos #endif
     33      1.1  christos 
     34      1.1  christos #ifdef HAVE_STRING_H
     35      1.1  christos #include <string.h>
     36      1.1  christos #endif
     37      1.1  christos 
     38      1.1  christos #ifdef HAVE_INTTYPES_H
     39      1.1  christos #include <inttypes.h>
     40      1.1  christos #endif
     41      1.1  christos 
     42      1.1  christos #ifndef SEEK_SET
     43      1.1  christos #define SEEK_SET 0
     44      1.1  christos #endif
     45      1.1  christos 
     46      1.1  christos #include "simple-object-common.h"
     47      1.1  christos 
     48      1.1  christos /* The known object file formats.  */
     49      1.1  christos 
     50      1.1  christos static const struct simple_object_functions * const format_functions[] =
     51      1.1  christos {
     52      1.1  christos   &simple_object_elf_functions,
     53      1.1  christos   &simple_object_mach_o_functions,
     54  1.1.1.3  christos   &simple_object_coff_functions,
     55  1.1.1.3  christos   &simple_object_xcoff_functions
     56      1.1  christos };
     57      1.1  christos 
     58      1.1  christos /* Read data from a file using the simple_object error reporting
     59      1.1  christos    conventions.  */
     60      1.1  christos 
     61      1.1  christos int
     62      1.1  christos simple_object_internal_read (int descriptor, off_t offset,
     63      1.1  christos 			     unsigned char *buffer, size_t size,
     64      1.1  christos 			     const char **errmsg, int *err)
     65      1.1  christos {
     66      1.1  christos   if (lseek (descriptor, offset, SEEK_SET) < 0)
     67      1.1  christos     {
     68      1.1  christos       *errmsg = "lseek";
     69      1.1  christos       *err = errno;
     70      1.1  christos       return 0;
     71      1.1  christos     }
     72      1.1  christos 
     73  1.1.1.3  christos   do
     74      1.1  christos     {
     75  1.1.1.3  christos       ssize_t got = read (descriptor, buffer, size);
     76  1.1.1.3  christos       if (got == 0)
     77  1.1.1.3  christos 	break;
     78  1.1.1.3  christos       else if (got > 0)
     79  1.1.1.3  christos 	{
     80  1.1.1.3  christos 	  buffer += got;
     81  1.1.1.3  christos 	  size -= got;
     82  1.1.1.3  christos 	}
     83  1.1.1.3  christos       else if (errno != EINTR)
     84  1.1.1.3  christos 	{
     85  1.1.1.3  christos 	  *errmsg = "read";
     86  1.1.1.3  christos 	  *err = errno;
     87  1.1.1.3  christos 	  return 0;
     88  1.1.1.3  christos 	}
     89      1.1  christos     }
     90  1.1.1.3  christos   while (size > 0);
     91      1.1  christos 
     92  1.1.1.3  christos   if (size > 0)
     93      1.1  christos     {
     94      1.1  christos       *errmsg = "file too short";
     95      1.1  christos       *err = 0;
     96      1.1  christos       return 0;
     97      1.1  christos     }
     98      1.1  christos 
     99      1.1  christos   return 1;
    100      1.1  christos }
    101      1.1  christos 
    102      1.1  christos /* Write data to a file using the simple_object error reporting
    103      1.1  christos    conventions.  */
    104      1.1  christos 
    105      1.1  christos int
    106      1.1  christos simple_object_internal_write (int descriptor, off_t offset,
    107      1.1  christos 			      const unsigned char *buffer, size_t size,
    108      1.1  christos 			      const char **errmsg, int *err)
    109      1.1  christos {
    110      1.1  christos   if (lseek (descriptor, offset, SEEK_SET) < 0)
    111      1.1  christos     {
    112      1.1  christos       *errmsg = "lseek";
    113      1.1  christos       *err = errno;
    114      1.1  christos       return 0;
    115      1.1  christos     }
    116      1.1  christos 
    117  1.1.1.3  christos   do
    118      1.1  christos     {
    119  1.1.1.3  christos       ssize_t wrote = write (descriptor, buffer, size);
    120  1.1.1.3  christos       if (wrote == 0)
    121  1.1.1.3  christos 	break;
    122  1.1.1.3  christos       else if (wrote > 0)
    123  1.1.1.3  christos 	{
    124  1.1.1.3  christos 	  buffer += wrote;
    125  1.1.1.3  christos 	  size -= wrote;
    126  1.1.1.3  christos 	}
    127  1.1.1.3  christos       else if (errno != EINTR)
    128  1.1.1.3  christos 	{
    129  1.1.1.3  christos 	  *errmsg = "write";
    130  1.1.1.3  christos 	  *err = errno;
    131  1.1.1.3  christos 	  return 0;
    132  1.1.1.3  christos 	}
    133      1.1  christos     }
    134  1.1.1.3  christos   while (size > 0);
    135      1.1  christos 
    136  1.1.1.3  christos   if (size > 0)
    137      1.1  christos     {
    138      1.1  christos       *errmsg = "short write";
    139      1.1  christos       *err = 0;
    140      1.1  christos       return 0;
    141      1.1  christos     }
    142      1.1  christos 
    143      1.1  christos   return 1;
    144      1.1  christos }
    145      1.1  christos 
    146      1.1  christos /* Open for read.  */
    147      1.1  christos 
    148      1.1  christos simple_object_read *
    149      1.1  christos simple_object_start_read (int descriptor, off_t offset,
    150      1.1  christos 			  const char *segment_name, const char **errmsg,
    151      1.1  christos 			  int *err)
    152      1.1  christos {
    153      1.1  christos   unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN];
    154      1.1  christos   size_t len, i;
    155      1.1  christos 
    156      1.1  christos   if (!simple_object_internal_read (descriptor, offset, header,
    157      1.1  christos 				    SIMPLE_OBJECT_MATCH_HEADER_LEN,
    158      1.1  christos 				    errmsg, err))
    159      1.1  christos     return NULL;
    160      1.1  christos 
    161      1.1  christos   len = sizeof (format_functions) / sizeof (format_functions[0]);
    162      1.1  christos   for (i = 0; i < len; ++i)
    163      1.1  christos     {
    164      1.1  christos       void *data;
    165      1.1  christos 
    166      1.1  christos       data = format_functions[i]->match (header, descriptor, offset,
    167      1.1  christos 					 segment_name, errmsg, err);
    168      1.1  christos       if (data != NULL)
    169      1.1  christos 	{
    170      1.1  christos 	  simple_object_read *ret;
    171      1.1  christos 
    172      1.1  christos 	  ret = XNEW (simple_object_read);
    173      1.1  christos 	  ret->descriptor = descriptor;
    174      1.1  christos 	  ret->offset = offset;
    175      1.1  christos 	  ret->functions = format_functions[i];
    176      1.1  christos 	  ret->data = data;
    177      1.1  christos 	  return ret;
    178      1.1  christos 	}
    179      1.1  christos     }
    180      1.1  christos 
    181      1.1  christos   *errmsg = "file not recognized";
    182      1.1  christos   *err = 0;
    183      1.1  christos   return NULL;
    184      1.1  christos }
    185      1.1  christos 
    186      1.1  christos /* Find all sections.  */
    187      1.1  christos 
    188      1.1  christos const char *
    189      1.1  christos simple_object_find_sections (simple_object_read *sobj,
    190      1.1  christos 			     int (*pfn) (void *, const char *, off_t, off_t),
    191      1.1  christos 			     void *data,
    192      1.1  christos 			     int *err)
    193      1.1  christos {
    194      1.1  christos   return sobj->functions->find_sections (sobj, pfn, data, err);
    195      1.1  christos }
    196      1.1  christos 
    197      1.1  christos /* Internal data passed to find_one_section.  */
    198      1.1  christos 
    199      1.1  christos struct find_one_section_data
    200      1.1  christos {
    201      1.1  christos   /* The section we are looking for.  */
    202      1.1  christos   const char *name;
    203      1.1  christos   /* Where to store the section offset.  */
    204      1.1  christos   off_t *offset;
    205      1.1  christos   /* Where to store the section length.  */
    206      1.1  christos   off_t *length;
    207      1.1  christos   /* Set if the name is found.  */
    208      1.1  christos   int found;
    209      1.1  christos };
    210      1.1  christos 
    211      1.1  christos /* Internal function passed to find_sections.  */
    212      1.1  christos 
    213      1.1  christos static int
    214      1.1  christos find_one_section (void *data, const char *name, off_t offset, off_t length)
    215      1.1  christos {
    216      1.1  christos   struct find_one_section_data *fosd = (struct find_one_section_data *) data;
    217      1.1  christos 
    218      1.1  christos   if (strcmp (name, fosd->name) != 0)
    219      1.1  christos     return 1;
    220      1.1  christos 
    221      1.1  christos   *fosd->offset = offset;
    222      1.1  christos   *fosd->length = length;
    223      1.1  christos   fosd->found = 1;
    224      1.1  christos 
    225      1.1  christos   /* Stop iteration.  */
    226      1.1  christos   return 0;
    227      1.1  christos }
    228      1.1  christos 
    229      1.1  christos /* Find a section.  */
    230      1.1  christos 
    231      1.1  christos int
    232      1.1  christos simple_object_find_section (simple_object_read *sobj, const char *name,
    233      1.1  christos 			    off_t *offset, off_t *length,
    234      1.1  christos 			    const char **errmsg, int *err)
    235      1.1  christos {
    236      1.1  christos   struct find_one_section_data fosd;
    237      1.1  christos 
    238      1.1  christos   fosd.name = name;
    239      1.1  christos   fosd.offset = offset;
    240      1.1  christos   fosd.length = length;
    241      1.1  christos   fosd.found = 0;
    242      1.1  christos 
    243      1.1  christos   *errmsg = simple_object_find_sections (sobj, find_one_section,
    244      1.1  christos 					 (void *) &fosd, err);
    245      1.1  christos   if (*errmsg != NULL)
    246      1.1  christos     return 0;
    247      1.1  christos   if (!fosd.found)
    248      1.1  christos     return 0;
    249      1.1  christos   return 1;
    250      1.1  christos }
    251      1.1  christos 
    252      1.1  christos /* Fetch attributes.  */
    253      1.1  christos 
    254      1.1  christos simple_object_attributes *
    255      1.1  christos simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg,
    256      1.1  christos 				int *err)
    257      1.1  christos {
    258      1.1  christos   void *data;
    259      1.1  christos   simple_object_attributes *ret;
    260      1.1  christos 
    261      1.1  christos   data = sobj->functions->fetch_attributes (sobj, errmsg, err);
    262      1.1  christos   if (data == NULL)
    263      1.1  christos     return NULL;
    264      1.1  christos   ret = XNEW (simple_object_attributes);
    265      1.1  christos   ret->functions = sobj->functions;
    266      1.1  christos   ret->data = data;
    267      1.1  christos   return ret;
    268      1.1  christos }
    269      1.1  christos 
    270      1.1  christos /* Release an simple_object_read.  */
    271      1.1  christos 
    272      1.1  christos void
    273      1.1  christos simple_object_release_read (simple_object_read *sobj)
    274      1.1  christos {
    275      1.1  christos   sobj->functions->release_read (sobj->data);
    276      1.1  christos   XDELETE (sobj);
    277      1.1  christos }
    278      1.1  christos 
    279  1.1.1.2  christos /* Merge attributes.  */
    280      1.1  christos 
    281      1.1  christos const char *
    282  1.1.1.2  christos simple_object_attributes_merge (simple_object_attributes *to,
    283  1.1.1.2  christos 				simple_object_attributes *from,
    284  1.1.1.2  christos 				int *err)
    285      1.1  christos {
    286  1.1.1.2  christos   if (to->functions != from->functions)
    287      1.1  christos     {
    288      1.1  christos       *err = 0;
    289      1.1  christos       return "different object file format";
    290      1.1  christos     }
    291  1.1.1.2  christos   return to->functions->attributes_merge (to->data, from->data, err);
    292      1.1  christos }
    293      1.1  christos 
    294      1.1  christos /* Release an attributes structure.  */
    295      1.1  christos 
    296      1.1  christos void
    297      1.1  christos simple_object_release_attributes (simple_object_attributes *attrs)
    298      1.1  christos {
    299      1.1  christos   attrs->functions->release_attributes (attrs->data);
    300      1.1  christos   XDELETE (attrs);
    301      1.1  christos }
    302      1.1  christos 
    303      1.1  christos /* Start creating an object file.  */
    304      1.1  christos 
    305      1.1  christos simple_object_write *
    306      1.1  christos simple_object_start_write (simple_object_attributes *attrs,
    307      1.1  christos 			   const char *segment_name, const char **errmsg,
    308      1.1  christos 			   int *err)
    309      1.1  christos {
    310      1.1  christos   void *data;
    311      1.1  christos   simple_object_write *ret;
    312      1.1  christos 
    313      1.1  christos   data = attrs->functions->start_write (attrs->data, errmsg, err);
    314      1.1  christos   if (data == NULL)
    315      1.1  christos     return NULL;
    316      1.1  christos   ret = XNEW (simple_object_write);
    317      1.1  christos   ret->functions = attrs->functions;
    318      1.1  christos   ret->segment_name = xstrdup (segment_name);
    319      1.1  christos   ret->sections = NULL;
    320      1.1  christos   ret->last_section = NULL;
    321      1.1  christos   ret->data = data;
    322      1.1  christos   return ret;
    323      1.1  christos }
    324      1.1  christos 
    325      1.1  christos /* Start creating a section.  */
    326      1.1  christos 
    327      1.1  christos simple_object_write_section *
    328      1.1  christos simple_object_write_create_section (simple_object_write *sobj, const char *name,
    329      1.1  christos 				    unsigned int align,
    330      1.1  christos 				    const char **errmsg ATTRIBUTE_UNUSED,
    331      1.1  christos 				    int *err ATTRIBUTE_UNUSED)
    332      1.1  christos {
    333      1.1  christos   simple_object_write_section *ret;
    334      1.1  christos 
    335      1.1  christos   ret = XNEW (simple_object_write_section);
    336      1.1  christos   ret->next = NULL;
    337      1.1  christos   ret->name = xstrdup (name);
    338      1.1  christos   ret->align = align;
    339      1.1  christos   ret->buffers = NULL;
    340      1.1  christos   ret->last_buffer = NULL;
    341      1.1  christos 
    342      1.1  christos   if (sobj->last_section == NULL)
    343      1.1  christos     {
    344      1.1  christos       sobj->sections = ret;
    345      1.1  christos       sobj->last_section = ret;
    346      1.1  christos     }
    347      1.1  christos   else
    348      1.1  christos     {
    349      1.1  christos       sobj->last_section->next = ret;
    350      1.1  christos       sobj->last_section = ret;
    351      1.1  christos     }
    352      1.1  christos 
    353      1.1  christos   return ret;
    354      1.1  christos }
    355      1.1  christos 
    356      1.1  christos /* Add data to a section.  */
    357      1.1  christos 
    358      1.1  christos const char *
    359      1.1  christos simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED,
    360      1.1  christos 			      simple_object_write_section *section,
    361      1.1  christos 			      const void *buffer,
    362      1.1  christos 			      size_t size, int copy,
    363      1.1  christos 			      int *err ATTRIBUTE_UNUSED)
    364      1.1  christos {
    365      1.1  christos   struct simple_object_write_section_buffer *wsb;
    366      1.1  christos 
    367      1.1  christos   wsb = XNEW (struct simple_object_write_section_buffer);
    368      1.1  christos   wsb->next = NULL;
    369      1.1  christos   wsb->size = size;
    370      1.1  christos 
    371      1.1  christos   if (!copy)
    372      1.1  christos     {
    373      1.1  christos       wsb->buffer = buffer;
    374      1.1  christos       wsb->free_buffer = NULL;
    375      1.1  christos     }
    376      1.1  christos   else
    377      1.1  christos     {
    378      1.1  christos       wsb->free_buffer = (void *) XNEWVEC (char, size);
    379      1.1  christos       memcpy (wsb->free_buffer, buffer, size);
    380      1.1  christos       wsb->buffer = wsb->free_buffer;
    381      1.1  christos     }
    382      1.1  christos 
    383      1.1  christos   if (section->last_buffer == NULL)
    384      1.1  christos     {
    385      1.1  christos       section->buffers = wsb;
    386      1.1  christos       section->last_buffer = wsb;
    387      1.1  christos     }
    388      1.1  christos   else
    389      1.1  christos     {
    390      1.1  christos       section->last_buffer->next = wsb;
    391      1.1  christos       section->last_buffer = wsb;
    392      1.1  christos     }
    393      1.1  christos 
    394      1.1  christos   return NULL;
    395      1.1  christos }
    396      1.1  christos 
    397      1.1  christos /* Write the complete object file.  */
    398      1.1  christos 
    399      1.1  christos const char *
    400      1.1  christos simple_object_write_to_file (simple_object_write *sobj, int descriptor,
    401      1.1  christos 			     int *err)
    402      1.1  christos {
    403      1.1  christos   return sobj->functions->write_to_file (sobj, descriptor, err);
    404      1.1  christos }
    405      1.1  christos 
    406      1.1  christos /* Release an simple_object_write.  */
    407      1.1  christos 
    408      1.1  christos void
    409      1.1  christos simple_object_release_write (simple_object_write *sobj)
    410      1.1  christos {
    411      1.1  christos   simple_object_write_section *section;
    412      1.1  christos 
    413      1.1  christos   free (sobj->segment_name);
    414      1.1  christos 
    415      1.1  christos   section = sobj->sections;
    416      1.1  christos   while (section != NULL)
    417      1.1  christos     {
    418      1.1  christos       struct simple_object_write_section_buffer *buffer;
    419      1.1  christos       simple_object_write_section *next_section;
    420      1.1  christos 
    421      1.1  christos       buffer = section->buffers;
    422      1.1  christos       while (buffer != NULL)
    423      1.1  christos 	{
    424      1.1  christos 	  struct simple_object_write_section_buffer *next_buffer;
    425      1.1  christos 
    426      1.1  christos 	  if (buffer->free_buffer != NULL)
    427      1.1  christos 	    XDELETEVEC (buffer->free_buffer);
    428      1.1  christos 	  next_buffer = buffer->next;
    429      1.1  christos 	  XDELETE (buffer);
    430      1.1  christos 	  buffer = next_buffer;
    431      1.1  christos 	}
    432      1.1  christos 
    433      1.1  christos       next_section = section->next;
    434      1.1  christos       free (section->name);
    435      1.1  christos       XDELETE (section);
    436      1.1  christos       section = next_section;
    437      1.1  christos     }
    438      1.1  christos 
    439      1.1  christos   sobj->functions->release_write (sobj->data);
    440      1.1  christos   XDELETE (sobj);
    441      1.1  christos }
    442