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