(root)/
gcc-13.2.0/
libiberty/
simple-object.c
       1  /* simple-object.c -- simple routines to read and write object files.
       2     Copyright (C) 2010-2023 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  }