// reloc.cc -- relocate input files for gold.
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright (C) 2006-2014 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
void
Read_relocs::locks(Task_locker* tl)
{
- tl->add(this, this->object_->token());
+ Task_token* token = this->object_->token();
+ if (token != NULL)
+ tl->add(this, token);
}
// Read the relocations and then start a Scan_relocs_task.
void
Scan_relocs::locks(Task_locker* tl)
{
- tl->add(this, this->object_->token());
+ Task_token* token = this->object_->token();
+ if (token != NULL)
+ tl->add(this, token);
tl->add(this, this->next_blocker_);
}
if (this->input_sections_blocker_ != NULL)
tl->add(this, this->input_sections_blocker_);
tl->add(this, this->final_blocker_);
- tl->add(this, this->object_->token());
+ Task_token* token = this->object_->token();
+ if (token != NULL)
+ tl->add(this, token);
}
// Run the task.
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
+Sized_relobj_file<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
{
rd->relocs.clear();
rd->relocs.reserve(shnum / 2);
const Output_sections& out_sections(this->output_sections());
- const std::vector<Address>& out_offsets(this->section_offsets_);
+ const std::vector<Address>& out_offsets(this->section_offsets());
const unsigned char* pshdrs = this->get_view(this->elf_file_.shoff(),
shnum * This::shdr_size,
off_t sh_size = shdr.get_sh_size();
+ if (sh_size == 0)
+ continue;
+
unsigned int reloc_size;
if (sh_type == elfcpp::SHT_REL)
reloc_size = elfcpp::Elf_sizes<size>::rel_size;
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::do_gc_process_relocs(Symbol_table* symtab,
- Layout* layout,
- Read_relocs_data* rd)
+Sized_relobj_file<size, big_endian>::do_gc_process_relocs(Symbol_table* symtab,
+ Layout* layout,
+ Read_relocs_data* rd)
{
Sized_target<size, big_endian>* target =
parameters->sized_target<size, big_endian>();
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::do_scan_relocs(Symbol_table* symtab,
+Sized_relobj_file<size, big_endian>::do_scan_relocs(Symbol_table* symtab,
Layout* layout,
Read_relocs_data* rd)
{
// For incremental links, finalize the allocation of relocations.
if (layout->incremental_inputs() != NULL)
- this->finalize_incremental_relocs(layout);
+ this->finalize_incremental_relocs(layout, true);
if (rd->local_symbols != NULL)
{
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::emit_relocs_scan(
+Sized_relobj_file<size, big_endian>::emit_relocs_scan(
Symbol_table* symtab,
Layout* layout,
const unsigned char* plocal_syms,
template<int size, bool big_endian>
template<int sh_type>
void
-Sized_relobj<size, big_endian>::emit_relocs_scan_reltype(
+Sized_relobj_file<size, big_endian>::emit_relocs_scan_reltype(
Symbol_table* symtab,
Layout* layout,
const unsigned char* plocal_syms,
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::incremental_relocs_scan(
+Sized_relobj_file<size, big_endian>::incremental_relocs_scan(
const Read_relocs_data::Relocs_list::iterator& p)
{
if (p->sh_type == elfcpp::SHT_REL)
}
}
-// Scan the input relocation for --emit-relocs, templatized on the
+// Scan the input relocation for --incremental, templatized on the
// type of the relocation section.
template<int size, bool big_endian>
template<int sh_type>
void
-Sized_relobj<size, big_endian>::incremental_relocs_scan_reltype(
+Sized_relobj_file<size, big_endian>::incremental_relocs_scan_reltype(
const Read_relocs_data::Relocs_list::iterator& p)
{
typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::do_relocate(const Symbol_table* symtab,
- const Layout* layout,
- Output_file* of)
+Sized_relobj_file<size, big_endian>::do_relocate(const Symbol_table* symtab,
+ const Layout* layout,
+ Output_file* of)
{
unsigned int shnum = this->shnum();
// section data to the output file. The second one applies
// relocations.
- this->write_sections(pshdrs, of, &views);
+ this->write_sections(layout, pshdrs, of, &views);
// To speed up relocations, we set up hash tables for fast lookup of
// input offsets to output addresses.
{
if (views[i].view != NULL)
{
+ if (views[i].is_ctors_reverse_view)
+ this->reverse_words(views[i].view, views[i].view_size);
if (!views[i].is_postprocessing_view)
{
if (views[i].is_input_output_view)
// Write out the local symbols.
this->write_local_symbols(of, layout->sympool(), layout->dynpool(),
- layout->symtab_xindex(), layout->dynsym_xindex());
+ layout->symtab_xindex(), layout->dynsym_xindex(),
+ layout->symtab_section_offset());
}
// Sort a Read_multiple vector by file offset.
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs,
- Output_file* of,
- Views* pviews)
+Sized_relobj_file<size, big_endian>::write_sections(const Layout* layout,
+ const unsigned char* pshdrs,
+ Output_file* of,
+ Views* pviews)
{
unsigned int shnum = this->shnum();
const Output_sections& out_sections(this->output_sections());
- const std::vector<Address>& out_offsets(this->section_offsets_);
+ const std::vector<Address>& out_offsets(this->section_offsets());
File_read::Read_multiple rm;
bool is_sorted = true;
pvs->address = posd->address();
pvs->is_input_output_view = false;
pvs->is_postprocessing_view = false;
+ pvs->is_ctors_reverse_view = false;
continue;
}
pvs->view_size = view_size;
pvs->is_input_output_view = output_offset == invalid_address;
pvs->is_postprocessing_view = os->requires_postprocessing();
+ pvs->is_ctors_reverse_view =
+ (!parameters->options().relocatable()
+ && view_size > size / 8
+ && (strcmp(os->name(), ".init_array") == 0
+ || strcmp(os->name(), ".fini_array") == 0)
+ && layout->is_ctors_in_init_array(this, i));
}
// Actually read the data.
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::do_relocate_sections(
+Sized_relobj_file<size, big_endian>::do_relocate_sections(
const Symbol_table* symtab,
const Layout* layout,
const unsigned char* pshdrs,
parameters->sized_target<size, big_endian>();
const Output_sections& out_sections(this->output_sections());
- const std::vector<Address>& out_offsets(this->section_offsets_);
+ const std::vector<Address>& out_offsets(this->section_offsets());
Relocate_info<size, big_endian> relinfo;
relinfo.symtab = symtab;
output_offset == invalid_address,
view, address, view_size, reloc_map);
if (parameters->options().emit_relocs())
- this->emit_relocs(&relinfo, i, sh_type, prelocs, reloc_count,
- os, output_offset, view, address, view_size,
- (*pviews)[i].view, (*pviews)[i].view_size);
+ {
+ Relocatable_relocs* rr = this->relocatable_relocs(i);
+ target->relocate_relocs(&relinfo, sh_type, prelocs, reloc_count,
+ os, output_offset, rr,
+ view, address, view_size,
+ (*pviews)[i].view,
+ (*pviews)[i].view_size);
+ }
if (parameters->incremental())
this->incremental_relocs_write(&relinfo, sh_type, prelocs,
reloc_count, os, output_offset, of);
else
{
Relocatable_relocs* rr = this->relocatable_relocs(i);
- target->relocate_for_relocatable(&relinfo, sh_type, prelocs,
- reloc_count, os, output_offset, rr,
- view, address, view_size,
- (*pviews)[i].view,
- (*pviews)[i].view_size);
+ target->relocate_relocs(&relinfo, sh_type, prelocs, reloc_count,
+ os, output_offset, rr,
+ view, address, view_size,
+ (*pviews)[i].view,
+ (*pviews)[i].view_size);
}
}
}
-// Emit the relocs for --emit-relocs.
-
-template<int size, bool big_endian>
-void
-Sized_relobj<size, big_endian>::emit_relocs(
- const Relocate_info<size, big_endian>* relinfo,
- unsigned int i,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section,
- unsigned char* view,
- typename elfcpp::Elf_types<size>::Elf_Addr address,
- section_size_type view_size,
- unsigned char* reloc_view,
- section_size_type reloc_view_size)
-{
- if (sh_type == elfcpp::SHT_REL)
- this->emit_relocs_reltype<elfcpp::SHT_REL>(relinfo, i, prelocs,
- reloc_count, output_section,
- offset_in_output_section,
- view, address, view_size,
- reloc_view, reloc_view_size);
- else
- {
- gold_assert(sh_type == elfcpp::SHT_RELA);
- this->emit_relocs_reltype<elfcpp::SHT_RELA>(relinfo, i, prelocs,
- reloc_count, output_section,
- offset_in_output_section,
- view, address, view_size,
- reloc_view, reloc_view_size);
- }
-}
-
-// Emit the relocs for --emit-relocs, templatized on the type of the
-// relocation section.
-
-template<int size, bool big_endian>
-template<int sh_type>
-void
-Sized_relobj<size, big_endian>::emit_relocs_reltype(
- const Relocate_info<size, big_endian>* relinfo,
- unsigned int i,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section,
- unsigned char* view,
- typename elfcpp::Elf_types<size>::Elf_Addr address,
- section_size_type view_size,
- unsigned char* reloc_view,
- section_size_type reloc_view_size)
-{
- const Relocatable_relocs* rr = this->relocatable_relocs(i);
- relocate_for_relocatable<size, big_endian, sh_type>(
- relinfo,
- prelocs,
- reloc_count,
- output_section,
- offset_in_output_section,
- rr,
- view,
- address,
- view_size,
- reloc_view,
- reloc_view_size);
-}
-
// Write the incremental relocs.
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::incremental_relocs_write(
+Sized_relobj_file<size, big_endian>::incremental_relocs_write(
const Relocate_info<size, big_endian>* relinfo,
unsigned int sh_type,
const unsigned char* prelocs,
template<int size, bool big_endian>
template<int sh_type>
void
-Sized_relobj<size, big_endian>::incremental_relocs_write_reltype(
+Sized_relobj_file<size, big_endian>::incremental_relocs_write_reltype(
const Relocate_info<size, big_endian>* relinfo,
const unsigned char* prelocs,
size_t reloc_count,
const unsigned int reloc_size =
Reloc_types<sh_type, size, big_endian>::reloc_size;
const unsigned int sizeof_addr = size / 8;
- const unsigned int incr_reloc_size = 8 + 2 * sizeof_addr;
+ const unsigned int incr_reloc_size =
+ Incremental_relocs_reader<size, big_endian>::reloc_size;
unsigned int out_shndx = output_section->out_shndx();
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::initialize_input_to_output_maps()
+Sized_relobj_file<size, big_endian>::initialize_input_to_output_maps()
{
const unsigned int loccount = this->local_symbol_count_;
for (unsigned int i = 1; i < loccount; ++i)
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::free_input_to_output_maps()
+Sized_relobj_file<size, big_endian>::free_input_to_output_maps()
{
const unsigned int loccount = this->local_symbol_count_;
for (unsigned int i = 1; i < loccount; ++i)
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::split_stack_adjust(
+Sized_relobj_file<size, big_endian>::split_stack_adjust(
const Symbol_table* symtab,
const unsigned char* pshdrs,
unsigned int sh_type,
template<int size, bool big_endian>
template<int sh_type>
void
-Sized_relobj<size, big_endian>::split_stack_adjust_reltype(
+Sized_relobj_file<size, big_endian>::split_stack_adjust_reltype(
const Symbol_table* symtab,
const unsigned char* pshdrs,
unsigned int shndx,
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::find_functions(
+Sized_relobj_file<size, big_endian>::find_functions(
const unsigned char* pshdrs,
unsigned int shndx,
- Sized_relobj<size, big_endian>::Function_offsets* function_offsets)
+ Sized_relobj_file<size, big_endian>::Function_offsets* function_offsets)
{
// We need to read the symbols to find the functions. If we wanted
// to, we could cache reading the symbols across all sections in the
}
}
+// Reverse the words in a section. Used for .ctors sections mapped to
+// .init_array sections. See ctors_sections_in_init_array in
+// layout.cc.
+
+template<int size, bool big_endian>
+void
+Sized_relobj_file<size, big_endian>::reverse_words(unsigned char* view,
+ section_size_type view_size)
+{
+ typedef typename elfcpp::Swap<size, big_endian>::Valtype Valtype;
+ Valtype* vview = reinterpret_cast<Valtype*>(view);
+ section_size_type vview_size = view_size / (size / 8);
+ for (section_size_type i = 0; i < vview_size / 2; ++i)
+ {
+ Valtype tmp = vview[i];
+ vview[i] = vview[vview_size - 1 - i];
+ vview[vview_size - 1 - i] = tmp;
+ }
+}
+
// Class Merged_symbol_value.
template<int size>
#ifdef HAVE_TARGET_32_LITTLE
template
void
-Sized_relobj<32, false>::do_read_relocs(Read_relocs_data* rd);
+Sized_relobj_file<32, false>::do_read_relocs(Read_relocs_data* rd);
#endif
#ifdef HAVE_TARGET_32_BIG
template
void
-Sized_relobj<32, true>::do_read_relocs(Read_relocs_data* rd);
+Sized_relobj_file<32, true>::do_read_relocs(Read_relocs_data* rd);
#endif
#ifdef HAVE_TARGET_64_LITTLE
template
void
-Sized_relobj<64, false>::do_read_relocs(Read_relocs_data* rd);
+Sized_relobj_file<64, false>::do_read_relocs(Read_relocs_data* rd);
#endif
#ifdef HAVE_TARGET_64_BIG
template
void
-Sized_relobj<64, true>::do_read_relocs(Read_relocs_data* rd);
+Sized_relobj_file<64, true>::do_read_relocs(Read_relocs_data* rd);
#endif
#ifdef HAVE_TARGET_32_LITTLE
template
void
-Sized_relobj<32, false>::do_gc_process_relocs(Symbol_table* symtab,
- Layout* layout,
- Read_relocs_data* rd);
+Sized_relobj_file<32, false>::do_gc_process_relocs(Symbol_table* symtab,
+ Layout* layout,
+ Read_relocs_data* rd);
#endif
#ifdef HAVE_TARGET_32_BIG
template
void
-Sized_relobj<32, true>::do_gc_process_relocs(Symbol_table* symtab,
- Layout* layout,
- Read_relocs_data* rd);
+Sized_relobj_file<32, true>::do_gc_process_relocs(Symbol_table* symtab,
+ Layout* layout,
+ Read_relocs_data* rd);
#endif
#ifdef HAVE_TARGET_64_LITTLE
template
void
-Sized_relobj<64, false>::do_gc_process_relocs(Symbol_table* symtab,
- Layout* layout,
- Read_relocs_data* rd);
+Sized_relobj_file<64, false>::do_gc_process_relocs(Symbol_table* symtab,
+ Layout* layout,
+ Read_relocs_data* rd);
#endif
#ifdef HAVE_TARGET_64_BIG
template
void
-Sized_relobj<64, true>::do_gc_process_relocs(Symbol_table* symtab,
- Layout* layout,
- Read_relocs_data* rd);
+Sized_relobj_file<64, true>::do_gc_process_relocs(Symbol_table* symtab,
+ Layout* layout,
+ Read_relocs_data* rd);
#endif
#ifdef HAVE_TARGET_32_LITTLE
template
void
-Sized_relobj<32, false>::do_scan_relocs(Symbol_table* symtab,
- Layout* layout,
- Read_relocs_data* rd);
+Sized_relobj_file<32, false>::do_scan_relocs(Symbol_table* symtab,
+ Layout* layout,
+ Read_relocs_data* rd);
#endif
#ifdef HAVE_TARGET_32_BIG
template
void
-Sized_relobj<32, true>::do_scan_relocs(Symbol_table* symtab,
- Layout* layout,
- Read_relocs_data* rd);
+Sized_relobj_file<32, true>::do_scan_relocs(Symbol_table* symtab,
+ Layout* layout,
+ Read_relocs_data* rd);
#endif
#ifdef HAVE_TARGET_64_LITTLE
template
void
-Sized_relobj<64, false>::do_scan_relocs(Symbol_table* symtab,
- Layout* layout,
- Read_relocs_data* rd);
+Sized_relobj_file<64, false>::do_scan_relocs(Symbol_table* symtab,
+ Layout* layout,
+ Read_relocs_data* rd);
#endif
#ifdef HAVE_TARGET_64_BIG
template
void
-Sized_relobj<64, true>::do_scan_relocs(Symbol_table* symtab,
- Layout* layout,
- Read_relocs_data* rd);
+Sized_relobj_file<64, true>::do_scan_relocs(Symbol_table* symtab,
+ Layout* layout,
+ Read_relocs_data* rd);
#endif
#ifdef HAVE_TARGET_32_LITTLE
template
void
-Sized_relobj<32, false>::do_relocate(const Symbol_table* symtab,
- const Layout* layout,
- Output_file* of);
+Sized_relobj_file<32, false>::do_relocate(const Symbol_table* symtab,
+ const Layout* layout,
+ Output_file* of);
#endif
#ifdef HAVE_TARGET_32_BIG
template
void
-Sized_relobj<32, true>::do_relocate(const Symbol_table* symtab,
- const Layout* layout,
- Output_file* of);
+Sized_relobj_file<32, true>::do_relocate(const Symbol_table* symtab,
+ const Layout* layout,
+ Output_file* of);
#endif
#ifdef HAVE_TARGET_64_LITTLE
template
void
-Sized_relobj<64, false>::do_relocate(const Symbol_table* symtab,
- const Layout* layout,
- Output_file* of);
+Sized_relobj_file<64, false>::do_relocate(const Symbol_table* symtab,
+ const Layout* layout,
+ Output_file* of);
#endif
#ifdef HAVE_TARGET_64_BIG
template
void
-Sized_relobj<64, true>::do_relocate(const Symbol_table* symtab,
- const Layout* layout,
- Output_file* of);
+Sized_relobj_file<64, true>::do_relocate(const Symbol_table* symtab,
+ const Layout* layout,
+ Output_file* of);
#endif
#ifdef HAVE_TARGET_32_LITTLE
template
void
-Sized_relobj<32, false>::do_relocate_sections(
+Sized_relobj_file<32, false>::do_relocate_sections(
const Symbol_table* symtab,
const Layout* layout,
const unsigned char* pshdrs,
#ifdef HAVE_TARGET_32_BIG
template
void
-Sized_relobj<32, true>::do_relocate_sections(
+Sized_relobj_file<32, true>::do_relocate_sections(
const Symbol_table* symtab,
const Layout* layout,
const unsigned char* pshdrs,
#ifdef HAVE_TARGET_64_LITTLE
template
void
-Sized_relobj<64, false>::do_relocate_sections(
+Sized_relobj_file<64, false>::do_relocate_sections(
const Symbol_table* symtab,
const Layout* layout,
const unsigned char* pshdrs,
#ifdef HAVE_TARGET_64_BIG
template
void
-Sized_relobj<64, true>::do_relocate_sections(
+Sized_relobj_file<64, true>::do_relocate_sections(
const Symbol_table* symtab,
const Layout* layout,
const unsigned char* pshdrs,
#ifdef HAVE_TARGET_32_LITTLE
template
void
-Sized_relobj<32, false>::initialize_input_to_output_maps();
+Sized_relobj_file<32, false>::initialize_input_to_output_maps();
template
void
-Sized_relobj<32, false>::free_input_to_output_maps();
+Sized_relobj_file<32, false>::free_input_to_output_maps();
#endif
#ifdef HAVE_TARGET_32_BIG
template
void
-Sized_relobj<32, true>::initialize_input_to_output_maps();
+Sized_relobj_file<32, true>::initialize_input_to_output_maps();
template
void
-Sized_relobj<32, true>::free_input_to_output_maps();
+Sized_relobj_file<32, true>::free_input_to_output_maps();
#endif
#ifdef HAVE_TARGET_64_LITTLE
template
void
-Sized_relobj<64, false>::initialize_input_to_output_maps();
+Sized_relobj_file<64, false>::initialize_input_to_output_maps();
template
void
-Sized_relobj<64, false>::free_input_to_output_maps();
+Sized_relobj_file<64, false>::free_input_to_output_maps();
#endif
#ifdef HAVE_TARGET_64_BIG
template
void
-Sized_relobj<64, true>::initialize_input_to_output_maps();
+Sized_relobj_file<64, true>::initialize_input_to_output_maps();
template
void
-Sized_relobj<64, true>::free_input_to_output_maps();
+Sized_relobj_file<64, true>::free_input_to_output_maps();
#endif
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)