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