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