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