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