(root)/
binutils-2.41/
bfd/
simple.c
       1  /* simple.c -- BFD simple client routines
       2     Copyright (C) 2002-2023 Free Software Foundation, Inc.
       3     Contributed by MontaVista Software, Inc.
       4  
       5     This file is part of BFD, the Binary File Descriptor library.
       6  
       7     This program is free software; you can redistribute it and/or modify
       8     it under the terms of the GNU General Public License as published by
       9     the Free Software Foundation; either version 3 of the License, or
      10     (at your option) any later version.
      11  
      12     This program is distributed in the hope that it will be useful,
      13     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15     GNU General Public License for more details.
      16  
      17     You should have received a copy of the GNU General Public License
      18     along with this program; if not, write to the Free Software
      19     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      20     MA 02110-1301, USA.  */
      21  
      22  #include "sysdep.h"
      23  #include "bfd.h"
      24  #include "libbfd.h"
      25  #include "bfdlink.h"
      26  #include "genlink.h"
      27  
      28  static void
      29  simple_dummy_add_to_set (struct bfd_link_info * info ATTRIBUTE_UNUSED,
      30  			 struct bfd_link_hash_entry *entry ATTRIBUTE_UNUSED,
      31  			 bfd_reloc_code_real_type reloc ATTRIBUTE_UNUSED,
      32  			 bfd *abfd ATTRIBUTE_UNUSED,
      33  			 asection *sec ATTRIBUTE_UNUSED,
      34  			 bfd_vma value ATTRIBUTE_UNUSED)
      35  {
      36  }
      37  
      38  static  void
      39  simple_dummy_constructor (struct bfd_link_info * info ATTRIBUTE_UNUSED,
      40  			  bool constructor ATTRIBUTE_UNUSED,
      41  			  const char *name ATTRIBUTE_UNUSED,
      42  			  bfd *abfd ATTRIBUTE_UNUSED,
      43  			  asection *sec ATTRIBUTE_UNUSED,
      44  			  bfd_vma value ATTRIBUTE_UNUSED)
      45  {
      46  }
      47  
      48  static void
      49  simple_dummy_multiple_common (struct bfd_link_info * info ATTRIBUTE_UNUSED,
      50  			      struct bfd_link_hash_entry * entry ATTRIBUTE_UNUSED,
      51  			      bfd * abfd ATTRIBUTE_UNUSED,
      52  			      enum bfd_link_hash_type type ATTRIBUTE_UNUSED,
      53  			      bfd_vma size ATTRIBUTE_UNUSED)
      54  {
      55  }
      56  
      57  static void
      58  simple_dummy_warning (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
      59  		      const char *warning ATTRIBUTE_UNUSED,
      60  		      const char *symbol ATTRIBUTE_UNUSED,
      61  		      bfd *abfd ATTRIBUTE_UNUSED,
      62  		      asection *section ATTRIBUTE_UNUSED,
      63  		      bfd_vma address ATTRIBUTE_UNUSED)
      64  {
      65  }
      66  
      67  static void
      68  simple_dummy_undefined_symbol (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
      69  			       const char *name ATTRIBUTE_UNUSED,
      70  			       bfd *abfd ATTRIBUTE_UNUSED,
      71  			       asection *section ATTRIBUTE_UNUSED,
      72  			       bfd_vma address ATTRIBUTE_UNUSED,
      73  			       bool fatal ATTRIBUTE_UNUSED)
      74  {
      75  }
      76  
      77  static void
      78  simple_dummy_reloc_overflow (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
      79  			     struct bfd_link_hash_entry *entry ATTRIBUTE_UNUSED,
      80  			     const char *name ATTRIBUTE_UNUSED,
      81  			     const char *reloc_name ATTRIBUTE_UNUSED,
      82  			     bfd_vma addend ATTRIBUTE_UNUSED,
      83  			     bfd *abfd ATTRIBUTE_UNUSED,
      84  			     asection *section ATTRIBUTE_UNUSED,
      85  			     bfd_vma address ATTRIBUTE_UNUSED)
      86  {
      87  }
      88  
      89  static void
      90  simple_dummy_reloc_dangerous (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
      91  			      const char *message ATTRIBUTE_UNUSED,
      92  			      bfd *abfd ATTRIBUTE_UNUSED,
      93  			      asection *section ATTRIBUTE_UNUSED,
      94  			      bfd_vma address ATTRIBUTE_UNUSED)
      95  {
      96  }
      97  
      98  static void
      99  simple_dummy_unattached_reloc (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
     100  			       const char *name ATTRIBUTE_UNUSED,
     101  			       bfd *abfd ATTRIBUTE_UNUSED,
     102  			       asection *section ATTRIBUTE_UNUSED,
     103  			       bfd_vma address ATTRIBUTE_UNUSED)
     104  {
     105  }
     106  
     107  static void
     108  simple_dummy_multiple_definition (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
     109  				  struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED,
     110  				  bfd *nbfd ATTRIBUTE_UNUSED,
     111  				  asection *nsec ATTRIBUTE_UNUSED,
     112  				  bfd_vma nval ATTRIBUTE_UNUSED)
     113  {
     114  }
     115  
     116  static void
     117  simple_dummy_einfo (const char *fmt ATTRIBUTE_UNUSED, ...)
     118  {
     119  }
     120  
     121  struct saved_output_info
     122  {
     123    bfd_vma offset;
     124    asection *section;
     125  };
     126  
     127  struct saved_offsets
     128  {
     129    unsigned int section_count;
     130    struct saved_output_info *sections;
     131  };
     132  
     133  /* The sections in ABFD may already have output sections and offsets
     134     set if we are here during linking.
     135  
     136     DWARF-2 specifies offsets into debug sections in many cases and
     137     bfd_simple_get_relocated_section_contents is called to relocate
     138     debug info for a single relocatable object file.  So we want
     139     offsets relative to that object file's sections, not offsets in the
     140     output file.  For that reason, reset a debug section->output_offset
     141     to zero.
     142  
     143     If not called during linking then set section->output_section to
     144     point back to the input section, because output_section must not be
     145     NULL when calling the relocation routines.
     146  
     147     Save the original output offset and section to restore later.  */
     148  
     149  static void
     150  simple_save_output_info (bfd *abfd ATTRIBUTE_UNUSED,
     151  			 asection *section,
     152  			 void *ptr)
     153  {
     154    struct saved_offsets *saved_offsets = (struct saved_offsets *) ptr;
     155    struct saved_output_info *output_info;
     156  
     157    output_info = &saved_offsets->sections[section->index];
     158    output_info->offset = section->output_offset;
     159    output_info->section = section->output_section;
     160    if ((section->flags & SEC_DEBUGGING) != 0
     161        || section->output_section == NULL)
     162      {
     163        section->output_offset = 0;
     164        section->output_section = section;
     165      }
     166  }
     167  
     168  static void
     169  simple_restore_output_info (bfd *abfd ATTRIBUTE_UNUSED,
     170  			    asection *section,
     171  			    void *ptr)
     172  {
     173    struct saved_offsets *saved_offsets = (struct saved_offsets *) ptr;
     174    struct saved_output_info *output_info;
     175  
     176    if (section->index >= saved_offsets->section_count)
     177      return;
     178  
     179    output_info = &saved_offsets->sections[section->index];
     180    section->output_offset = output_info->offset;
     181    section->output_section = output_info->section;
     182  }
     183  
     184  /*
     185  FUNCTION
     186  	bfd_simple_relocate_secton
     187  
     188  SYNOPSIS
     189  	bfd_byte *bfd_simple_get_relocated_section_contents
     190  	  (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
     191  
     192  DESCRIPTION
     193  	Returns the relocated contents of section @var{sec}.  The symbols in
     194  	@var{symbol_table} will be used, or the symbols from @var{abfd} if
     195  	@var{symbol_table} is NULL.  The output offsets for debug sections will
     196  	be temporarily reset to 0.  The result will be stored at @var{outbuf}
     197  	or allocated with @code{bfd_malloc} if @var{outbuf} is @code{NULL}.
     198  
     199  	Returns @code{NULL} on a fatal error; ignores errors applying
     200  	particular relocations.
     201  */
     202  
     203  bfd_byte *
     204  bfd_simple_get_relocated_section_contents (bfd *abfd,
     205  					   asection *sec,
     206  					   bfd_byte *outbuf,
     207  					   asymbol **symbol_table)
     208  {
     209    struct bfd_link_info link_info;
     210    struct bfd_link_order link_order;
     211    struct bfd_link_callbacks callbacks;
     212    bfd_byte *contents;
     213    struct saved_offsets saved_offsets;
     214    bfd *link_next;
     215  
     216    /* Don't apply relocation on executable and shared library.  See
     217       PR 4756.  */
     218    if ((abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC)) != HAS_RELOC
     219        || ! (sec->flags & SEC_RELOC))
     220      {
     221        if (!bfd_get_full_section_contents (abfd, sec, &outbuf))
     222  	return NULL;
     223        return outbuf;
     224      }
     225  
     226    /* In order to use bfd_get_relocated_section_contents, we need
     227       to forge some data structures that it expects.  */
     228  
     229    /* Fill in the bare minimum number of fields for our purposes.  */
     230    memset (&link_info, 0, sizeof (link_info));
     231    link_info.output_bfd = abfd;
     232    link_info.input_bfds = abfd;
     233    link_info.input_bfds_tail = &abfd->link.next;
     234  
     235    link_next = abfd->link.next;
     236    abfd->link.next = NULL;
     237    link_info.hash = _bfd_generic_link_hash_table_create (abfd);
     238    link_info.callbacks = &callbacks;
     239    /* Make sure that any fields not initialised below do not
     240       result in a potential indirection via a random address.  */
     241    memset (&callbacks, 0, sizeof callbacks);
     242    callbacks.warning = simple_dummy_warning;
     243    callbacks.undefined_symbol = simple_dummy_undefined_symbol;
     244    callbacks.reloc_overflow = simple_dummy_reloc_overflow;
     245    callbacks.reloc_dangerous = simple_dummy_reloc_dangerous;
     246    callbacks.unattached_reloc = simple_dummy_unattached_reloc;
     247    callbacks.multiple_definition = simple_dummy_multiple_definition;
     248    callbacks.einfo = simple_dummy_einfo;
     249    callbacks.multiple_common = simple_dummy_multiple_common;
     250    callbacks.constructor = simple_dummy_constructor;
     251    callbacks.add_to_set = simple_dummy_add_to_set;
     252  
     253    memset (&link_order, 0, sizeof (link_order));
     254    link_order.next = NULL;
     255    link_order.type = bfd_indirect_link_order;
     256    link_order.offset = 0;
     257    link_order.size = sec->size;
     258    link_order.u.indirect.section = sec;
     259  
     260    contents = NULL;
     261  
     262    saved_offsets.section_count = abfd->section_count;
     263    saved_offsets.sections = malloc (sizeof (*saved_offsets.sections)
     264  				   * saved_offsets.section_count);
     265    if (saved_offsets.sections == NULL)
     266      goto out1;
     267    bfd_map_over_sections (abfd, simple_save_output_info, &saved_offsets);
     268  
     269    if (symbol_table == NULL)
     270      {
     271        if (!bfd_generic_link_read_symbols (abfd))
     272  	goto out2;
     273        symbol_table = _bfd_generic_link_get_symbols (abfd);
     274      }
     275  
     276    contents = bfd_get_relocated_section_contents (abfd,
     277  						 &link_info,
     278  						 &link_order,
     279  						 outbuf,
     280  						 false,
     281  						 symbol_table);
     282   out2:
     283    bfd_map_over_sections (abfd, simple_restore_output_info, &saved_offsets);
     284    free (saved_offsets.sections);
     285   out1:
     286    _bfd_generic_link_hash_table_free (abfd);
     287    abfd->link.next = link_next;
     288    return contents;
     289  }