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