public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [gold patch] Incremental 13/18: Dynamic relocations
@ 2011-04-04 22:33 Cary Coutant
  2011-05-24 14:45 ` Ian Lance Taylor
  0 siblings, 1 reply; 5+ messages in thread
From: Cary Coutant @ 2011-04-04 22:33 UTC (permalink / raw)
  To: Ian Lance Taylor, Binutils

[-- Attachment #1: Type: text/plain, Size: 8003 bytes --]

This patch adds incremental update support for dynamic relocations.
For dynamic relocations that result from static relocations from input
files, I record the range of output dynamic relocs for each input
file, and copy those over to the output file (adding two more fields
to the incremental info for each input file). For dynamic relocations
generated for other purposes, I let the linker regenerate them. In
order to regenerate the dynamic relocations for GOT entries, I added a
couple more target hooks, moved a bunch of GOT-related methods up to
Sized_relobj_base, and adjusted the types of the relobj parameter to
Output_data_got and Output_data_reloc methods.

-cary


	* incremental-dump.cc (dump_incremental_inputs): Print dynamic reloc
	info; adjust display of GOT entries.
	* incremental.cc (Sized_incremental_binary::setup_readers): Allocate
	vector of input objects; remove file_status_.
	(Sized_incremental_binary::do_reserve_layout): Remove file_status_.
	(Sized_incremental_binary::do_process_got_plt): Adjust calls to
	got_plt reader; call target hooks to reserve GOT entries.
	(Output_section_incremental_inputs::set_final_data_size): Adjust size
	of input file info header and GOT info entry.
	(Output_section_incremental_inputs::write_info_blocks): Write dynamic
	relocation info.
	(Got_plt_view_info::got_descriptor): Remove.
	(Got_plt_view_info::sym_index): New data member.
	(Got_plt_view_info::input_index): New data member.
	(Local_got_offset_visitor::visit): Write input file index.
	(Global_got_offset_visitor::visit): Write 0 for input file index.
	(Global_symbol_visitor_got_plt::operator()): Replace got_descriptor
	with sym_index and input_index.
	(Output_section_incremental_inputs::write_got_plt): Adjust size of
	incremental info GOT entry; replace got_descriptor with input_index.
	(Sized_incr_relobj::Sized_incr_relobj): Adjust initializers; record
	map from input file index to object.
	(Sized_incr_relobj::do_layout): Replace direct data member reference
	with accessor function.
	(Sized_incr_relobj::do_for_all_local_got_entries): Move to base class.
	* incremental.h (Incremental_input_entry_reader::get_symbol_offset):
	Adjust size of input file info header.
	(Incremental_input_entry_reader::get_first_dyn_reloc): New function.
	(Incremental_input_entry_reader::get_dyn_reloc_count): New function.
	(Incremental_input_entry_reader::get_input_section): Adjust size of
	input file info header.
	(Incremental_got_plt_reader::Incremental_got_plt_reader): Adjust size
	of incremental info GOT entry.
	(Incremental_got_plt_reader::get_got_desc): Remove.
	(Incremental_got_plt_reader::get_got_symndx): New function.
	(Incremental_got_plt_reader::get_got_input_index): New function.
	(Sized_incremental_binary::Sized_incremental_binary): Remove
	file_status_; add input_objects_.
	(Sized_incremental_binary::~Sized_incremental_binary): Remove.
	(Sized_incremental_binary::set_file_is_unchanged): Remove.
	(Sized_incremental_binary::file_is_unchanged): Remove.
	(Sized_incremental_binary::set_input_object): New function.
	(Sized_incremental_binary::input_object): New function.
	(Sized_incremental_binary::file_status_): Remove.
	(Sized_incremental_binary::input_objects_): New data member.
	(Sized_incr_relobj::invalid_address): Move to base class.
	(Sized_incr_relobj::is_output_section_offset_invalid): Move to base
	class.
	(Sized_incr_relobj::do_output_section_offset): Likewise.
	(Sized_incr_relobj::do_for_all_local_got_entries): Likewise.
	(Sized_incr_relobj::section_offsets_): Likewise.
	* object.cc (Sized_relobj_base::do_for_all_local_got_entries): New
	function.
	(Sized_relobj::Sized_relobj): Remove local_got_offsets_.
	(Sized_relobj::layout_section): Replace refs to section_offsets_
	with accessor function.
	(Sized_relobj::do_layout): Likewise.
	(Sized_relobj::do_layout_deferred_sections): Likewise.
	(Sized_relobj::do_for_all_local_got_entries): Move to base class.
	(Sized_relobj::compute_final_local_value): Replace refs to
	section_offsets_ with accessor function.
	(Sized_relobj::do_finalize_local_symbols): Likewise.
	* object.h (Relobj::Relobj): Initialize new data members.
	(Relobj::add_dyn_reloc): New function.
	(Relobj::first_dyn_reloc): New function.
	(Relobj::dyn_reloc_count): New function.
	(Relobj::first_dyn_reloc_): New data member.
	(Relobj::dyn_reloc_count_): New data member.
	(Sized_relobj_base::Address): New typedef.
	(Sized_relobj_base::invalid_address): Move here from child class.
	(Sized_relobj_base::Sized_relobj_base): Initialize new data members.
	(Sized_relobj_base::sized_relobj): New function.
	(Sized_relobj_base::is_output_section_offset_invalid): Move here from
	child class.
	(Sized_relobj_base::get_output_section_offset): Likewise.
	(Sized_relobj_base::local_has_got_offset): Likewise.
	(Sized_relobj_base::local_got_offset): Likewise.
	(Sized_relobj_base::set_local_got_offset): Likewise.
	(Sized_relobj_base::do_for_all_local_got_entries): Likewise.
	(Sized_relobj_base::clear_got_offsets): New function.
	(Sized_relobj_base::section_offsets): Move here from child class.
	(Sized_relobj_base::do_output_section_offset): Likewise.
	(Sized_relobj_base::do_set_section_offset): Likewise.
	(Sized_relobj_base::Local_got_offsets): Likewise.
	(Sized_relobj_base::local_got_offsets_): Likewise.
	(Sized_relobj_base::section_offsets_): Likewise.
	(Sized_relobj::is_output_section_offset_invalid): Move to base class.
	(Sized_relobj::sized_relobj): New function
	(Sized_relobj::local_has_got_offset): Move to base class.
	(Sized_relobj::local_got_offset): Likewise.
	(Sized_relobj::set_local_got_offset): Likewise.
	(Sized_relobj::get_output_section_offset): Likewise.
	(Sized_relobj::do_for_all_local_got_entries): Likewise.
	(Sized_relobj::do_output_section_offset): Likewise.
	(Sized_relobj::do_set_section_offset): Likewise.
	(Sized_relobj::Local_got_offsets): Likewise.
	(Sized_relobj::local_got_offsets_): Likewise.
	(Sized_relobj::section_offsets_): Likewise.
	* output.cc (Output_reloc::Output_reloc): Adjust type of relobj
	(all constructors).
	(set_needs_dynsym_index): Convert relobj to derived class pointer.
	(Output_reloc::get_symbol_index): Likewise.
	(Output_reloc::local_section_offset): Likewise.
	(Output_reloc::get_address): Likewise.
	(Output_reloc::symbol_value): Likewise.
	(Output_data_got::reserve_slot): Move to class definition.
	(Output_data_got::reserve_local): New function.
	(Output_data_got::reserve_slot_for_global): Remove.
	(Output_data_got::reserve_global): New function.
	* output.h (Output_reloc::Output_reloc): Adjust type of relobj
	(all constructors, two instantiations).
	(Output_reloc::get_relobj): New function (two instantiations).
	(Output_reloc::u1_.relobj, Output_reloc::u2_.relobj): Adjust type.
	(Output_data_reloc_base::add): Convert relobj to derived class pointer.
	(Output_data_reloc::add_global): Adjust type of relobj.
	(Output_data_reloc::add_global_relative): Likewise.
	(Output_data_reloc::add_symbolless_global_addend): Likewise.
	(Output_data_reloc::add_local): Likewise.
	(Output_data_reloc::add_local_relative): Likewise.
	(Output_data_reloc::add_symbolless_local_addend): Likewise.
	(Output_data_reloc::add_local_section): Likewise.
	(Output_data_reloc::add_output_section): Likewise.
	(Output_data_reloc::add_absolute): Likewise.
	(Output_data_reloc::add_target_specific): Likewise.
	(Output_data_got::reserve_slot): Move definition here.
	(Output_data_got::reserve_local): New function.
	(Output_data_got::reserve_global): New function.
	* reloc.cc (Sized_relobj::do_read_relocs): Replace refs to
	section_offsets_ with accessor function.
	(Sized_relobj::write_sections): Likewise.
	(Sized_relobj::do_relocate_sections): Likewise.
	* target.h (Sized_target::reserve_local_got_entry): New function.
	(Sized_target::reserve_global_got_entry): New function.
	* x86_64.cc (Target_x86_64::reserve_local_got_entry): New function.
	(Target_x86_64::reserve_global_got_entry): New function.
	(Target_x86_64::init_got_plt_for_update): Create rela_dyn section.

[-- Attachment #2: incr-patch-13.txt --]
[-- Type: text/plain, Size: 78155 bytes --]

Add incremental update support for dynamic relocations.


2011-04-04 Cary Coutant  <ccoutant@google.com>

	* incremental-dump.cc (dump_incremental_inputs): Print dynamic reloc
	info; adjust display of GOT entries.
	* incremental.cc (Sized_incremental_binary::setup_readers): Allocate
	vector of input objects; remove file_status_.
	(Sized_incremental_binary::do_reserve_layout): Remove file_status_.
	(Sized_incremental_binary::do_process_got_plt): Adjust calls to
	got_plt reader; call target hooks to reserve GOT entries.
	(Output_section_incremental_inputs::set_final_data_size): Adjust size
	of input file info header and GOT info entry.
	(Output_section_incremental_inputs::write_info_blocks): Write dynamic
	relocation info.
	(Got_plt_view_info::got_descriptor): Remove.
	(Got_plt_view_info::sym_index): New data member.
	(Got_plt_view_info::input_index): New data member.
	(Local_got_offset_visitor::visit): Write input file index.
	(Global_got_offset_visitor::visit): Write 0 for input file index.
	(Global_symbol_visitor_got_plt::operator()): Replace got_descriptor
	with sym_index and input_index.
	(Output_section_incremental_inputs::write_got_plt): Adjust size of
	incremental info GOT entry; replace got_descriptor with input_index.
	(Sized_incr_relobj::Sized_incr_relobj): Adjust initializers; record
	map from input file index to object.
	(Sized_incr_relobj::do_layout): Replace direct data member reference
	with accessor function.
	(Sized_incr_relobj::do_for_all_local_got_entries): Move to base class.
	* incremental.h (Incremental_input_entry_reader::get_symbol_offset):
	Adjust size of input file info header.
	(Incremental_input_entry_reader::get_first_dyn_reloc): New function.
	(Incremental_input_entry_reader::get_dyn_reloc_count): New function.
	(Incremental_input_entry_reader::get_input_section): Adjust size of
	input file info header.
	(Incremental_got_plt_reader::Incremental_got_plt_reader): Adjust size
	of incremental info GOT entry.
	(Incremental_got_plt_reader::get_got_desc): Remove.
	(Incremental_got_plt_reader::get_got_symndx): New function.
	(Incremental_got_plt_reader::get_got_input_index): New function.
	(Sized_incremental_binary::Sized_incremental_binary): Remove
	file_status_; add input_objects_.
	(Sized_incremental_binary::~Sized_incremental_binary): Remove.
	(Sized_incremental_binary::set_file_is_unchanged): Remove.
	(Sized_incremental_binary::file_is_unchanged): Remove.
	(Sized_incremental_binary::set_input_object): New function.
	(Sized_incremental_binary::input_object): New function.
	(Sized_incremental_binary::file_status_): Remove.
	(Sized_incremental_binary::input_objects_): New data member.
	(Sized_incr_relobj::invalid_address): Move to base class.
	(Sized_incr_relobj::is_output_section_offset_invalid): Move to base
	class.
	(Sized_incr_relobj::do_output_section_offset): Likewise.
	(Sized_incr_relobj::do_for_all_local_got_entries): Likewise.
	(Sized_incr_relobj::section_offsets_): Likewise.
	* object.cc (Sized_relobj_base::do_for_all_local_got_entries): New
	function.
	(Sized_relobj::Sized_relobj): Remove local_got_offsets_.
	(Sized_relobj::layout_section): Replace refs to section_offsets_
	with accessor function.
	(Sized_relobj::do_layout): Likewise.
	(Sized_relobj::do_layout_deferred_sections): Likewise.
	(Sized_relobj::do_for_all_local_got_entries): Move to base class.
	(Sized_relobj::compute_final_local_value): Replace refs to
	section_offsets_ with accessor function.
	(Sized_relobj::do_finalize_local_symbols): Likewise.
	* object.h (Relobj::Relobj): Initialize new data members.
	(Relobj::add_dyn_reloc): New function.
	(Relobj::first_dyn_reloc): New function.
	(Relobj::dyn_reloc_count): New function.
	(Relobj::first_dyn_reloc_): New data member.
	(Relobj::dyn_reloc_count_): New data member.
	(Sized_relobj_base::Address): New typedef.
	(Sized_relobj_base::invalid_address): Move here from child class.
	(Sized_relobj_base::Sized_relobj_base): Initialize new data members.
	(Sized_relobj_base::sized_relobj): New function.
	(Sized_relobj_base::is_output_section_offset_invalid): Move here from
	child class.
	(Sized_relobj_base::get_output_section_offset): Likewise.
	(Sized_relobj_base::local_has_got_offset): Likewise.
	(Sized_relobj_base::local_got_offset): Likewise.
	(Sized_relobj_base::set_local_got_offset): Likewise.
	(Sized_relobj_base::do_for_all_local_got_entries): Likewise.
	(Sized_relobj_base::clear_got_offsets): New function.
	(Sized_relobj_base::section_offsets): Move here from child class.
	(Sized_relobj_base::do_output_section_offset): Likewise.
	(Sized_relobj_base::do_set_section_offset): Likewise.
	(Sized_relobj_base::Local_got_offsets): Likewise.
	(Sized_relobj_base::local_got_offsets_): Likewise.
	(Sized_relobj_base::section_offsets_): Likewise.
	(Sized_relobj::is_output_section_offset_invalid): Move to base class.
	(Sized_relobj::sized_relobj): New function
	(Sized_relobj::local_has_got_offset): Move to base class.
	(Sized_relobj::local_got_offset): Likewise.
	(Sized_relobj::set_local_got_offset): Likewise.
	(Sized_relobj::get_output_section_offset): Likewise.
	(Sized_relobj::do_for_all_local_got_entries): Likewise.
	(Sized_relobj::do_output_section_offset): Likewise.
	(Sized_relobj::do_set_section_offset): Likewise.
	(Sized_relobj::Local_got_offsets): Likewise.
	(Sized_relobj::local_got_offsets_): Likewise.
	(Sized_relobj::section_offsets_): Likewise.
	* output.cc (Output_reloc::Output_reloc): Adjust type of relobj
	(all constructors).
	(set_needs_dynsym_index): Convert relobj to derived class pointer.
	(Output_reloc::get_symbol_index): Likewise.
	(Output_reloc::local_section_offset): Likewise.
	(Output_reloc::get_address): Likewise.
	(Output_reloc::symbol_value): Likewise.
	(Output_data_got::reserve_slot): Move to class definition.
	(Output_data_got::reserve_local): New function.
	(Output_data_got::reserve_slot_for_global): Remove.
	(Output_data_got::reserve_global): New function.
	* output.h (Output_reloc::Output_reloc): Adjust type of relobj
	(all constructors, two instantiations).
	(Output_reloc::get_relobj): New function (two instantiations).
	(Output_reloc::u1_.relobj, Output_reloc::u2_.relobj): Adjust type.
	(Output_data_reloc_base::add): Convert relobj to derived class pointer.
	(Output_data_reloc::add_global): Adjust type of relobj.
	(Output_data_reloc::add_global_relative): Likewise.
	(Output_data_reloc::add_symbolless_global_addend): Likewise.
	(Output_data_reloc::add_local): Likewise.
	(Output_data_reloc::add_local_relative): Likewise.
	(Output_data_reloc::add_symbolless_local_addend): Likewise.
	(Output_data_reloc::add_local_section): Likewise.
	(Output_data_reloc::add_output_section): Likewise.
	(Output_data_reloc::add_absolute): Likewise.
	(Output_data_reloc::add_target_specific): Likewise.
	(Output_data_got::reserve_slot): Move definition here.
	(Output_data_got::reserve_local): New function.
	(Output_data_got::reserve_global): New function.
	* reloc.cc (Sized_relobj::do_read_relocs): Replace refs to
	section_offsets_ with accessor function.
	(Sized_relobj::write_sections): Likewise.
	(Sized_relobj::do_relocate_sections): Likewise.
	* target.h (Sized_target::reserve_local_got_entry): New function.
	(Sized_target::reserve_global_got_entry): New function.
	* x86_64.cc (Target_x86_64::reserve_local_got_entry): New function.
	(Target_x86_64::reserve_global_got_entry): New function.
	(Target_x86_64::init_got_plt_for_update): Create rela_dyn section.

diff --git a/gold/incremental-dump.cc b/gold/incremental-dump.cc
index eecf8a8..c1e2530 100644
--- a/gold/incremental-dump.cc
+++ b/gold/incremental-dump.cc
@@ -149,6 +149,10 @@ dump_incremental_inputs(const char* argv0, const char* filename,
 		 input_file.get_local_symbol_offset());
 	  printf("    Local symbol count: %d\n",
 		 input_file.get_local_symbol_count());
+	  printf("    First dynamic reloc: %d\n",
+		 input_file.get_first_dyn_reloc());
+	  printf("    Dynamic reloc count: %d\n",
+		 input_file.get_dyn_reloc_count());
 	  break;
 	case INCREMENTAL_INPUT_ARCHIVE:
 	  printf("Archive\n");
@@ -368,24 +372,26 @@ dump_incremental_inputs(const char* argv0, const char* filename,
   for (unsigned int i = 0; i < ngot; ++i)
     {
       unsigned int got_type = igot_plt.get_got_type(i);
-      unsigned int got_desc = igot_plt.get_got_desc(i);
+      unsigned int got_symndx = igot_plt.get_got_symndx(i);
+      unsigned int got_input_index = igot_plt.get_got_input_index(i);
       printf("[%d] type %02x, ", i, got_type & 0x7f);
       if ((got_type & 0x7f) == 0x7f)
 	printf("reserved");
       else if (got_type & 0x80)
 	{
-	  Entry_reader input_file = incremental_inputs.input_file(got_desc);
+	  Entry_reader input_file =
+	      incremental_inputs.input_file(got_input_index);
 	  const char* objname = input_file.filename();
-	  printf("local: %s (%d)", objname, got_desc);
+	  printf("local: %s (%d)", objname, got_symndx);
 	}
       else
 	{
-	  sym_p = symtab_view.data() + got_desc * sym_size;
+	  sym_p = symtab_view.data() + got_symndx * sym_size;
 	  elfcpp::Sym<size, big_endian> sym(sym_p);
 	  const char* symname;
 	  if (!strtab.get_c_string(sym.get_st_name(), &symname))
 	    symname = "<unknown>";
-	  printf("global %s (%d)", symname, got_desc);
+	  printf("global %s (%d)", symname, got_symndx);
 	}
       printf("\n");
     }
diff --git a/gold/incremental.cc b/gold/incremental.cc
index 0d335e0..75b738e 100644
--- a/gold/incremental.cc
+++ b/gold/incremental.cc
@@ -276,6 +276,7 @@ Sized_incremental_binary<size, big_endian>::setup_readers()
   // libraries and scripts.
   Incremental_inputs_reader<size, big_endian>& inputs = this->inputs_reader_;
   unsigned int count = inputs.input_file_count();
+  this->input_objects_.resize(count);
   this->input_entry_readers_.reserve(count);
   this->library_map_.resize(count);
   this->script_map_.resize(count);
@@ -327,10 +328,6 @@ Sized_incremental_binary<size, big_endian>::setup_readers()
   unsigned int nglobals = this->symtab_reader_.symbol_count();
   this->symbol_map_.resize(nglobals);
 
-  // Initialize the status of each input file.
-  this->file_status_ = new unsigned char[(count + 7) / 8];
-  memset(this->file_status_, 0, (count + 7) / 8);
-
   this->has_incremental_info_ = true;
 }
 
@@ -524,8 +521,6 @@ Sized_incremental_binary<size, big_endian>::do_reserve_layout(
   Input_entry_reader input_file =
       this->inputs_reader_.input_file(input_file_index);
 
-  this->set_file_is_unchanged(input_file_index);
-
   if (input_file.type() == INCREMENTAL_INPUT_SHARED_LIBRARY)
     return;
 
@@ -579,29 +574,31 @@ Sized_incremental_binary<size, big_endian>::do_process_got_plt(
 	  got->reserve_slot(i);
 	  continue;
 	}
-      unsigned int got_desc = got_plt_reader.get_got_desc(i);
+      unsigned int symndx = got_plt_reader.get_got_symndx(i);
       if (got_type & 0x80)
 	{
-	  // This is an entry for a local symbol.  GOT_DESC is the index
-	  // of the object file entry in the list of input files.  Ignore
-	  // this entry if the object file was replaced.
+	  // This is an entry for a local symbol.  Ignore this entry if
+	  // the object file was replaced.
+	  unsigned int input_index = got_plt_reader.get_got_input_index(i);
 	  gold_debug(DEBUG_INCREMENTAL,
 		     "GOT entry %d, type %02x: (local symbol)",
 		     i, got_type & 0x7f);
-	  if (this->file_is_unchanged(got_desc))
-	    got->reserve_slot(i);
+	  Sized_incr_relobj<size, big_endian>* obj =
+	      this->input_object(input_index);
+	  if (obj != NULL)
+	    target->reserve_local_got_entry(i, obj, symndx, got_type & 0x7f);
 	}
       else
 	{
 	  // This is an entry for a global symbol.  GOT_DESC is the symbol
 	  // table index.
 	  // FIXME: This should really be a fatal error (corrupt input).
-	  gold_assert(got_desc >= first_global && got_desc < symtab_count);
-	  Symbol* sym = this->global_symbol(got_desc - first_global);
+	  gold_assert(symndx >= first_global && symndx < symtab_count);
+	  Symbol* sym = this->global_symbol(symndx - first_global);
 	  gold_debug(DEBUG_INCREMENTAL,
 		     "GOT entry %d, type %02x: %s",
 		     i, got_type, sym->name());
-	  got->reserve_slot_for_global(i, sym, got_type);
+	  target->reserve_global_got_entry(i, sym, got_type);
 	}
     }
 
@@ -1146,8 +1143,8 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
 	    gold_assert(entry != NULL);
 	    (*p)->set_info_offset(info_offset);
 	    // Input section count, global symbol count, local symbol offset,
-	    // local symbol count.
-	    info_offset += 16;
+	    // local symbol count, first dynamic reloc, dynamic reloc count.
+	    info_offset += 24;
 	    // Each input section.
 	    info_offset += (entry->get_input_section_count()
 			    * (8 + 2 * sizeof_addr));
@@ -1216,7 +1213,7 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
   unsigned int plt_count = target->plt_entry_count();
   unsigned int got_plt_size = 8;  // GOT entry count, PLT entry count.
   got_plt_size = (got_plt_size + got_count + 3) & ~3;  // GOT type array.
-  got_plt_size += got_count * 4 + plt_count * 4;  // GOT array, PLT array.
+  got_plt_size += got_count * 8 + plt_count * 4;  // GOT array, PLT array.
   inputs->got_plt_section()->set_current_data_size(got_plt_size);
 }
 
@@ -1393,11 +1390,15 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
 	    unsigned int nsyms = syms->size();
 	    off_t locals_offset = relobj->local_symbol_offset();
 	    unsigned int nlocals = relobj->output_local_symbol_count();
+	    unsigned int first_dynrel = relobj->first_dyn_reloc();
+	    unsigned int ndynrel = relobj->dyn_reloc_count();
 	    Swap32::writeval(pov, nsections);
 	    Swap32::writeval(pov + 4, nsyms);
 	    Swap32::writeval(pov + 8, static_cast<unsigned int>(locals_offset));
 	    Swap32::writeval(pov + 12, nlocals);
-	    pov += 16;
+	    Swap32::writeval(pov + 16, first_dynrel);
+	    Swap32::writeval(pov + 20, ndynrel);
+	    pov += 24;
 
 	    // Build a temporary array to map input section indexes
 	    // from the original object file index to the index in the
@@ -1592,11 +1593,14 @@ struct Got_plt_view_info
   unsigned int first_plt_entry_offset;
   // Size of a PLT entry (this is a target-dependent value).
   unsigned int plt_entry_size;
-  // Value to write in the GOT descriptor array.  For global symbols,
-  // this is the global symbol table index; for local symbols, it is
-  // the offset of the input file entry in the .gnu_incremental_inputs
-  // section.
-  unsigned int got_descriptor;
+  // Symbol index to write in the GOT descriptor array.  For global symbols,
+  // this is the global symbol table index; for local symbols, it is the
+  // local symbol table index.
+  unsigned int sym_index;
+  // Input file index to write in the GOT descriptor array.  For global
+  // symbols, this is 0; for local symbols, it is the index of the input
+  // file entry in the .gnu_incremental_inputs section.
+  unsigned int input_index;
 };
 
 // Functor class for processing a GOT offset list for local symbols.
@@ -1621,8 +1625,9 @@ class Local_got_offset_visitor : public Got_offset_list::Visitor
     // high bit to flag a local symbol.
     gold_assert(got_type < 0x7f);
     this->info_.got_type_p[got_index] = got_type | 0x80;
-    unsigned char* pov = this->info_.got_desc_p + got_index * 4;
-    elfcpp::Swap<32, big_endian>::writeval(pov, this->info_.got_descriptor);
+    unsigned char* pov = this->info_.got_desc_p + got_index * 8;
+    elfcpp::Swap<32, big_endian>::writeval(pov, this->info_.sym_index);
+    elfcpp::Swap<32, big_endian>::writeval(pov + 4, this->info_.input_index);
   }
 
  private:
@@ -1652,8 +1657,9 @@ class Global_got_offset_visitor : public Got_offset_list::Visitor
     // high bit to flag a local symbol.
     gold_assert(got_type < 0x7f);
     this->info_.got_type_p[got_index] = got_type;
-    unsigned char* pov = this->info_.got_desc_p + got_index * 4;
-    elfcpp::Swap<32, big_endian>::writeval(pov, this->info_.got_descriptor);
+    unsigned char* pov = this->info_.got_desc_p + got_index * 8;
+    elfcpp::Swap<32, big_endian>::writeval(pov, this->info_.sym_index);
+    elfcpp::Swap<32, big_endian>::writeval(pov + 4, 0);
   }
 
  private:
@@ -1680,7 +1686,8 @@ class Global_symbol_visitor_got_plt
     const Got_offset_list* got_offsets = sym->got_offset_list();
     if (got_offsets != NULL)
       {
-        this->info_.got_descriptor = sym->symtab_index();
+        this->info_.sym_index = sym->symtab_index();
+        this->info_.input_index = 0;
         Got_visitor v(this->info_);
 	got_offsets->for_all_got_offsets(&v);
       }
@@ -1719,7 +1726,7 @@ Output_section_incremental_inputs<size, big_endian>::write_got_plt(
   view_info.got_type_p = pov + 8;
   view_info.got_desc_p = (view_info.got_type_p
 			  + ((view_info.got_count + 3) & ~3));
-  view_info.plt_desc_p = view_info.got_desc_p + view_info.got_count * 4;
+  view_info.plt_desc_p = view_info.got_desc_p + view_info.got_count * 8;
 
   gold_assert(pov + view_size ==
 	      view_info.plt_desc_p + view_info.plt_count * 4);
@@ -1745,7 +1752,7 @@ Output_section_incremental_inputs<size, big_endian>::write_got_plt(
       gold_assert(entry != NULL);
       const Object* obj = entry->object();
       gold_assert(obj != NULL);
-      view_info.got_descriptor = (*p)->get_file_index();
+      view_info.input_index = (*p)->get_file_index();
       Got_visitor v(view_info);
       obj->for_all_local_got_entries(&v);
     }
@@ -1769,14 +1776,14 @@ Sized_incr_relobj<size, big_endian>::Sized_incr_relobj(
     input_reader_(ibase->inputs_reader().input_file(input_file_index)),
     local_symbol_count_(0), output_local_dynsym_count_(0),
     local_symbol_index_(0), local_symbol_offset_(0), local_dynsym_offset_(0),
-    symbols_(), section_offsets_(), incr_reloc_offset_(-1U),
-    incr_reloc_count_(0), incr_reloc_output_index_(0), incr_relocs_(NULL),
-    local_symbols_()
+    symbols_(), incr_reloc_offset_(-1U), incr_reloc_count_(0),
+    incr_reloc_output_index_(0), incr_relocs_(NULL), local_symbols_()
 {
   if (this->input_reader_.is_in_system_directory())
     this->set_is_in_system_directory();
   const unsigned int shnum = this->input_reader_.get_input_section_count() + 1;
   this->set_shnum(shnum);
+  ibase->set_input_object(input_file_index, this);
 }
 
 // Read the symbols.
@@ -1802,7 +1809,7 @@ Sized_incr_relobj<size, big_endian>::do_layout(
   gold_assert(incremental_inputs != NULL);
   Output_sections& out_sections(this->output_sections());
   out_sections.resize(shnum);
-  this->section_offsets_.resize(shnum);
+  this->section_offsets().resize(shnum);
   for (unsigned int i = 1; i < shnum; i++)
     {
       typename Input_entry_reader::Input_section_info sect =
@@ -1815,7 +1822,7 @@ Sized_incr_relobj<size, big_endian>::do_layout(
       Output_section* os = this->ibase_->output_section(sect.output_shndx);
       gold_assert(os != NULL);
       out_sections[i] = os;
-      this->section_offsets_[i] = static_cast<Address>(sect.sh_offset);
+      this->section_offsets()[i] = static_cast<Address>(sect.sh_offset);
     }
 }
 
@@ -1937,17 +1944,6 @@ Sized_incr_relobj<size, big_endian>::do_for_all_global_symbols(
   // This routine is not used for incremental objects.
 }
 
-// Iterate over local symbols, calling a visitor class V for each GOT offset
-// associated with a local symbol.
-
-template<int size, bool big_endian>
-void
-Sized_incr_relobj<size, big_endian>::do_for_all_local_got_entries(
-    Got_offset_list::Visitor*) const
-{
-  // FIXME: Implement Sized_incr_relobj::do_for_all_local_got_entries.
-}
-
 // Get the size of a section.
 
 template<int size, bool big_endian>
diff --git a/gold/incremental.h b/gold/incremental.h
index 1a8efb9..c8bfd78 100644
--- a/gold/incremental.h
+++ b/gold/incremental.h
@@ -736,7 +736,7 @@ class Incremental_inputs_reader
 		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
 
       unsigned int section_count = this->get_input_section_count();
-      return (this->info_offset_ + 16
+      return (this->info_offset_ + 24
 	      + section_count * input_section_entry_size
 	      + symndx * 20);
     }
@@ -777,6 +777,26 @@ class Incremental_inputs_reader
       return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 12);
     }
 
+    // Return the index of the first dynamic relocation -- for objects only.
+    unsigned int
+    get_first_dyn_reloc() const
+    {
+      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
+		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
+
+      return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 16);
+    }
+
+    // Return the dynamic relocation count -- for objects only.
+    unsigned int
+    get_dyn_reloc_count() const
+    {
+      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
+		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
+
+      return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 20);
+    }
+
     // Return the object count -- for scripts only.
     unsigned int
     get_object_count() const
@@ -847,7 +867,7 @@ class Incremental_inputs_reader
     {
       Input_section_info info;
       const unsigned char* p = (this->inputs_->p_
-				+ this->info_offset_ + 16
+				+ this->info_offset_ + 24
 				+ n * input_section_entry_size);
       unsigned int name_offset = Swap32::readval(p);
       info.name = this->inputs_->get_string(name_offset);
@@ -865,7 +885,7 @@ class Incremental_inputs_reader
 		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
       unsigned int section_count = this->get_input_section_count();
       const unsigned char* p = (this->inputs_->p_
-				+ this->info_offset_ + 16
+				+ this->info_offset_ + 24
 				+ section_count * input_section_entry_size
 				+ n * 20);
       return Incremental_global_symbol_reader<big_endian>(p);
@@ -1064,7 +1084,7 @@ class Incremental_got_plt_reader
   {
     this->got_count_ = elfcpp::Swap<32, big_endian>::readval(p);
     this->got_desc_p_ = p + 8 + ((this->got_count_ + 3) & ~3);
-    this->plt_desc_p_ = this->got_desc_p_ + this->got_count_ * 4;
+    this->plt_desc_p_ = this->got_desc_p_ + this->got_count_ * 8;
   }
 
   // Return the GOT entry count.
@@ -1088,11 +1108,18 @@ class Incremental_got_plt_reader
     return this->p_[8 + n];
   }
 
-  // Return the GOT descriptor for GOT entry N.
+  // Return the symbol index for GOT entry N.
+  unsigned int
+  get_got_symndx(unsigned int n)
+  {
+    return elfcpp::Swap<32, big_endian>::readval(this->got_desc_p_ + n * 8);
+  }
+
+  // Return the input file index for GOT entry N.
   unsigned int
-  get_got_desc(unsigned int n)
+  get_got_input_index(unsigned int n)
   {
-    return elfcpp::Swap<32, big_endian>::readval(this->got_desc_p_ + n * 4);
+    return elfcpp::Swap<32, big_endian>::readval(this->got_desc_p_ + n * 8 + 4);
   }
 
   // Return the PLT descriptor for PLT entry N.
@@ -1358,6 +1385,9 @@ class Incremental_binary
 };
 
 template<int size, bool big_endian>
+class Sized_incr_relobj;
+
+template<int size, bool big_endian>
 class Sized_incremental_binary : public Incremental_binary
 {
  public:
@@ -1365,38 +1395,29 @@ class Sized_incremental_binary : public Incremental_binary
                            const elfcpp::Ehdr<size, big_endian>& ehdr,
                            Target* target)
     : Incremental_binary(output, target), elf_file_(this, ehdr),
-      file_status_(NULL), section_map_(), symbol_map_(), main_symtab_loc_(),
+      input_objects_(), section_map_(), symbol_map_(), main_symtab_loc_(),
       main_strtab_loc_(), has_incremental_info_(false), inputs_reader_(),
       symtab_reader_(), relocs_reader_(), got_plt_reader_(),
       input_entry_readers_()
   { this->setup_readers(); }
 
-  virtual
-  ~Sized_incremental_binary()
-  {
-    if (this->file_status_ != NULL)
-      delete[] this->file_status_;
-  }
-
   // Returns TRUE if the file contains incremental info.
   bool
   has_incremental_info() const
   { return this->has_incremental_info_; }
 
-  // Set the flag for input file N to indicate that the file is unchanged.
+  // Record a pointer to the object for input file N.
   void
-  set_file_is_unchanged(unsigned int n)
-  {
-    gold_assert(this->file_status_ != NULL);
-    this->file_status_[n / 8] |= 1U << (n % 8);
-  }
+  set_input_object(unsigned int n,
+		   Sized_incr_relobj<size, big_endian>* obj)
+  { this->input_objects_[n] = obj; }
 
-  // Returns TRUE if input file N is unchanged.
-  bool
-  file_is_unchanged(unsigned int n) const
+  // Return a pointer to the object for input file N.
+  Sized_incr_relobj<size, big_endian>*
+  input_object(unsigned int n) const
   {
-    gold_assert(this->file_status_ != NULL);
-    return (this->file_status_[n / 8] & (1U << (n % 8))) != 0;
+    gold_assert(n < this->input_objects_.size());
+    return this->input_objects_[n];
   }
 
   // Return the Output_section for section index SHNDX.
@@ -1537,10 +1558,9 @@ class Sized_incremental_binary : public Incremental_binary
   // Output as an ELF file.
   elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file_;
 
-  // Status flags for each input file.  Each bit represents one input file;
-  // 0 indicates that the file was replaced; 1 indicates that the file was
-  // unchanged.
-  unsigned char* file_status_;
+  // Vector of pointers to the input objects for the unchanged files.
+  // For replaced files, the corresponding pointer is NULL.
+  std::vector<Sized_incr_relobj<size, big_endian>*> input_objects_;
 
   // Map section index to an Output_section in the updated layout.
   std::vector<Output_section*> section_map_;
@@ -1572,32 +1592,10 @@ class Sized_incr_relobj : public Sized_relobj_base<size, big_endian>
   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
   typedef typename Sized_relobj_base<size, big_endian>::Symbols Symbols;
 
-  static const Address invalid_address = static_cast<Address>(0) - 1;
-
   Sized_incr_relobj(const std::string& name,
 		    Sized_incremental_binary<size, big_endian>* ibase,
 		    unsigned int input_file_index);
 
-  // Checks if the offset of input section SHNDX within its output
-  // section is invalid.
-  bool
-  is_output_section_offset_invalid(unsigned int shndx) const
-  { return this->section_offsets_[shndx] == invalid_address; }
-
-  // Get the offset of input section SHNDX within its output section.
-  // This is -1 if the input section requires a special mapping, such
-  // as a merge section.  The output section can be found in the
-  // output_sections_ field of the parent class Incrobj.
-  uint64_t
-  do_output_section_offset(unsigned int shndx) const
-  {
-    gold_assert(shndx < this->section_offsets_.size());
-    Address off = this->section_offsets_[shndx];
-    if (off == invalid_address)
-      return -1ULL;
-    return off;
-  }
-
  private:
   // For convenience.
   typedef Sized_incr_relobj<size, big_endian> This;
@@ -1671,11 +1669,6 @@ class Sized_incr_relobj : public Sized_relobj_base<size, big_endian>
   do_for_all_global_symbols(Read_symbols_data* sd,
 			    Library_base::Symbol_visitor_base* v);
 
-  // Iterate over local symbols, calling a visitor class V for each GOT offset
-  // associated with a local symbol.
-  void
-  do_for_all_local_got_entries(Got_offset_list::Visitor* v) const;
-
   // Get the size of a section.
   uint64_t
   do_section_size(unsigned int shndx);
@@ -1801,10 +1794,6 @@ class Sized_incr_relobj : public Sized_relobj_base<size, big_endian>
   unsigned int local_dynsym_offset_;
   // The entries in the symbol table for the external symbols.
   Symbols symbols_;
-  // For each input section, the offset of the input section in its
-  // output section.  This is INVALID_ADDRESS if the input section requires a
-  // special mapping.
-  std::vector<Address> section_offsets_;
   // The offset of the first incremental relocation for this object.
   unsigned int incr_reloc_offset_;
   // The number of incremental relocations for this object.
diff --git a/gold/object.cc b/gold/object.cc
index 104a8db..be080c2 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -372,6 +372,28 @@ Relobj::finalize_incremental_relocs(Layout* layout, bool clear_counts)
   layout->incremental_inputs()->set_reloc_count(rindex);
 }
 
+// Class Sized_relobj_base.
+
+// Iterate over local symbols, calling a visitor class V for each GOT offset
+// associated with a local symbol.
+
+template<int size, bool big_endian>
+void
+Sized_relobj_base<size, big_endian>::do_for_all_local_got_entries(
+    Got_offset_list::Visitor* v) const
+{
+  unsigned int nsyms = this->local_symbol_count();
+  for (unsigned int i = 0; i < nsyms; i++)
+    {
+      Local_got_offsets::const_iterator p = this->local_got_offsets_.find(i);
+      if (p != this->local_got_offsets_.end())
+	{
+	  const Got_offset_list* got_offsets = p->second;
+	  got_offsets->for_all_got_offsets(v);
+	}
+    }
+}
+
 // Class Sized_relobj.
 
 template<int size, bool big_endian>
@@ -391,7 +413,6 @@ Sized_relobj<size, big_endian>::Sized_relobj(
     local_symbol_offset_(0),
     local_dynsym_offset_(0),
     local_values_(),
-    local_got_offsets_(),
     local_plt_offsets_(),
     kept_comdat_sections_(),
     has_eh_frame_(false),
@@ -1001,9 +1022,9 @@ Sized_relobj<size, big_endian>::layout_section(Layout* layout,
 
   this->output_sections()[shndx] = os;
   if (offset == -1)
-    this->section_offsets_[shndx] = invalid_address;
+    this->section_offsets()[shndx] = invalid_address;
   else
-    this->section_offsets_[shndx] = convert_types<Address, off_t>(offset);
+    this->section_offsets()[shndx] = convert_types<Address, off_t>(offset);
 
   // If this section requires special handling, and if there are
   // relocs that apply to it, then we must do the special handling
@@ -1151,7 +1172,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
     }
 
   Output_sections& out_sections(this->output_sections());
-  std::vector<Address>& out_section_offsets(this->section_offsets_);
+  std::vector<Address>& out_section_offsets(this->section_offsets());
 
   if (!is_gc_pass_two)
     {
@@ -1575,7 +1596,7 @@ Sized_relobj<size, big_endian>::do_layout_deferred_sections(Layout* layout)
   // Now handle the deferred relocation sections.
 
   Output_sections& out_sections(this->output_sections());
-  std::vector<Address>& out_section_offsets(this->section_offsets_);
+  std::vector<Address>& out_section_offsets(this->section_offsets());
 
   for (deferred = this->deferred_layout_relocs_.begin();
        deferred != this->deferred_layout_relocs_.end();
@@ -1720,26 +1741,6 @@ Sized_relobj<size, big_endian>::do_for_all_global_symbols(
     }
 }
 
-// Iterate over local symbols, calling a visitor class V for each GOT offset
-// associated with a local symbol.
-
-template<int size, bool big_endian>
-void
-Sized_relobj<size, big_endian>::do_for_all_local_got_entries(
-    Got_offset_list::Visitor* v) const
-{
-  unsigned int nsyms = this->local_symbol_count();
-  for (unsigned int i = 0; i < nsyms; i++)
-    {
-      Local_got_offsets::const_iterator p = this->local_got_offsets_.find(i);
-      if (p != this->local_got_offsets_.end())
-	{
-	  const Got_offset_list* got_offsets = p->second;
-	  got_offsets->for_all_got_offsets(v);
-	}
-    }
-}
-
 // Return whether the local symbol SYMNDX has a PLT offset.
 
 template<int size, bool big_endian>
@@ -2093,7 +2094,7 @@ Sized_relobj<size, big_endian>::compute_final_local_value(
   // This is just a wrapper of compute_final_local_value_internal.
   const bool relocatable = parameters->options().relocatable();
   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());
   return this->compute_final_local_value_internal(r_sym, lv_in, lv_out,
 						  relocatable, out_sections,
 						  out_offsets, symtab);
@@ -2117,7 +2118,7 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
 
   const bool relocatable = parameters->options().relocatable();
   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());
 
   for (unsigned int i = 1; i < loccount; ++i)
     {
diff --git a/gold/object.h b/gold/object.h
index dc56136..ce3c27e 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -929,7 +929,9 @@ class Relobj : public Object
       relocs_must_follow_section_writes_(false),
       sd_(NULL),
       reloc_counts_(NULL),
-      reloc_bases_(NULL)
+      reloc_bases_(NULL),
+      first_dyn_reloc_(0),
+      dyn_reloc_count_(0)
   { }
 
   // During garbage collection, the Read_symbols_data pass for 
@@ -1022,6 +1024,25 @@ class Relobj : public Object
   set_local_dynsym_offset(off_t off)
   { return this->do_set_local_dynsym_offset(off); }
 
+  // Record a dynamic relocation against an input section from this object.
+  void
+  add_dyn_reloc(unsigned int index)
+  {
+    if (this->dyn_reloc_count_ == 0)
+      this->first_dyn_reloc_ = index;
+    ++this->dyn_reloc_count_;
+  }
+
+  // Return the index of the first dynamic relocation.
+  unsigned int
+  first_dyn_reloc() const
+  { return this->first_dyn_reloc_; }
+
+  // Return the count of dynamic relocations.
+  unsigned int
+  dyn_reloc_count() const
+  { return this->dyn_reloc_count_; }
+
   // Relocate the input sections and write out the local symbols.
   void
   relocate(const Symbol_table* symtab, const Layout* layout, Output_file* of)
@@ -1262,6 +1283,10 @@ class Relobj : public Object
   unsigned int* reloc_counts_;
   // Per-symbol base indexes of relocations, for incremental links.
   unsigned int* reloc_bases_;
+  // Index of the first dynamic relocation for this object.
+  unsigned int first_dyn_reloc_;
+  // Count of dynamic relocations for this object.
+  unsigned int dyn_reloc_count_;
 };
 
 // This class is used to handle relocations against a section symbol
@@ -1681,24 +1706,142 @@ template<int size, bool big_endian>
 class Sized_relobj_base : public Relobj
 {
  public:
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
   typedef Relobj::Symbols Symbols;
 
+  static const Address invalid_address = static_cast<Address>(0) - 1;
+
   Sized_relobj_base(const std::string& name, Input_file* input_file)
-    : Relobj(name, input_file)
+    : Relobj(name, input_file), local_got_offsets_(), section_offsets_()
   { }
 
   Sized_relobj_base(const std::string& name, Input_file* input_file,
 		    off_t offset)
-    : Relobj(name, input_file, offset)
+    : Relobj(name, input_file, offset), local_got_offsets_(), section_offsets_()
   { }
 
   ~Sized_relobj_base()
   { }
 
+  // If this is a regular object, return a pointer to the Sized_relobj object.
+  // Otherwise, return NULL.
+  virtual Sized_relobj<size, big_endian>*
+  sized_relobj()
+  { return NULL; }
+
+  const virtual Sized_relobj<size, big_endian>*
+  sized_relobj() const
+  { return NULL; }
+
+  // Checks if the offset of input section SHNDX within its output
+  // section is invalid.
+  bool
+  is_output_section_offset_invalid(unsigned int shndx) const
+  { return this->get_output_section_offset(shndx) == invalid_address; }
+
+  // Get the offset of input section SHNDX within its output section.
+  // This is -1 if the input section requires a special mapping, such
+  // as a merge section.  The output section can be found in the
+  // output_sections_ field of the parent class Relobj.
+  Address
+  get_output_section_offset(unsigned int shndx) const
+  {
+    gold_assert(shndx < this->section_offsets_.size());
+    return this->section_offsets_[shndx];
+  }
+
+  // Return whether the local symbol SYMNDX has a GOT offset.
+  // For TLS symbols, the GOT entry will hold its tp-relative offset.
+  bool
+  local_has_got_offset(unsigned int symndx, unsigned int got_type) const
+  {
+    Local_got_offsets::const_iterator p =
+        this->local_got_offsets_.find(symndx);
+    return (p != this->local_got_offsets_.end()
+            && p->second->get_offset(got_type) != -1U);
+  }
+
+  // Return the GOT offset of the local symbol SYMNDX.
+  unsigned int
+  local_got_offset(unsigned int symndx, unsigned int got_type) const
+  {
+    Local_got_offsets::const_iterator p =
+        this->local_got_offsets_.find(symndx);
+    gold_assert(p != this->local_got_offsets_.end());
+    unsigned int off = p->second->get_offset(got_type);
+    gold_assert(off != -1U);
+    return off;
+  }
+
+  // Set the GOT offset of the local symbol SYMNDX to GOT_OFFSET.
+  void
+  set_local_got_offset(unsigned int symndx, unsigned int got_type,
+                       unsigned int got_offset)
+  {
+    Local_got_offsets::const_iterator p =
+        this->local_got_offsets_.find(symndx);
+    if (p != this->local_got_offsets_.end())
+      p->second->set_offset(got_type, got_offset);
+    else
+      {
+        Got_offset_list* g = new Got_offset_list(got_type, got_offset);
+        std::pair<Local_got_offsets::iterator, bool> ins =
+            this->local_got_offsets_.insert(std::make_pair(symndx, g));
+        gold_assert(ins.second);
+      }
+  }
+
+  // Iterate over local symbols, calling a visitor class V for each GOT offset
+  // associated with a local symbol.
+  void
+  do_for_all_local_got_entries(Got_offset_list::Visitor* v) const;
+
  protected:
   typedef Relobj::Output_sections Output_sections;
 
+  // Clear the local symbol information.
+  void
+  clear_got_offsets()
+  { this->local_got_offsets_.clear(); }
+
+  // Return the vector of section offsets.
+  std::vector<Address>&
+  section_offsets()
+  { return this->section_offsets_; }
+
+  // Get the offset of a section.
+  uint64_t
+  do_output_section_offset(unsigned int shndx) const
+  {
+    Address off = this->get_output_section_offset(shndx);
+    if (off == invalid_address)
+      return -1ULL;
+    return off;
+  }
+
+  // Set the offset of a section.
+  void
+  do_set_section_offset(unsigned int shndx, uint64_t off)
+  {
+    gold_assert(shndx < this->section_offsets_.size());
+    this->section_offsets_[shndx] =
+      (off == static_cast<uint64_t>(-1)
+       ? invalid_address
+       : convert_types<Address, uint64_t>(off));
+  }
+
  private:
+  // The GOT offsets of local symbols. This map also stores GOT offsets
+  // for tp-relative offsets for TLS symbols.
+  typedef Unordered_map<unsigned int, Got_offset_list*> Local_got_offsets;
+
+  // GOT offsets for local non-TLS symbols, and tp-relative offsets
+  // for TLS symbols, indexed by symbol number.
+  Local_got_offsets local_got_offsets_;
+  // For each input section, the offset of the input section in its
+  // output section.  This is INVALID_ADDRESS if the input section requires a
+  // special mapping.
+  std::vector<Address> section_offsets_;
 };
 
 // A regular object file.  This is size and endian specific.
@@ -1728,17 +1871,20 @@ class Sized_relobj : public Sized_relobj_base<size, big_endian>
 
   ~Sized_relobj();
 
-  // Checks if the offset of input section SHNDX within its output
-  // section is invalid. 
-  bool
-  is_output_section_offset_invalid(unsigned int shndx) const
-  { return this->get_output_section_offset(shndx) == invalid_address; }
-
   // Set up the object file based on TARGET.
   void
   setup()
   { this->do_setup(); }
 
+  // Return a pointer to the Sized_relobj object.
+  Sized_relobj<size, big_endian>*
+  sized_relobj()
+  { return this; }
+
+  const Sized_relobj<size, big_endian>*
+  sized_relobj() const
+  { return this; }
+
   // Return the number of symbols.  This is only valid after
   // Object::add_symbols has been called.
   unsigned int
@@ -1818,47 +1964,6 @@ class Sized_relobj : public Sized_relobj_base<size, big_endian>
     this->local_values_[sym].set_needs_output_dynsym_entry();
   }
 
-  // Return whether the local symbol SYMNDX has a GOT offset.
-  // For TLS symbols, the GOT entry will hold its tp-relative offset.
-  bool
-  local_has_got_offset(unsigned int symndx, unsigned int got_type) const
-  {
-    Local_got_offsets::const_iterator p =
-        this->local_got_offsets_.find(symndx);
-    return (p != this->local_got_offsets_.end()
-            && p->second->get_offset(got_type) != -1U);
-  }
-
-  // Return the GOT offset of the local symbol SYMNDX.
-  unsigned int
-  local_got_offset(unsigned int symndx, unsigned int got_type) const
-  {
-    Local_got_offsets::const_iterator p =
-        this->local_got_offsets_.find(symndx);
-    gold_assert(p != this->local_got_offsets_.end());
-    unsigned int off = p->second->get_offset(got_type);
-    gold_assert(off != -1U);
-    return off;
-  }
-
-  // Set the GOT offset of the local symbol SYMNDX to GOT_OFFSET.
-  void
-  set_local_got_offset(unsigned int symndx, unsigned int got_type,
-                       unsigned int got_offset)
-  {
-    Local_got_offsets::const_iterator p =
-        this->local_got_offsets_.find(symndx);
-    if (p != this->local_got_offsets_.end())
-      p->second->set_offset(got_type, got_offset);
-    else
-      {
-        Got_offset_list* g = new Got_offset_list(got_type, got_offset);
-        std::pair<Local_got_offsets::iterator, bool> ins =
-            this->local_got_offsets_.insert(std::make_pair(symndx, g));
-        gold_assert(ins.second);
-      }
-  }
-
   // Return whether the local symbol SYMNDX has a PLT offset.
   bool
   local_has_plt_offset(unsigned int symndx) const;
@@ -1872,17 +1977,6 @@ class Sized_relobj : public Sized_relobj_base<size, big_endian>
   void
   set_local_plt_offset(unsigned int symndx, unsigned int plt_offset);
 
-  // Get the offset of input section SHNDX within its output section.
-  // This is -1 if the input section requires a special mapping, such
-  // as a merge section.  The output section can be found in the
-  // output_sections_ field of the parent class Relobj.
-  Address
-  get_output_section_offset(unsigned int shndx) const
-  {
-    gold_assert(shndx < this->section_offsets_.size());
-    return this->section_offsets_[shndx];
-  }
-
   // Return the name of the symbol that spans the given offset in the
   // specified section in this object.  This is used only for error
   // messages and is not particularly efficient.
@@ -1961,11 +2055,6 @@ class Sized_relobj : public Sized_relobj_base<size, big_endian>
   do_for_all_global_symbols(Read_symbols_data* sd,
 			    Library_base::Symbol_visitor_base* v);
 
-  // Iterate over local symbols, calling a visitor class V for each GOT offset
-  // associated with a local symbol.
-  void
-  do_for_all_local_got_entries(Got_offset_list::Visitor* v) const;
-
   // Read the relocs.
   void
   do_read_relocs(Read_relocs_data*);
@@ -2061,27 +2150,6 @@ class Sized_relobj : public Sized_relobj_base<size, big_endian>
   do_get_global_symbols() const
   { return &this->symbols_; }
 
-  // Get the offset of a section.
-  uint64_t
-  do_output_section_offset(unsigned int shndx) const
-  {
-    Address off = this->get_output_section_offset(shndx);
-    if (off == invalid_address)
-      return -1ULL;
-    return off;
-  }
-
-  // Set the offset of a section.
-  void
-  do_set_section_offset(unsigned int shndx, uint64_t off)
-  {
-    gold_assert(shndx < this->section_offsets_.size());
-    this->section_offsets_[shndx] =
-      (off == static_cast<uint64_t>(-1)
-       ? invalid_address
-       : convert_types<Address, uint64_t>(off));
-  }
-
   // Adjust a section index if necessary.
   unsigned int
   adjust_shndx(unsigned int shndx)
@@ -2369,10 +2437,6 @@ class Sized_relobj : public Sized_relobj_base<size, big_endian>
 				     const std::vector<Address>& out_offsets,
 				     const Symbol_table* symtab);
 
-  // The GOT offsets of local symbols. This map also stores GOT offsets
-  // for tp-relative offsets for TLS symbols.
-  typedef Unordered_map<unsigned int, Got_offset_list*> Local_got_offsets;
-
   // The PLT offsets of local symbols.
   typedef Unordered_map<unsigned int, unsigned int> Local_plt_offsets;
 
@@ -2416,15 +2480,8 @@ class Sized_relobj : public Sized_relobj_base<size, big_endian>
   off_t local_dynsym_offset_;
   // Values of local symbols.
   Local_values local_values_;
-  // GOT offsets for local non-TLS symbols, and tp-relative offsets
-  // for TLS symbols, indexed by symbol number.
-  Local_got_offsets local_got_offsets_;
   // PLT offsets for local symbols.
   Local_plt_offsets local_plt_offsets_;
-  // For each input section, the offset of the input section in its
-  // output section.  This is INVALID_ADDRESS if the input section requires a
-  // special mapping.
-  std::vector<Address> section_offsets_;
   // Table mapping discarded comdat sections to corresponding kept sections.
   Kept_comdat_section_table kept_comdat_sections_;
   // Whether this object has a GNU style .eh_frame section.
diff --git a/gold/output.cc b/gold/output.cc
index d77325d..f66d471 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -657,7 +657,7 @@ template<bool dynamic, int size, bool big_endian>
 Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Symbol* gsym,
     unsigned int type,
-    Sized_relobj<size, big_endian>* relobj,
+    Sized_relobj_base<size, big_endian>* relobj,
     unsigned int shndx,
     Address address,
     bool is_relative,
@@ -679,7 +679,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
 
 template<bool dynamic, int size, bool big_endian>
 Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
-    Sized_relobj<size, big_endian>* relobj,
+    Sized_relobj_base<size, big_endian>* relobj,
     unsigned int local_sym_index,
     unsigned int type,
     Output_data* od,
@@ -703,7 +703,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
 
 template<bool dynamic, int size, bool big_endian>
 Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
-    Sized_relobj<size, big_endian>* relobj,
+    Sized_relobj_base<size, big_endian>* relobj,
     unsigned int local_sym_index,
     unsigned int type,
     unsigned int shndx,
@@ -752,7 +752,7 @@ template<bool dynamic, int size, bool big_endian>
 Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Output_section* os,
     unsigned int type,
-    Sized_relobj<size, big_endian>* relobj,
+    Sized_relobj_base<size, big_endian>* relobj,
     unsigned int shndx,
     Address address)
   : address_(address), local_sym_index_(SECTION_CODE), type_(type),
@@ -790,7 +790,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
 template<bool dynamic, int size, bool big_endian>
 Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int type,
-    Sized_relobj<size, big_endian>* relobj,
+    Sized_relobj_base<size, big_endian>* relobj,
     unsigned int shndx,
     Address address)
   : address_(address), local_sym_index_(0), type_(type),
@@ -826,7 +826,7 @@ template<bool dynamic, int size, bool big_endian>
 Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int type,
     void* arg,
-    Sized_relobj<size, big_endian>* relobj,
+    Sized_relobj_base<size, big_endian>* relobj,
     unsigned int shndx,
     Address address)
   : address_(address), local_sym_index_(TARGET_CODE), type_(type),
@@ -872,10 +872,13 @@ set_needs_dynsym_index()
     default:
       {
         const unsigned int lsi = this->local_sym_index_;
+	Sized_relobj<size, big_endian>* relobj =
+	    this->u1_.relobj->sized_relobj();
+	gold_assert(relobj != NULL);
         if (!this->is_section_symbol_)
-          this->u1_.relobj->set_needs_output_dynsym_entry(lsi);
+          relobj->set_needs_output_dynsym_entry(lsi);
         else
-          this->u1_.relobj->output_section(lsi)->set_needs_dynsym_index();
+          relobj->output_section(lsi)->set_needs_dynsym_index();
       }
       break;
     }
@@ -925,16 +928,19 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_symbol_index()
     default:
       {
         const unsigned int lsi = this->local_sym_index_;
+	Sized_relobj<size, big_endian>* relobj =
+	    this->u1_.relobj->sized_relobj();
+	gold_assert(relobj != NULL);
         if (!this->is_section_symbol_)
           {
             if (dynamic)
-              index = this->u1_.relobj->dynsym_index(lsi);
+              index = relobj->dynsym_index(lsi);
             else
-              index = this->u1_.relobj->symtab_index(lsi);
+              index = relobj->symtab_index(lsi);
           }
         else
           {
-            Output_section* os = this->u1_.relobj->output_section(lsi);
+            Output_section* os = relobj->output_section(lsi);
             gold_assert(os != NULL);
             if (dynamic)
               index = os->dynsym_index();
@@ -969,7 +975,9 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::
   if (offset != invalid_address)
     return offset + addend;
   // This is a merge section.
-  offset = os->output_address(this->u1_.relobj, lsi, addend);
+  Sized_relobj<size, big_endian>* relobj = this->u1_.relobj->sized_relobj();
+  gold_assert(relobj != NULL);
+  offset = os->output_address(relobj, lsi, addend);
   gold_assert(offset != invalid_address);
   return offset;
 }
@@ -990,8 +998,10 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_address() const
 	address += os->address() + off;
       else
 	{
-	  address = os->output_address(this->u2_.relobj, this->shndx_,
-				       address);
+	  Sized_relobj<size, big_endian>* relobj =
+	      this->u2_.relobj->sized_relobj();
+	  gold_assert(relobj != NULL);
+	  address = os->output_address(relobj, this->shndx_, address);
 	  gold_assert(address != invalid_address);
 	}
     }
@@ -1044,8 +1054,10 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value(
 	      && this->local_sym_index_ != 0
               && !this->is_section_symbol_);
   const unsigned int lsi = this->local_sym_index_;
-  const Symbol_value<size>* symval = this->u1_.relobj->local_symbol(lsi);
-  return symval->value(this->u1_.relobj, addend);
+  Sized_relobj<size, big_endian>* relobj = this->u1_.relobj->sized_relobj();
+  gold_assert(relobj != NULL);
+  const Symbol_value<size>* symval = relobj->local_symbol(lsi);
+  return symval->value(relobj, addend);
 }
 
 // Reloc comparison.  This function sorts the dynamic relocs for the
@@ -1561,21 +1573,26 @@ Output_data_got<size, big_endian>::add_local_pair_with_rela(
 
 template<int size, bool big_endian>
 void
-Output_data_got<size, big_endian>::reserve_slot(unsigned int i)
+Output_data_got<size, big_endian>::reserve_local(
+    unsigned int i,
+    Sized_relobj_base<size, big_endian>* object,
+    unsigned int sym_index,
+    unsigned int got_type)
 {
-  this->free_list_.remove(i * size / 8, (i + 1) * size / 8);
+  this->reserve_slot(i);
+  object->set_local_got_offset(sym_index, got_type, this->got_offset(i));
 }
 
 // Reserve a slot in the GOT for a global symbol.
 
 template<int size, bool big_endian>
 void
-Output_data_got<size, big_endian>::reserve_slot_for_global(
+Output_data_got<size, big_endian>::reserve_global(
     unsigned int i,
     Symbol* gsym,
     unsigned int got_type)
 {
-  this->free_list_.remove(i * size / 8, (i + 1) * size / 8);
+  this->reserve_slot(i);
   gsym->set_got_offset(got_type, this->got_offset(i));
 }
 
diff --git a/gold/output.h b/gold/output.h
index 3fc6d89..54ce4f9 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -45,6 +45,8 @@ class Target;
 template<int size, bool big_endian>
 class Sized_target;
 template<int size, bool big_endian>
+class Sized_relobj_base;
+template<int size, bool big_endian>
 class Sized_relobj;
 
 // An abtract class for data which has to go into the output file.
@@ -1024,18 +1026,18 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 	       Address address, bool is_relative, bool is_symbolless);
 
   Output_reloc(Symbol* gsym, unsigned int type,
-               Sized_relobj<size, big_endian>* relobj,
+               Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int shndx, Address address, bool is_relative,
 	       bool is_symbolless);
 
   // A reloc against a local symbol or local section symbol.
 
-  Output_reloc(Sized_relobj<size, big_endian>* relobj,
+  Output_reloc(Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int local_sym_index, unsigned int type,
 	       Output_data* od, Address address, bool is_relative,
                bool is_symbolless, bool is_section_symbol);
 
-  Output_reloc(Sized_relobj<size, big_endian>* relobj,
+  Output_reloc(Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int local_sym_index, unsigned int type,
 	       unsigned int shndx, Address address, bool is_relative,
                bool is_symbolless, bool is_section_symbol);
@@ -1046,14 +1048,14 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 	       Address address);
 
   Output_reloc(Output_section* os, unsigned int type,
-               Sized_relobj<size, big_endian>* relobj,
+               Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int shndx, Address address);
 
   // An absolute relocation with no symbol.
 
   Output_reloc(unsigned int type, Output_data* od, Address address);
 
-  Output_reloc(unsigned int type, Sized_relobj<size, big_endian>* relobj,
+  Output_reloc(unsigned int type, Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int shndx, Address address);
 
   // A target specific relocation.  The target will be called to get
@@ -1064,7 +1066,7 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 	       Address address);
 
   Output_reloc(unsigned int type, void* arg,
-	       Sized_relobj<size, big_endian>* relobj,
+	       Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int shndx, Address address);
 
   // Return the reloc type.
@@ -1119,6 +1121,16 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   Address
   symbol_value(Addend addend) const;
 
+  // If this relocation is against an input section, return the
+  // relocatable object containing the input section.
+  Sized_relobj_base<size, big_endian>*
+  get_relobj() const
+  {
+    if (this->shndx_ == INVALID_CODE)
+      return NULL;
+    return this->u2_.relobj;
+  }
+
   // Write the reloc entry to an output view.
   void
   write(unsigned char* pov) const;
@@ -1172,8 +1184,8 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
     // (this->local_sym_index_ >= 0), the object.  We will never
     // generate a relocation against a local symbol in a dynamic
     // object; that doesn't make sense.  And our callers will always
-    // be templatized, so we use Sized_relobj here.
-    Sized_relobj<size, big_endian>* relobj;
+    // be templatized, so we use Sized_relobj_base here.
+    Sized_relobj_base<size, big_endian>* relobj;
     // For a global symbol (this->local_sym_index_ == GSYM_CODE, the
     // symbol.  If this is NULL, it indicates a relocation against the
     // undefined 0 symbol.
@@ -1189,7 +1201,7 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   {
     // If this->shndx_ is not INVALID CODE, the object which holds the
     // input section being used to specify the reloc address.
-    Sized_relobj<size, big_endian>* relobj;
+    Sized_relobj_base<size, big_endian>* relobj;
     // If this->shndx_ is INVALID_CODE, the output data being used to
     // specify the reloc address.  This may be NULL if the reloc
     // address is absolute.
@@ -1245,7 +1257,7 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   { }
 
   Output_reloc(Symbol* gsym, unsigned int type,
-               Sized_relobj<size, big_endian>* relobj,
+               Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int shndx, Address address, Addend addend,
 	       bool is_relative, bool is_symbolless)
     : rel_(gsym, type, relobj, shndx, address, is_relative,
@@ -1254,7 +1266,7 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
 
   // A reloc against a local symbol.
 
-  Output_reloc(Sized_relobj<size, big_endian>* relobj,
+  Output_reloc(Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int local_sym_index, unsigned int type,
 	       Output_data* od, Address address,
 	       Addend addend, bool is_relative,
@@ -1264,7 +1276,7 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
       addend_(addend)
   { }
 
-  Output_reloc(Sized_relobj<size, big_endian>* relobj,
+  Output_reloc(Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int local_sym_index, unsigned int type,
 	       unsigned int shndx, Address address,
 	       Addend addend, bool is_relative,
@@ -1282,7 +1294,7 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   { }
 
   Output_reloc(Output_section* os, unsigned int type,
-               Sized_relobj<size, big_endian>* relobj,
+               Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int shndx, Address address, Addend addend)
     : rel_(os, type, relobj, shndx, address), addend_(addend)
   { }
@@ -1294,7 +1306,7 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
     : rel_(type, od, address), addend_(addend)
   { }
 
-  Output_reloc(unsigned int type, Sized_relobj<size, big_endian>* relobj,
+  Output_reloc(unsigned int type, Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int shndx, Address address, Addend addend)
     : rel_(type, relobj, shndx, address), addend_(addend)
   { }
@@ -1309,7 +1321,7 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   { }
 
   Output_reloc(unsigned int type, void* arg,
-	       Sized_relobj<size, big_endian>* relobj,
+	       Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int shndx, Address address, Addend addend)
     : rel_(type, arg, relobj, shndx, address), addend_(addend)
   { }
@@ -1325,6 +1337,12 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   is_symbolless() const
   { return this->rel_.is_symbolless(); }
 
+  // If this relocation is against an input section, return the
+  // relocatable object containing the input section.
+  Sized_relobj_base<size, big_endian>*
+  get_relobj() const
+  { return this->rel_.get_relobj(); }
+
   // Write the reloc entry to an output view.
   void
   write(unsigned char* pov) const;
@@ -1437,6 +1455,9 @@ class Output_data_reloc_base : public Output_data_reloc_generic
     od->add_dynamic_reloc();
     if (reloc.is_relative())
       this->bump_relative_reloc_count();
+    Sized_relobj_base<size, big_endian>* relobj = reloc.get_relobj();
+    if (relobj != NULL)
+      relobj->add_dyn_reloc(this->relocs_.size() - 1);
   }
 
  private:
@@ -1485,7 +1506,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 
   void
   add_global(Symbol* gsym, unsigned int type, Output_data* od,
-             Sized_relobj<size, big_endian>* relobj,
+             Sized_relobj_base<size, big_endian>* relobj,
 	     unsigned int shndx, Address address)
   { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
                                     false, false)); }
@@ -1502,7 +1523,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 
   void
   add_global(Symbol* gsym, unsigned int type, Output_data* od,
-             Sized_relobj<size, big_endian>* relobj,
+             Sized_relobj_base<size, big_endian>* relobj,
 	     unsigned int shndx, Address address, Address addend)
   {
     gold_assert(addend == 0);
@@ -1519,7 +1540,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 
   void
   add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
-                      Sized_relobj<size, big_endian>* relobj,
+                      Sized_relobj_base<size, big_endian>* relobj,
                       unsigned int shndx, Address address)
   {
     this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
@@ -1537,7 +1558,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   void
   add_symbolless_global_addend(Symbol* gsym, unsigned int type,
 			       Output_data* od,
-			       Sized_relobj<size, big_endian>* relobj,
+			       Sized_relobj_base<size, big_endian>* relobj,
 			       unsigned int shndx, Address address)
   {
     this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
@@ -1547,7 +1568,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   // Add a reloc against a local symbol.
 
   void
-  add_local(Sized_relobj<size, big_endian>* relobj,
+  add_local(Sized_relobj_base<size, big_endian>* relobj,
 	    unsigned int local_sym_index, unsigned int type,
 	    Output_data* od, Address address)
   {
@@ -1556,7 +1577,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   }
 
   void
-  add_local(Sized_relobj<size, big_endian>* relobj,
+  add_local(Sized_relobj_base<size, big_endian>* relobj,
 	    unsigned int local_sym_index, unsigned int type,
 	    Output_data* od, unsigned int shndx, Address address)
   {
@@ -1567,7 +1588,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   // Add a RELATIVE reloc against a local symbol.
 
   void
-  add_local_relative(Sized_relobj<size, big_endian>* relobj,
+  add_local_relative(Sized_relobj_base<size, big_endian>* relobj,
 	             unsigned int local_sym_index, unsigned int type,
 	             Output_data* od, Address address)
   {
@@ -1576,7 +1597,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   }
 
   void
-  add_local_relative(Sized_relobj<size, big_endian>* relobj,
+  add_local_relative(Sized_relobj_base<size, big_endian>* relobj,
 	             unsigned int local_sym_index, unsigned int type,
 	             Output_data* od, unsigned int shndx, Address address)
   {
@@ -1588,7 +1609,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   // but which gets its addend from a symbol.
 
   void
-  add_symbolless_local_addend(Sized_relobj<size, big_endian>* relobj,
+  add_symbolless_local_addend(Sized_relobj_base<size, big_endian>* relobj,
 			      unsigned int local_sym_index, unsigned int type,
 			      Output_data* od, Address address)
   {
@@ -1597,7 +1618,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   }
 
   void
-  add_symbolless_local_addend(Sized_relobj<size, big_endian>* relobj,
+  add_symbolless_local_addend(Sized_relobj_base<size, big_endian>* relobj,
 			      unsigned int local_sym_index, unsigned int type,
 			      Output_data* od, unsigned int shndx,
 			      Address address)
@@ -1611,7 +1632,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   // output section.
 
   void
-  add_local_section(Sized_relobj<size, big_endian>* relobj,
+  add_local_section(Sized_relobj_base<size, big_endian>* relobj,
                     unsigned int input_shndx, unsigned int type,
                     Output_data* od, Address address)
   {
@@ -1620,7 +1641,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   }
 
   void
-  add_local_section(Sized_relobj<size, big_endian>* relobj,
+  add_local_section(Sized_relobj_base<size, big_endian>* relobj,
                     unsigned int input_shndx, unsigned int type,
                     Output_data* od, unsigned int shndx, Address address)
   {
@@ -1639,7 +1660,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 
   void
   add_output_section(Output_section* os, unsigned int type, Output_data* od,
-		     Sized_relobj<size, big_endian>* relobj,
+		     Sized_relobj_base<size, big_endian>* relobj,
                      unsigned int shndx, Address address)
   { this->add(od, Output_reloc_type(os, type, relobj, shndx, address)); }
 
@@ -1651,7 +1672,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 
   void
   add_absolute(unsigned int type, Output_data* od,
-	       Sized_relobj<size, big_endian>* relobj,
+	       Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int shndx, Address address)
   { this->add(od, Output_reloc_type(type, relobj, shndx, address)); }
 
@@ -1665,7 +1686,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 
   void
   add_target_specific(unsigned int type, void* arg, Output_data* od,
-		      Sized_relobj<size, big_endian>* relobj,
+		      Sized_relobj_base<size, big_endian>* relobj,
 		      unsigned int shndx, Address address)
   { this->add(od, Output_reloc_type(type, arg, relobj, shndx, address)); }
 };
@@ -1699,7 +1720,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
 
   void
   add_global(Symbol* gsym, unsigned int type, Output_data* od,
-             Sized_relobj<size, big_endian>* relobj,
+             Sized_relobj_base<size, big_endian>* relobj,
 	     unsigned int shndx, Address address,
 	     Addend addend)
   { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
@@ -1718,7 +1739,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
 
   void
   add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
-                      Sized_relobj<size, big_endian>* relobj,
+                      Sized_relobj_base<size, big_endian>* relobj,
                       unsigned int shndx, Address address, Addend addend)
   { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
                                     addend, true, true)); }
@@ -1735,7 +1756,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   void
   add_symbolless_global_addend(Symbol* gsym, unsigned int type,
 			       Output_data* od,
-			       Sized_relobj<size, big_endian>* relobj,
+			       Sized_relobj_base<size, big_endian>* relobj,
 			       unsigned int shndx, Address address, Addend addend)
   { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
                                     addend, false, true)); }
@@ -1743,7 +1764,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   // Add a reloc against a local symbol.
 
   void
-  add_local(Sized_relobj<size, big_endian>* relobj,
+  add_local(Sized_relobj_base<size, big_endian>* relobj,
 	    unsigned int local_sym_index, unsigned int type,
 	    Output_data* od, Address address, Addend addend)
   {
@@ -1752,7 +1773,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   }
 
   void
-  add_local(Sized_relobj<size, big_endian>* relobj,
+  add_local(Sized_relobj_base<size, big_endian>* relobj,
 	    unsigned int local_sym_index, unsigned int type,
 	    Output_data* od, unsigned int shndx, Address address,
 	    Addend addend)
@@ -1764,7 +1785,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   // Add a RELATIVE reloc against a local symbol.
 
   void
-  add_local_relative(Sized_relobj<size, big_endian>* relobj,
+  add_local_relative(Sized_relobj_base<size, big_endian>* relobj,
 	             unsigned int local_sym_index, unsigned int type,
 	             Output_data* od, Address address, Addend addend)
   {
@@ -1773,7 +1794,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   }
 
   void
-  add_local_relative(Sized_relobj<size, big_endian>* relobj,
+  add_local_relative(Sized_relobj_base<size, big_endian>* relobj,
 	             unsigned int local_sym_index, unsigned int type,
 	             Output_data* od, unsigned int shndx, Address address,
 	             Addend addend)
@@ -1786,7 +1807,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   // but which gets it's addend from a symbol.
 
   void
-  add_symbolless_local_addend(Sized_relobj<size, big_endian>* relobj,
+  add_symbolless_local_addend(Sized_relobj_base<size, big_endian>* relobj,
 			      unsigned int local_sym_index, unsigned int type,
 			      Output_data* od, Address address, Addend addend)
   {
@@ -1795,7 +1816,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   }
 
   void
-  add_symbolless_local_addend(Sized_relobj<size, big_endian>* relobj,
+  add_symbolless_local_addend(Sized_relobj_base<size, big_endian>* relobj,
 			      unsigned int local_sym_index, unsigned int type,
 			      Output_data* od, unsigned int shndx,
 			      Address address, Addend addend)
@@ -1809,7 +1830,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   // output section.
 
   void
-  add_local_section(Sized_relobj<size, big_endian>* relobj,
+  add_local_section(Sized_relobj_base<size, big_endian>* relobj,
                     unsigned int input_shndx, unsigned int type,
                     Output_data* od, Address address, Addend addend)
   {
@@ -1818,7 +1839,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   }
 
   void
-  add_local_section(Sized_relobj<size, big_endian>* relobj,
+  add_local_section(Sized_relobj_base<size, big_endian>* relobj,
 	             unsigned int input_shndx, unsigned int type,
 	             Output_data* od, unsigned int shndx, Address address,
 	             Addend addend)
@@ -1836,7 +1857,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
 
   void
   add_output_section(Output_section* os, unsigned int type, Output_data* od,
-                     Sized_relobj<size, big_endian>* relobj,
+                     Sized_relobj_base<size, big_endian>* relobj,
 		     unsigned int shndx, Address address, Addend addend)
   { this->add(od, Output_reloc_type(os, type, relobj, shndx, address,
                                     addend)); }
@@ -1850,7 +1871,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
 
   void
   add_absolute(unsigned int type, Output_data* od,
-	       Sized_relobj<size, big_endian>* relobj,
+	       Sized_relobj_base<size, big_endian>* relobj,
 	       unsigned int shndx, Address address, Addend addend)
   { this->add(od, Output_reloc_type(type, relobj, shndx, address, addend)); }
 
@@ -1864,7 +1885,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
 
   void
   add_target_specific(unsigned int type, void* arg, Output_data* od,
-		      Sized_relobj<size, big_endian>* relobj,
+		      Sized_relobj_base<size, big_endian>* relobj,
 		      unsigned int shndx, Address address, Addend addend)
   {
     this->add(od, Output_reloc_type(type, arg, relobj, shndx, address,
@@ -2046,13 +2067,19 @@ class Output_data_got : public Output_section_data_build
     return got_offset;
   }
 
-  // Reserve a slot in the GOT for a local symbol or the second slot of a pair.
+  // Reserve a slot in the GOT.
+  void
+  reserve_slot(unsigned int i)
+  { this->free_list_.remove(i * size / 8, (i + 1) * size / 8); }
+
+  // Reserve a slot in the GOT for a local symbol.
   void
-  reserve_slot(unsigned int i);
+  reserve_local(unsigned int i, Sized_relobj_base<size, big_endian>* object,
+		unsigned int sym_index, unsigned int got_type);
 
   // Reserve a slot in the GOT for a global symbol.
   void
-  reserve_slot_for_global(unsigned int i, Symbol* gsym, unsigned int got_type);
+  reserve_global(unsigned int i, Symbol* gsym, unsigned int got_type);
 
  protected:
   // Write out the GOT table.
diff --git a/gold/reloc.cc b/gold/reloc.cc
index 7103572..63722c8 100644
--- a/gold/reloc.cc
+++ b/gold/reloc.cc
@@ -269,7 +269,7 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
   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,
@@ -715,7 +715,7 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs,
 {
   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;
@@ -900,7 +900,7 @@ Sized_relobj<size, big_endian>::do_relocate_sections(
     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;
diff --git a/gold/target.h b/gold/target.h
index 6b25d5f..e675204 100644
--- a/gold/target.h
+++ b/gold/target.h
@@ -44,6 +44,8 @@ namespace gold
 class Object;
 class Relobj;
 template<int size, bool big_endian>
+class Sized_relobj_base;
+template<int size, bool big_endian>
 class Sized_relobj;
 class Relocatable_relocs;
 template<int size, bool big_endian>
@@ -807,6 +809,22 @@ class Sized_target : public Target
 			  unsigned int /* plt_count */)
   { gold_unreachable(); }
 
+  // Reserve a GOT entry for a local symbol, and regenerate any
+  // necessary dynamic relocations.
+  virtual void
+  reserve_local_got_entry(unsigned int /* got_index */,
+			  Sized_relobj_base<size, big_endian>* /* obj */,
+			  unsigned int /* r_sym */,
+			  unsigned int /* got_type */)
+  { gold_unreachable(); }
+
+  // Reserve a GOT entry for a global symbol, and regenerate any
+  // necessary dynamic relocations.
+  virtual void
+  reserve_global_got_entry(unsigned int /* got_index */, Symbol* /* gsym */,
+			   unsigned int /* got_type */)
+  { gold_unreachable(); }
+
   // Register an existing PLT entry for a global symbol.
   // A target needs to implement this to support incremental linking.
 
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index c85f65c..1a54fb0 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -390,6 +390,20 @@ class Target_x86_64 : public Target_freebsd<64, false>
 			  unsigned int got_count,
 			  unsigned int plt_count);
 
+  // Reserve a GOT entry for a local symbol, and regenerate any
+  // necessary dynamic relocations.
+  void
+  reserve_local_got_entry(unsigned int got_index,
+		          Sized_relobj_base<64, false>* obj,
+			  unsigned int r_sym,
+			  unsigned int got_type);
+
+  // Reserve a GOT entry for a global symbol, and regenerate any
+  // necessary dynamic relocations.
+  void
+  reserve_global_got_entry(unsigned int got_index, Symbol* gsym,
+			   unsigned int got_type);
+
   // Register an existing PLT entry for a global symbol.
   // A target needs to implement this to support incremental linking.
   void
@@ -1261,9 +1275,101 @@ Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
   Output_section* rela_plt_os = this->plt_->rela_plt()->output_section();
   rela_plt_os->set_info_section(this->plt_->output_section());
 
+  // Create the rela_dyn section.
+  (void)this->rela_dyn_section(layout);
+
   return this->got_;
 }
 
+// Reserve a GOT entry for a local symbol, and regenerate any
+// necessary dynamic relocations.
+
+void
+Target_x86_64::reserve_local_got_entry(
+    unsigned int got_index,
+    Sized_relobj_base<64, false>* obj,
+    unsigned int r_sym,
+    unsigned int got_type)
+{
+  unsigned int got_offset = got_index * 8;
+  Reloc_section* rela_dyn = this->rela_dyn_section(NULL);
+
+  this->got_->reserve_local(got_index, obj, r_sym, got_type);
+  switch (got_type)
+    {
+    case GOT_TYPE_STANDARD:
+      if (parameters->options().output_is_position_independent())
+	rela_dyn->add_local_relative(obj, r_sym, elfcpp::R_X86_64_RELATIVE,
+				     this->got_, got_offset, 0);
+      break;
+    case GOT_TYPE_TLS_OFFSET:
+      rela_dyn->add_local(obj, r_sym, elfcpp::R_X86_64_TPOFF64,
+			  this->got_, got_offset, 0);
+      break;
+    case GOT_TYPE_TLS_PAIR:
+      this->got_->reserve_slot(got_index + 1);
+      rela_dyn->add_local(obj, r_sym, elfcpp::R_X86_64_DTPMOD64,
+			  this->got_, got_offset, 0);
+      break;
+    case GOT_TYPE_TLS_DESC:
+      gold_fatal(_("TLS_DESC not yet supported for incremental linking"));
+      // this->got_->reserve_slot(got_index + 1);
+      // rela_dyn->add_target_specific(elfcpp::R_X86_64_TLSDESC, arg,
+      //			       this->got_, got_offset, 0);
+      break;
+    default:
+      gold_unreachable();
+    }
+}
+
+// Reserve a GOT entry for a global symbol, and regenerate any
+// necessary dynamic relocations.
+
+void
+Target_x86_64::reserve_global_got_entry(unsigned int got_index, Symbol* gsym,
+					unsigned int got_type)
+{
+  unsigned int got_offset = got_index * 8;
+  Reloc_section* rela_dyn = this->rela_dyn_section(NULL);
+
+  this->got_->reserve_global(got_index, gsym, got_type);
+  switch (got_type)
+    {
+    case GOT_TYPE_STANDARD:
+      if (!gsym->final_value_is_known())
+	{
+	  if (gsym->is_from_dynobj()
+	      || gsym->is_undefined()
+	      || gsym->is_preemptible()
+	      || gsym->type() == elfcpp::STT_GNU_IFUNC)
+	    rela_dyn->add_global(gsym, elfcpp::R_X86_64_GLOB_DAT,
+				 this->got_, got_offset, 0);
+	  else
+	    rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_RELATIVE,
+					  this->got_, got_offset, 0);
+	}
+      break;
+    case GOT_TYPE_TLS_OFFSET:
+      rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_TPOFF64,
+				    this->got_, got_offset, 0);
+      break;
+    case GOT_TYPE_TLS_PAIR:
+      this->got_->reserve_slot(got_index + 1);
+      rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_DTPMOD64,
+				    this->got_, got_offset, 0);
+      rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_DTPOFF64,
+				    this->got_, got_offset + 8, 0);
+      break;
+    case GOT_TYPE_TLS_DESC:
+      this->got_->reserve_slot(got_index + 1);
+      rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_TLSDESC,
+				    this->got_, got_offset, 0);
+      break;
+    default:
+      gold_unreachable();
+    }
+}
+
 // Register an existing PLT entry for a global symbol.
 
 void

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [gold patch] Incremental 13/18: Dynamic relocations
  2011-04-04 22:33 [gold patch] Incremental 13/18: Dynamic relocations Cary Coutant
@ 2011-05-24 14:45 ` Ian Lance Taylor
  2011-05-24 18:36   ` Cary Coutant
  2011-05-24 21:44   ` Cary Coutant
  0 siblings, 2 replies; 5+ messages in thread
From: Ian Lance Taylor @ 2011-05-24 14:45 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

Cary Coutant <ccoutant@google.com> writes:

> 	* incremental-dump.cc (dump_incremental_inputs): Print dynamic reloc
> 	info; adjust display of GOT entries.
> 	* incremental.cc (Sized_incremental_binary::setup_readers): Allocate
> 	vector of input objects; remove file_status_.
> 	(Sized_incremental_binary::do_reserve_layout): Remove file_status_.
> 	(Sized_incremental_binary::do_process_got_plt): Adjust calls to
> 	got_plt reader; call target hooks to reserve GOT entries.
> 	(Output_section_incremental_inputs::set_final_data_size): Adjust size
> 	of input file info header and GOT info entry.
> 	(Output_section_incremental_inputs::write_info_blocks): Write dynamic
> 	relocation info.
> 	(Got_plt_view_info::got_descriptor): Remove.
> 	(Got_plt_view_info::sym_index): New data member.
> 	(Got_plt_view_info::input_index): New data member.
> 	(Local_got_offset_visitor::visit): Write input file index.
> 	(Global_got_offset_visitor::visit): Write 0 for input file index.
> 	(Global_symbol_visitor_got_plt::operator()): Replace got_descriptor
> 	with sym_index and input_index.
> 	(Output_section_incremental_inputs::write_got_plt): Adjust size of
> 	incremental info GOT entry; replace got_descriptor with input_index.
> 	(Sized_incr_relobj::Sized_incr_relobj): Adjust initializers; record
> 	map from input file index to object.
> 	(Sized_incr_relobj::do_layout): Replace direct data member reference
> 	with accessor function.
> 	(Sized_incr_relobj::do_for_all_local_got_entries): Move to base class.
> 	* incremental.h (Incremental_input_entry_reader::get_symbol_offset):
> 	Adjust size of input file info header.
> 	(Incremental_input_entry_reader::get_first_dyn_reloc): New function.
> 	(Incremental_input_entry_reader::get_dyn_reloc_count): New function.
> 	(Incremental_input_entry_reader::get_input_section): Adjust size of
> 	input file info header.
> 	(Incremental_got_plt_reader::Incremental_got_plt_reader): Adjust size
> 	of incremental info GOT entry.
> 	(Incremental_got_plt_reader::get_got_desc): Remove.
> 	(Incremental_got_plt_reader::get_got_symndx): New function.
> 	(Incremental_got_plt_reader::get_got_input_index): New function.
> 	(Sized_incremental_binary::Sized_incremental_binary): Remove
> 	file_status_; add input_objects_.
> 	(Sized_incremental_binary::~Sized_incremental_binary): Remove.
> 	(Sized_incremental_binary::set_file_is_unchanged): Remove.
> 	(Sized_incremental_binary::file_is_unchanged): Remove.
> 	(Sized_incremental_binary::set_input_object): New function.
> 	(Sized_incremental_binary::input_object): New function.
> 	(Sized_incremental_binary::file_status_): Remove.
> 	(Sized_incremental_binary::input_objects_): New data member.
> 	(Sized_incr_relobj::invalid_address): Move to base class.
> 	(Sized_incr_relobj::is_output_section_offset_invalid): Move to base
> 	class.
> 	(Sized_incr_relobj::do_output_section_offset): Likewise.
> 	(Sized_incr_relobj::do_for_all_local_got_entries): Likewise.
> 	(Sized_incr_relobj::section_offsets_): Likewise.
> 	* object.cc (Sized_relobj_base::do_for_all_local_got_entries): New
> 	function.
> 	(Sized_relobj::Sized_relobj): Remove local_got_offsets_.
> 	(Sized_relobj::layout_section): Replace refs to section_offsets_
> 	with accessor function.
> 	(Sized_relobj::do_layout): Likewise.
> 	(Sized_relobj::do_layout_deferred_sections): Likewise.
> 	(Sized_relobj::do_for_all_local_got_entries): Move to base class.
> 	(Sized_relobj::compute_final_local_value): Replace refs to
> 	section_offsets_ with accessor function.
> 	(Sized_relobj::do_finalize_local_symbols): Likewise.
> 	* object.h (Relobj::Relobj): Initialize new data members.
> 	(Relobj::add_dyn_reloc): New function.
> 	(Relobj::first_dyn_reloc): New function.
> 	(Relobj::dyn_reloc_count): New function.
> 	(Relobj::first_dyn_reloc_): New data member.
> 	(Relobj::dyn_reloc_count_): New data member.
> 	(Sized_relobj_base::Address): New typedef.
> 	(Sized_relobj_base::invalid_address): Move here from child class.
> 	(Sized_relobj_base::Sized_relobj_base): Initialize new data members.
> 	(Sized_relobj_base::sized_relobj): New function.
> 	(Sized_relobj_base::is_output_section_offset_invalid): Move here from
> 	child class.
> 	(Sized_relobj_base::get_output_section_offset): Likewise.
> 	(Sized_relobj_base::local_has_got_offset): Likewise.
> 	(Sized_relobj_base::local_got_offset): Likewise.
> 	(Sized_relobj_base::set_local_got_offset): Likewise.
> 	(Sized_relobj_base::do_for_all_local_got_entries): Likewise.
> 	(Sized_relobj_base::clear_got_offsets): New function.
> 	(Sized_relobj_base::section_offsets): Move here from child class.
> 	(Sized_relobj_base::do_output_section_offset): Likewise.
> 	(Sized_relobj_base::do_set_section_offset): Likewise.
> 	(Sized_relobj_base::Local_got_offsets): Likewise.
> 	(Sized_relobj_base::local_got_offsets_): Likewise.
> 	(Sized_relobj_base::section_offsets_): Likewise.
> 	(Sized_relobj::is_output_section_offset_invalid): Move to base class.
> 	(Sized_relobj::sized_relobj): New function
> 	(Sized_relobj::local_has_got_offset): Move to base class.
> 	(Sized_relobj::local_got_offset): Likewise.
> 	(Sized_relobj::set_local_got_offset): Likewise.
> 	(Sized_relobj::get_output_section_offset): Likewise.
> 	(Sized_relobj::do_for_all_local_got_entries): Likewise.
> 	(Sized_relobj::do_output_section_offset): Likewise.
> 	(Sized_relobj::do_set_section_offset): Likewise.
> 	(Sized_relobj::Local_got_offsets): Likewise.
> 	(Sized_relobj::local_got_offsets_): Likewise.
> 	(Sized_relobj::section_offsets_): Likewise.
> 	* output.cc (Output_reloc::Output_reloc): Adjust type of relobj
> 	(all constructors).
> 	(set_needs_dynsym_index): Convert relobj to derived class pointer.
> 	(Output_reloc::get_symbol_index): Likewise.
> 	(Output_reloc::local_section_offset): Likewise.
> 	(Output_reloc::get_address): Likewise.
> 	(Output_reloc::symbol_value): Likewise.
> 	(Output_data_got::reserve_slot): Move to class definition.
> 	(Output_data_got::reserve_local): New function.
> 	(Output_data_got::reserve_slot_for_global): Remove.
> 	(Output_data_got::reserve_global): New function.
> 	* output.h (Output_reloc::Output_reloc): Adjust type of relobj
> 	(all constructors, two instantiations).
> 	(Output_reloc::get_relobj): New function (two instantiations).
> 	(Output_reloc::u1_.relobj, Output_reloc::u2_.relobj): Adjust type.
> 	(Output_data_reloc_base::add): Convert relobj to derived class pointer.
> 	(Output_data_reloc::add_global): Adjust type of relobj.
> 	(Output_data_reloc::add_global_relative): Likewise.
> 	(Output_data_reloc::add_symbolless_global_addend): Likewise.
> 	(Output_data_reloc::add_local): Likewise.
> 	(Output_data_reloc::add_local_relative): Likewise.
> 	(Output_data_reloc::add_symbolless_local_addend): Likewise.
> 	(Output_data_reloc::add_local_section): Likewise.
> 	(Output_data_reloc::add_output_section): Likewise.
> 	(Output_data_reloc::add_absolute): Likewise.
> 	(Output_data_reloc::add_target_specific): Likewise.
> 	(Output_data_got::reserve_slot): Move definition here.
> 	(Output_data_got::reserve_local): New function.
> 	(Output_data_got::reserve_global): New function.
> 	* reloc.cc (Sized_relobj::do_read_relocs): Replace refs to
> 	section_offsets_ with accessor function.
> 	(Sized_relobj::write_sections): Likewise.
> 	(Sized_relobj::do_relocate_sections): Likewise.
> 	* target.h (Sized_target::reserve_local_got_entry): New function.
> 	(Sized_target::reserve_global_got_entry): New function.
> 	* x86_64.cc (Target_x86_64::reserve_local_got_entry): New function.
> 	(Target_x86_64::reserve_global_got_entry): New function.
> 	(Target_x86_64::init_got_plt_for_update): Create rela_dyn section.


> @@ -1681,24 +1706,142 @@ template<int size, bool big_endian>
>  class Sized_relobj_base : public Relobj

Sized_relobj_base is turning into a poor choice of names.  It looks the
heirarchy is now

Object
Relobj
Sized_relobj_base
Sized_relobj / Sized_incr_relobj

I don't mind having Sized_relobj_base when just a couple of things refer
to it, but it looks wrong when lots of functions use it.  The name of a
class should indicate what sort of thing it is, rather than its position
in the class heirarchy.  We should consider renaming, e.g.,
Sized_relobj_base => Sized_relobj, Sized_relobj => Sized_relobj_file,
Sized_incr_relobj => Sized_relobj_incr.  I'm open to other suggestions.

> +  // Create the rela_dyn section.
> +  (void)this->rela_dyn_section(layout);

Drop the "(void)".

This is OK with those changes.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [gold patch] Incremental 13/18: Dynamic relocations
  2011-05-24 14:45 ` Ian Lance Taylor
@ 2011-05-24 18:36   ` Cary Coutant
  2011-05-24 18:51     ` Ian Lance Taylor
  2011-05-24 21:44   ` Cary Coutant
  1 sibling, 1 reply; 5+ messages in thread
From: Cary Coutant @ 2011-05-24 18:36 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Binutils

> Sized_relobj_base is turning into a poor choice of names.  It looks the
> heirarchy is now
>
> Object
> Relobj
> Sized_relobj_base
> Sized_relobj / Sized_incr_relobj
>
> I don't mind having Sized_relobj_base when just a couple of things refer
> to it, but it looks wrong when lots of functions use it.  The name of a
> class should indicate what sort of thing it is, rather than its position
> in the class heirarchy.  We should consider renaming, e.g.,
> Sized_relobj_base => Sized_relobj, Sized_relobj => Sized_relobj_file,
> Sized_incr_relobj => Sized_relobj_incr.  I'm open to other suggestions.

Yeah, I started out with something like this, but (a) I couldn't come
up with a name I liked for Sized_relobj_file, and (b) I was trying to
avoid wholesale changes to so many other files that were otherwise
unaffected.

In the ChangeLog, should I enumerate all the files touched, or is it
better to just say "Rename x to y; change all references" in object.h?

-cary

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [gold patch] Incremental 13/18: Dynamic relocations
  2011-05-24 18:36   ` Cary Coutant
@ 2011-05-24 18:51     ` Ian Lance Taylor
  0 siblings, 0 replies; 5+ messages in thread
From: Ian Lance Taylor @ 2011-05-24 18:51 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

Cary Coutant <ccoutant@google.com> writes:

>> Sized_relobj_base is turning into a poor choice of names.  It looks the
>> heirarchy is now
>>
>> Object
>> Relobj
>> Sized_relobj_base
>> Sized_relobj / Sized_incr_relobj
>>
>> I don't mind having Sized_relobj_base when just a couple of things refer
>> to it, but it looks wrong when lots of functions use it.  The name of a
>> class should indicate what sort of thing it is, rather than its position
>> in the class heirarchy.  We should consider renaming, e.g.,
>> Sized_relobj_base => Sized_relobj, Sized_relobj => Sized_relobj_file,
>> Sized_incr_relobj => Sized_relobj_incr.  I'm open to other suggestions.
>
> Yeah, I started out with something like this, but (a) I couldn't come
> up with a name I liked for Sized_relobj_file, and (b) I was trying to
> avoid wholesale changes to so many other files that were otherwise
> unaffected.
>
> In the ChangeLog, should I enumerate all the files touched, or is it
> better to just say "Rename x to y; change all references" in object.h?

Just saying "change all references" is fine.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [gold patch] Incremental 13/18: Dynamic relocations
  2011-05-24 14:45 ` Ian Lance Taylor
  2011-05-24 18:36   ` Cary Coutant
@ 2011-05-24 21:44   ` Cary Coutant
  1 sibling, 0 replies; 5+ messages in thread
From: Cary Coutant @ 2011-05-24 21:44 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Binutils

> I don't mind having Sized_relobj_base when just a couple of things refer
> to it, but it looks wrong when lots of functions use it.  The name of a
> class should indicate what sort of thing it is, rather than its position
> in the class heirarchy.  We should consider renaming, e.g.,
> Sized_relobj_base => Sized_relobj, Sized_relobj => Sized_relobj_file,
> Sized_incr_relobj => Sized_relobj_incr.  I'm open to other suggestions.

Done.

>> +  // Create the rela_dyn section.
>> +  (void)this->rela_dyn_section(layout);
>
> Drop the "(void)".

Done.

> This is OK with those changes.

Thanks, committed.

-cary

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-05-24 21:44 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-04 22:33 [gold patch] Incremental 13/18: Dynamic relocations Cary Coutant
2011-05-24 14:45 ` Ian Lance Taylor
2011-05-24 18:36   ` Cary Coutant
2011-05-24 18:51     ` Ian Lance Taylor
2011-05-24 21:44   ` Cary Coutant

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).