1130561Sobrien/* simple.c -- BFD simple client routines 2218822Sdim Copyright 2002, 2003, 2004, 2005, 2007 3130561Sobrien Free Software Foundation, Inc. 4130561Sobrien Contributed by MontaVista Software, Inc. 5130561Sobrien 6130561Sobrien This file is part of BFD, the Binary File Descriptor library. 7130561Sobrien 8130561Sobrien This program is free software; you can redistribute it and/or modify 9130561Sobrien it under the terms of the GNU General Public License as published by 10130561Sobrien the Free Software Foundation; either version 2 of the License, or 11130561Sobrien (at your option) any later version. 12130561Sobrien 13130561Sobrien This program is distributed in the hope that it will be useful, 14130561Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 15130561Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16130561Sobrien GNU General Public License for more details. 17130561Sobrien 18130561Sobrien You should have received a copy of the GNU General Public License 19130561Sobrien along with this program; if not, write to the Free Software 20218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 21130561Sobrien 22218822Sdim#include "sysdep.h" 23130561Sobrien#include "bfd.h" 24130561Sobrien#include "libbfd.h" 25130561Sobrien#include "bfdlink.h" 26130561Sobrien 27130561Sobrienstatic bfd_boolean 28130561Sobriensimple_dummy_warning (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, 29130561Sobrien const char *warning ATTRIBUTE_UNUSED, 30130561Sobrien const char *symbol ATTRIBUTE_UNUSED, 31130561Sobrien bfd *abfd ATTRIBUTE_UNUSED, 32130561Sobrien asection *section ATTRIBUTE_UNUSED, 33130561Sobrien bfd_vma address ATTRIBUTE_UNUSED) 34130561Sobrien{ 35130561Sobrien return TRUE; 36130561Sobrien} 37130561Sobrien 38130561Sobrienstatic bfd_boolean 39130561Sobriensimple_dummy_undefined_symbol (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, 40130561Sobrien const char *name ATTRIBUTE_UNUSED, 41130561Sobrien bfd *abfd ATTRIBUTE_UNUSED, 42130561Sobrien asection *section ATTRIBUTE_UNUSED, 43130561Sobrien bfd_vma address ATTRIBUTE_UNUSED, 44130561Sobrien bfd_boolean fatal ATTRIBUTE_UNUSED) 45130561Sobrien{ 46130561Sobrien return TRUE; 47130561Sobrien} 48130561Sobrien 49130561Sobrienstatic bfd_boolean 50130561Sobriensimple_dummy_reloc_overflow (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, 51218822Sdim struct bfd_link_hash_entry *entry ATTRIBUTE_UNUSED, 52130561Sobrien const char *name ATTRIBUTE_UNUSED, 53130561Sobrien const char *reloc_name ATTRIBUTE_UNUSED, 54130561Sobrien bfd_vma addend ATTRIBUTE_UNUSED, 55130561Sobrien bfd *abfd ATTRIBUTE_UNUSED, 56130561Sobrien asection *section ATTRIBUTE_UNUSED, 57130561Sobrien bfd_vma address ATTRIBUTE_UNUSED) 58130561Sobrien{ 59130561Sobrien return TRUE; 60130561Sobrien} 61130561Sobrien 62130561Sobrienstatic bfd_boolean 63130561Sobriensimple_dummy_reloc_dangerous (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, 64130561Sobrien const char *message ATTRIBUTE_UNUSED, 65130561Sobrien bfd *abfd ATTRIBUTE_UNUSED, 66130561Sobrien asection *section ATTRIBUTE_UNUSED, 67130561Sobrien bfd_vma address ATTRIBUTE_UNUSED) 68130561Sobrien{ 69130561Sobrien return TRUE; 70130561Sobrien} 71130561Sobrien 72130561Sobrienstatic bfd_boolean 73130561Sobriensimple_dummy_unattached_reloc (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, 74130561Sobrien const char *name ATTRIBUTE_UNUSED, 75130561Sobrien bfd *abfd ATTRIBUTE_UNUSED, 76130561Sobrien asection *section ATTRIBUTE_UNUSED, 77130561Sobrien bfd_vma address ATTRIBUTE_UNUSED) 78130561Sobrien{ 79130561Sobrien return TRUE; 80130561Sobrien} 81130561Sobrien 82218822Sdimstatic bfd_boolean 83218822Sdimsimple_dummy_multiple_definition (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, 84218822Sdim const char *name ATTRIBUTE_UNUSED, 85218822Sdim bfd *obfd ATTRIBUTE_UNUSED, 86218822Sdim asection *osec ATTRIBUTE_UNUSED, 87218822Sdim bfd_vma oval ATTRIBUTE_UNUSED, 88218822Sdim bfd *nbfd ATTRIBUTE_UNUSED, 89218822Sdim asection *nsec ATTRIBUTE_UNUSED, 90218822Sdim bfd_vma nval ATTRIBUTE_UNUSED) 91218822Sdim{ 92218822Sdim return TRUE; 93218822Sdim} 94218822Sdim 95218822Sdimstatic void 96218822Sdimsimple_dummy_einfo (const char *fmt ATTRIBUTE_UNUSED, ...) 97218822Sdim{ 98218822Sdim} 99218822Sdim 100130561Sobrienstruct saved_output_info 101130561Sobrien{ 102130561Sobrien bfd_vma offset; 103130561Sobrien asection *section; 104130561Sobrien}; 105130561Sobrien 106130561Sobrienstatic void 107130561Sobriensimple_save_output_info (bfd *abfd ATTRIBUTE_UNUSED, 108130561Sobrien asection *section, 109130561Sobrien void *ptr) 110130561Sobrien{ 111130561Sobrien struct saved_output_info *output_info = ptr; 112130561Sobrien output_info[section->index].offset = section->output_offset; 113130561Sobrien output_info[section->index].section = section->output_section; 114218822Sdim if ((section->flags & SEC_DEBUGGING) != 0 115218822Sdim || section->output_section == NULL) 116218822Sdim { 117218822Sdim section->output_offset = 0; 118218822Sdim section->output_section = section; 119218822Sdim } 120130561Sobrien} 121130561Sobrien 122130561Sobrienstatic void 123130561Sobriensimple_restore_output_info (bfd *abfd ATTRIBUTE_UNUSED, 124130561Sobrien asection *section, 125130561Sobrien void *ptr) 126130561Sobrien{ 127130561Sobrien struct saved_output_info *output_info = ptr; 128130561Sobrien section->output_offset = output_info[section->index].offset; 129130561Sobrien section->output_section = output_info[section->index].section; 130130561Sobrien} 131130561Sobrien 132130561Sobrien/* 133130561SobrienFUNCTION 134130561Sobrien bfd_simple_relocate_secton 135130561Sobrien 136130561SobrienSYNOPSIS 137130561Sobrien bfd_byte *bfd_simple_get_relocated_section_contents 138130561Sobrien (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table); 139130561Sobrien 140130561SobrienDESCRIPTION 141130561Sobrien Returns the relocated contents of section @var{sec}. The symbols in 142130561Sobrien @var{symbol_table} will be used, or the symbols from @var{abfd} if 143218822Sdim @var{symbol_table} is NULL. The output offsets for debug sections will 144130561Sobrien be temporarily reset to 0. The result will be stored at @var{outbuf} 145130561Sobrien or allocated with @code{bfd_malloc} if @var{outbuf} is @code{NULL}. 146130561Sobrien 147130561Sobrien Returns @code{NULL} on a fatal error; ignores errors applying 148130561Sobrien particular relocations. 149130561Sobrien*/ 150130561Sobrien 151130561Sobrienbfd_byte * 152130561Sobrienbfd_simple_get_relocated_section_contents (bfd *abfd, 153130561Sobrien asection *sec, 154130561Sobrien bfd_byte *outbuf, 155130561Sobrien asymbol **symbol_table) 156130561Sobrien{ 157130561Sobrien struct bfd_link_info link_info; 158130561Sobrien struct bfd_link_order link_order; 159130561Sobrien struct bfd_link_callbacks callbacks; 160130561Sobrien bfd_byte *contents, *data; 161130561Sobrien int storage_needed; 162130561Sobrien void *saved_offsets; 163130561Sobrien 164130561Sobrien if (! (sec->flags & SEC_RELOC)) 165130561Sobrien { 166218822Sdim bfd_size_type amt = sec->rawsize > sec->size ? sec->rawsize : sec->size; 167218822Sdim bfd_size_type size = sec->rawsize ? sec->rawsize : sec->size; 168130561Sobrien 169130561Sobrien if (outbuf == NULL) 170218822Sdim contents = bfd_malloc (amt); 171130561Sobrien else 172130561Sobrien contents = outbuf; 173130561Sobrien 174130561Sobrien if (contents) 175130561Sobrien bfd_get_section_contents (abfd, sec, contents, 0, size); 176130561Sobrien 177130561Sobrien return contents; 178130561Sobrien } 179130561Sobrien 180130561Sobrien /* In order to use bfd_get_relocated_section_contents, we need 181130561Sobrien to forge some data structures that it expects. */ 182130561Sobrien 183130561Sobrien /* Fill in the bare minimum number of fields for our purposes. */ 184130561Sobrien memset (&link_info, 0, sizeof (link_info)); 185130561Sobrien link_info.input_bfds = abfd; 186218822Sdim link_info.input_bfds_tail = &abfd->link_next; 187130561Sobrien 188130561Sobrien link_info.hash = _bfd_generic_link_hash_table_create (abfd); 189130561Sobrien link_info.callbacks = &callbacks; 190130561Sobrien callbacks.warning = simple_dummy_warning; 191130561Sobrien callbacks.undefined_symbol = simple_dummy_undefined_symbol; 192130561Sobrien callbacks.reloc_overflow = simple_dummy_reloc_overflow; 193130561Sobrien callbacks.reloc_dangerous = simple_dummy_reloc_dangerous; 194130561Sobrien callbacks.unattached_reloc = simple_dummy_unattached_reloc; 195218822Sdim callbacks.multiple_definition = simple_dummy_multiple_definition; 196218822Sdim callbacks.einfo = simple_dummy_einfo; 197130561Sobrien 198130561Sobrien memset (&link_order, 0, sizeof (link_order)); 199130561Sobrien link_order.next = NULL; 200130561Sobrien link_order.type = bfd_indirect_link_order; 201130561Sobrien link_order.offset = 0; 202218822Sdim link_order.size = sec->size; 203130561Sobrien link_order.u.indirect.section = sec; 204130561Sobrien 205130561Sobrien data = NULL; 206130561Sobrien if (outbuf == NULL) 207130561Sobrien { 208218822Sdim data = bfd_malloc (sec->size); 209130561Sobrien if (data == NULL) 210130561Sobrien return NULL; 211130561Sobrien outbuf = data; 212130561Sobrien } 213130561Sobrien 214130561Sobrien /* The sections in ABFD may already have output sections and offsets set. 215130561Sobrien Because this function is primarily for debug sections, and GCC uses the 216130561Sobrien knowledge that debug sections will generally have VMA 0 when emitting 217130561Sobrien relocations between DWARF-2 sections (which are supposed to be 218130561Sobrien section-relative offsets anyway), we need to reset the output offsets 219130561Sobrien to zero. We also need to arrange for section->output_section->vma plus 220130561Sobrien section->output_offset to equal section->vma, which we do by setting 221130561Sobrien section->output_section to point back to section. Save the original 222130561Sobrien output offset and output section to restore later. */ 223130561Sobrien saved_offsets = malloc (sizeof (struct saved_output_info) 224130561Sobrien * abfd->section_count); 225130561Sobrien if (saved_offsets == NULL) 226130561Sobrien { 227130561Sobrien if (data) 228130561Sobrien free (data); 229130561Sobrien return NULL; 230130561Sobrien } 231130561Sobrien bfd_map_over_sections (abfd, simple_save_output_info, saved_offsets); 232130561Sobrien 233130561Sobrien if (symbol_table == NULL) 234130561Sobrien { 235130561Sobrien _bfd_generic_link_add_symbols (abfd, &link_info); 236130561Sobrien 237130561Sobrien storage_needed = bfd_get_symtab_upper_bound (abfd); 238130561Sobrien symbol_table = bfd_malloc (storage_needed); 239130561Sobrien bfd_canonicalize_symtab (abfd, symbol_table); 240130561Sobrien } 241130561Sobrien else 242130561Sobrien storage_needed = 0; 243130561Sobrien 244130561Sobrien contents = bfd_get_relocated_section_contents (abfd, 245130561Sobrien &link_info, 246130561Sobrien &link_order, 247130561Sobrien outbuf, 248130561Sobrien 0, 249130561Sobrien symbol_table); 250130561Sobrien if (contents == NULL && data != NULL) 251130561Sobrien free (data); 252130561Sobrien 253130561Sobrien bfd_map_over_sections (abfd, simple_restore_output_info, saved_offsets); 254130561Sobrien free (saved_offsets); 255130561Sobrien 256130561Sobrien _bfd_generic_link_hash_table_free (link_info.hash); 257130561Sobrien return contents; 258130561Sobrien} 259