Home | History | Annotate | Download | only in bfd
      1 /* simple.c -- BFD simple client routines
      2    Copyright (C) 2002-2014 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 
     27 static bfd_boolean
     28 simple_dummy_warning (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
     29 		      const char *warning ATTRIBUTE_UNUSED,
     30 		      const char *symbol ATTRIBUTE_UNUSED,
     31 		      bfd *abfd ATTRIBUTE_UNUSED,
     32 		      asection *section ATTRIBUTE_UNUSED,
     33 		      bfd_vma address ATTRIBUTE_UNUSED)
     34 {
     35   return TRUE;
     36 }
     37 
     38 static bfd_boolean
     39 simple_dummy_undefined_symbol (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
     40 			       const char *name ATTRIBUTE_UNUSED,
     41 			       bfd *abfd ATTRIBUTE_UNUSED,
     42 			       asection *section ATTRIBUTE_UNUSED,
     43 			       bfd_vma address ATTRIBUTE_UNUSED,
     44 			       bfd_boolean fatal ATTRIBUTE_UNUSED)
     45 {
     46   return TRUE;
     47 }
     48 
     49 static bfd_boolean
     50 simple_dummy_reloc_overflow (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
     51 			     struct bfd_link_hash_entry *entry ATTRIBUTE_UNUSED,
     52 			     const char *name ATTRIBUTE_UNUSED,
     53 			     const char *reloc_name ATTRIBUTE_UNUSED,
     54 			     bfd_vma addend ATTRIBUTE_UNUSED,
     55 			     bfd *abfd ATTRIBUTE_UNUSED,
     56 			     asection *section ATTRIBUTE_UNUSED,
     57 			     bfd_vma address ATTRIBUTE_UNUSED)
     58 {
     59   return TRUE;
     60 }
     61 
     62 static bfd_boolean
     63 simple_dummy_reloc_dangerous (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
     64 			      const char *message ATTRIBUTE_UNUSED,
     65 			      bfd *abfd ATTRIBUTE_UNUSED,
     66 			      asection *section ATTRIBUTE_UNUSED,
     67 			      bfd_vma address ATTRIBUTE_UNUSED)
     68 {
     69   return TRUE;
     70 }
     71 
     72 static bfd_boolean
     73 simple_dummy_unattached_reloc (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
     74 			       const char *name ATTRIBUTE_UNUSED,
     75 			       bfd *abfd ATTRIBUTE_UNUSED,
     76 			       asection *section ATTRIBUTE_UNUSED,
     77 			       bfd_vma address ATTRIBUTE_UNUSED)
     78 {
     79   return TRUE;
     80 }
     81 
     82 static bfd_boolean
     83 simple_dummy_multiple_definition (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
     84 				  struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED,
     85 				  bfd *nbfd ATTRIBUTE_UNUSED,
     86 				  asection *nsec ATTRIBUTE_UNUSED,
     87 				  bfd_vma nval ATTRIBUTE_UNUSED)
     88 {
     89   return TRUE;
     90 }
     91 
     92 static void
     93 simple_dummy_einfo (const char *fmt ATTRIBUTE_UNUSED, ...)
     94 {
     95 }
     96 
     97 struct saved_output_info
     98 {
     99   bfd_vma offset;
    100   asection *section;
    101 };
    102 
    103 struct saved_offsets
    104 {
    105   int section_count;
    106   struct saved_output_info *sections;
    107 };
    108 
    109 /* The sections in ABFD may already have output sections and offsets
    110    set if we are here during linking.
    111 
    112    DWARF-2 specifies offsets into debug sections in many cases and
    113    bfd_simple_get_relocated_section_contents is called to relocate
    114    debug info for a single relocatable object file.  So we want
    115    offsets relative to that object file's sections, not offsets in the
    116    output file.  For that reason, reset a debug section->output_offset
    117    to zero.
    118 
    119    If not called during linking then set section->output_section to
    120    point back to the input section, because output_section must not be
    121    NULL when calling the relocation routines.
    122 
    123    Save the original output offset and section to restore later.  */
    124 
    125 static void
    126 simple_save_output_info (bfd *abfd ATTRIBUTE_UNUSED,
    127 			 asection *section,
    128 			 void *ptr)
    129 {
    130   struct saved_offsets *saved_offsets = (struct saved_offsets *) ptr;
    131   struct saved_output_info *output_info;
    132 
    133   output_info = &saved_offsets->sections[section->index];
    134   output_info->offset = section->output_offset;
    135   output_info->section = section->output_section;
    136   if ((section->flags & SEC_DEBUGGING) != 0
    137       || section->output_section == NULL)
    138     {
    139       section->output_offset = 0;
    140       section->output_section = section;
    141     }
    142 }
    143 
    144 static void
    145 simple_restore_output_info (bfd *abfd ATTRIBUTE_UNUSED,
    146 			    asection *section,
    147 			    void *ptr)
    148 {
    149   struct saved_offsets *saved_offsets = (struct saved_offsets *) ptr;
    150   struct saved_output_info *output_info;
    151 
    152   if (section->index >= saved_offsets->section_count)
    153     return;
    154 
    155   output_info = &saved_offsets->sections[section->index];
    156   section->output_offset = output_info->offset;
    157   section->output_section = output_info->section;
    158 }
    159 
    160 /*
    161 FUNCTION
    162 	bfd_simple_relocate_secton
    163 
    164 SYNOPSIS
    165 	bfd_byte *bfd_simple_get_relocated_section_contents
    166 	  (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
    167 
    168 DESCRIPTION
    169 	Returns the relocated contents of section @var{sec}.  The symbols in
    170 	@var{symbol_table} will be used, or the symbols from @var{abfd} if
    171 	@var{symbol_table} is NULL.  The output offsets for debug sections will
    172 	be temporarily reset to 0.  The result will be stored at @var{outbuf}
    173 	or allocated with @code{bfd_malloc} if @var{outbuf} is @code{NULL}.
    174 
    175 	Returns @code{NULL} on a fatal error; ignores errors applying
    176 	particular relocations.
    177 */
    178 
    179 bfd_byte *
    180 bfd_simple_get_relocated_section_contents (bfd *abfd,
    181 					   asection *sec,
    182 					   bfd_byte *outbuf,
    183 					   asymbol **symbol_table)
    184 {
    185   struct bfd_link_info link_info;
    186   struct bfd_link_order link_order;
    187   struct bfd_link_callbacks callbacks;
    188   bfd_byte *contents, *data;
    189   int storage_needed;
    190   struct saved_offsets saved_offsets;
    191   bfd *link_next;
    192 
    193   /* Don't apply relocation on executable and shared library.  See
    194      PR 4756.  */
    195   if ((abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC)) != HAS_RELOC
    196       || ! (sec->flags & SEC_RELOC))
    197     {
    198       contents = outbuf;
    199       if (!bfd_get_full_section_contents (abfd, sec, &contents))
    200 	return NULL;
    201       return contents;
    202     }
    203 
    204   /* In order to use bfd_get_relocated_section_contents, we need
    205      to forge some data structures that it expects.  */
    206 
    207   /* Fill in the bare minimum number of fields for our purposes.  */
    208   memset (&link_info, 0, sizeof (link_info));
    209   link_info.output_bfd = abfd;
    210   link_info.input_bfds = abfd;
    211   link_info.input_bfds_tail = &abfd->link.next;
    212 
    213   link_next = abfd->link.next;
    214   abfd->link.next = NULL;
    215   link_info.hash = _bfd_generic_link_hash_table_create (abfd);
    216   link_info.callbacks = &callbacks;
    217   callbacks.warning = simple_dummy_warning;
    218   callbacks.undefined_symbol = simple_dummy_undefined_symbol;
    219   callbacks.reloc_overflow = simple_dummy_reloc_overflow;
    220   callbacks.reloc_dangerous = simple_dummy_reloc_dangerous;
    221   callbacks.unattached_reloc = simple_dummy_unattached_reloc;
    222   callbacks.multiple_definition = simple_dummy_multiple_definition;
    223   callbacks.einfo = simple_dummy_einfo;
    224 
    225   memset (&link_order, 0, sizeof (link_order));
    226   link_order.next = NULL;
    227   link_order.type = bfd_indirect_link_order;
    228   link_order.offset = 0;
    229   link_order.size = sec->size;
    230   link_order.u.indirect.section = sec;
    231 
    232   data = NULL;
    233   if (outbuf == NULL)
    234     {
    235       bfd_size_type amt = sec->rawsize > sec->size ? sec->rawsize : sec->size;
    236       data = (bfd_byte *) bfd_malloc (amt);
    237       if (data == NULL)
    238 	{
    239 	  _bfd_generic_link_hash_table_free (abfd);
    240 	  abfd->link.next = link_next;
    241 	  return NULL;
    242 	}
    243       outbuf = data;
    244     }
    245 
    246   saved_offsets.section_count = abfd->section_count;
    247   saved_offsets.sections = malloc (sizeof (*saved_offsets.sections)
    248 				   * saved_offsets.section_count);
    249   if (saved_offsets.sections == NULL)
    250     {
    251       if (data)
    252 	free (data);
    253       _bfd_generic_link_hash_table_free (abfd);
    254       abfd->link.next = link_next;
    255       return NULL;
    256     }
    257   bfd_map_over_sections (abfd, simple_save_output_info, &saved_offsets);
    258 
    259   if (symbol_table == NULL)
    260     {
    261       _bfd_generic_link_add_symbols (abfd, &link_info);
    262 
    263       storage_needed = bfd_get_symtab_upper_bound (abfd);
    264       symbol_table = (asymbol **) bfd_malloc (storage_needed);
    265       bfd_canonicalize_symtab (abfd, symbol_table);
    266     }
    267   else
    268     storage_needed = 0;
    269 
    270   contents = bfd_get_relocated_section_contents (abfd,
    271 						 &link_info,
    272 						 &link_order,
    273 						 outbuf,
    274 						 0,
    275 						 symbol_table);
    276   if (contents == NULL && data != NULL)
    277     free (data);
    278 
    279   bfd_map_over_sections (abfd, simple_restore_output_info, &saved_offsets);
    280   free (saved_offsets.sections);
    281 
    282   _bfd_generic_link_hash_table_free (abfd);
    283   abfd->link.next = link_next;
    284   return contents;
    285 }
    286