diff --git a/gold/ChangeLog b/gold/ChangeLog
index 7ce8b69ec30..85d503442f2 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,12 @@
+2012-08-30  Alan Modra  <amodra@gmail.com>
+
+	* output.h (Output_reloc::Output_reloc <output section>): Add
+	is_relative param.  Adjust calls.
+	(Output_reloc::add_output_section_relative): New functions.
+	* output.cc (Output_reloc::Output_reloc <output section>): Handle
+	is_relative.
+	(Output_reloc::symbol_value): Handle SECTION_CODE.
+
 2012-08-24  Sriraman Tallam  <tmsriram@google.com>
 
 	* gold.cc (queue_middle_tasks): Call layout again when unique
@@ -8,7 +17,7 @@
 	(Layout::layout): Make output section for mapping to a unique segment.
 	(Layout::insert_section_segment_map): New function.
 	(Layout::attach_allocated_section_to_segment): Make unique segment for
-	output sections marked so. 
+	output sections marked so.
 	(Layout::segment_precedes): Check for unique segments when sorting.
 	* layout.h (Layout::Unique_segment_info): New struct.
 	(Layout::Section_segment_map): New typedef.
@@ -52,7 +61,6 @@
 	(unique_segment_for_sections): New global.
 	(claim_file_hook): Call allow_unique_segment_for_sections.
 	(all_symbols_read_hook): Call unique_segment_for_sections.
-	
 
 2012-08-22  Cary Coutant  <ccoutant@google.com>
 
@@ -5546,7 +5554,7 @@
 
 2010-05-26  Rafael Espindola  <espindola@google.com>
 
-       PR 11604
+	PR 11604
 	* gold/object.cc(Sized_relobj::do_layout_deferred_sections): Avoid
 	adding sections the garbage collector removed.
 	* gold/testsuite/Makefile.am: Add test.
@@ -7300,48 +7308,48 @@
 2010-01-08  Doug Kwan  <dougkwan@google.com>
 
 	* arm.cc (Stub_table::Stub_table): Initalize cortex_a8_stubs_,
-	  prev_data_size_ and prev_addralign_.  Remove initializer for
-	  deleted data member has_been_changed_.
-	  (Stub_table::empty): Look at both reloc_stubs_ and cortex_a8_stubs_
-	  to determine if the table is empty.
-	  (Stub_table::has_been_changed, Stub_table_set_has_been_changed):
-	  Remove.
-	  (Stub_table::add_reloc_stub): Define method in class definition
-	  instead of just declaring it there.
-	  (Stub_table::add_cortex_a8_stub): New method definition.
-	  (Stub_table::update_data_size_and_addralign): Ditto.
-	  (Stub_table::finalize_stubs): Ditto.
-	  (Stub_table::apply_cortex_a8_workaround_to_address_range): Ditto.
-	  (Stub_table::do_addralign_): Return address alignment in the
-	  (Stub_table::do_reset_address_and_file_offset): Define method in
-	  class definition instead of declaring it there.  Set current data
-	  size to be the data size of the previous pass.
-	  (Stub_table::set_final_data_size): Use current data size as the
-	  final data size.
-	  (Stub_table::relocate_stub): Change parameter type of stub from
-	  Reloc_stub pointer to Stub pointer.
-	  (Stub_table::addralign_, Stub_table::has_been_changed_): Remove.
-	  (Stub_table::Cortex_a8_stub_list): New typedef.
-	  (Stub_table::cortex_a8_stubs_, Stub_table::prev_data_size_,
-	   Stub_table::prev_addralign_): New data member.
-	  (Arm_relobj::Arm_relobj): Initialize data member
-	  section_has_cortex_a8_workaround_.
-	  (Arm_relobj::section_has_cortex_a8_workaround,
-	   Arm_relobj::mark_section_for_cortex_a8_workaround): New method
-	   definitions.
-	  (Arm_relobj::section_has_cortex_a8_workaround_): New data member
-	  declarations.
-	  (Target_arm::relocate_stub): Change parameter type of stub from
-	  Reloc_stub pointer to Stub pointer.
-	  (Insn_template::size, Insn_template::alignment): Handle
-	  THUMB16_SPECIAL_TYPE.
-	  (Stub_table::remove_all_cortex_a8_stubs, Stub_table::finalize_stubs,
-	   Stub_table::update_data_size_and_addralign,
-	   Stub_table::apply_cortex_a8_workaround_to_address_range): New method
-	  definitions.
-	  (Stub_table::relocate_stubs): Handle Cortex-A8 stubs.
-	  (Stub_table::do_write): Ditto.
-	  (Target_arm::do_relax): Adjust code for changes in Stub_table.
+	prev_data_size_ and prev_addralign_.  Remove initializer for
+	deleted data member has_been_changed_.
+	(Stub_table::empty): Look at both reloc_stubs_ and cortex_a8_stubs_
+	to determine if the table is empty.
+	(Stub_table::has_been_changed, Stub_table_set_has_been_changed):
+	Remove.
+	(Stub_table::add_reloc_stub): Define method in class definition
+	instead of just declaring it there.
+	(Stub_table::add_cortex_a8_stub): New method definition.
+	(Stub_table::update_data_size_and_addralign): Ditto.
+	(Stub_table::finalize_stubs): Ditto.
+	(Stub_table::apply_cortex_a8_workaround_to_address_range): Ditto.
+	(Stub_table::do_addralign_): Return address alignment in the
+	(Stub_table::do_reset_address_and_file_offset): Define method in
+	class definition instead of declaring it there.  Set current data
+	size to be the data size of the previous pass.
+	(Stub_table::set_final_data_size): Use current data size as the
+	final data size.
+	(Stub_table::relocate_stub): Change parameter type of stub from
+	Reloc_stub pointer to Stub pointer.
+	(Stub_table::addralign_, Stub_table::has_been_changed_): Remove.
+	(Stub_table::Cortex_a8_stub_list): New typedef.
+	(Stub_table::cortex_a8_stubs_, Stub_table::prev_data_size_,
+	 Stub_table::prev_addralign_): New data member.
+	(Arm_relobj::Arm_relobj): Initialize data member
+	section_has_cortex_a8_workaround_.
+	(Arm_relobj::section_has_cortex_a8_workaround,
+	 Arm_relobj::mark_section_for_cortex_a8_workaround): New method
+	 definitions.
+	(Arm_relobj::section_has_cortex_a8_workaround_): New data member
+	declarations.
+	(Target_arm::relocate_stub): Change parameter type of stub from
+	Reloc_stub pointer to Stub pointer.
+	(Insn_template::size, Insn_template::alignment): Handle
+	THUMB16_SPECIAL_TYPE.
+	(Stub_table::remove_all_cortex_a8_stubs, Stub_table::finalize_stubs,
+	 Stub_table::update_data_size_and_addralign,
+	 Stub_table::apply_cortex_a8_workaround_to_address_range): New method
+	definitions.
+	(Stub_table::relocate_stubs): Handle Cortex-A8 stubs.
+	(Stub_table::do_write): Ditto.
+	(Target_arm::do_relax): Adjust code for changes in Stub_table.
 
 2010-01-08  Ian Lance Taylor  <iant@google.com>
 
@@ -8246,7 +8254,7 @@
 
 2009-12-01  Rafael Avila de Espindola  <espindola@google.com>
 
-       * incremental-dump.cc (main): Fix typos.
+	* incremental-dump.cc (main): Fix typos.
 
 2009-11-27  Rafael Avila de Espindola  <espindola@google.com>
 
@@ -10374,12 +10382,12 @@
 	(Incremental_inputs::sized_create_incremental_inputs_data): New method.
 	* incremental.h: New file.
 	* layout.cc (Layout::Layout): Handle new incremental_inputs_.
-       (Layout::finalize): Create incremental inputs section in
+	(Layout::finalize): Create incremental inputs section in
 	incremental builds.
-       (Layout::create_incremental_info_sections): New method.
+	(Layout::create_incremental_info_sections): New method.
 	* layout.h (Layout::incremental_inputs): New method.
-       (Layout::create_incremental_info_sections): New method.
-       (Layout::incremental_inputs_): New field.
+	(Layout::create_incremental_info_sections): New method.
+	(Layout::incremental_inputs_): New field.
 	* main.cc (main): Notify Incremental_input of the command line.
 
 2009-04-01  Ian Lance Taylor  <iant@google.com>
diff --git a/gold/output.cc b/gold/output.cc
index 2539aac8a6f..68fe573f862 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -811,9 +811,10 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Output_section* os,
     unsigned int type,
     Output_data* od,
-    Address address)
+    Address address,
+    bool is_relative)
   : address_(address), local_sym_index_(SECTION_CODE), type_(type),
-    is_relative_(false), is_symbolless_(false),
+    is_relative_(is_relative), is_symbolless_(is_relative),
     is_section_symbol_(true), use_plt_offset_(false), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -832,9 +833,10 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int type,
     Sized_relobj<size, big_endian>* relobj,
     unsigned int shndx,
-    Address address)
+    Address address,
+    bool is_relative)
   : address_(address), local_sym_index_(SECTION_CODE), type_(type),
-    is_relative_(false), is_symbolless_(false),
+    is_relative_(is_relative), is_symbolless_(is_relative),
     is_section_symbol_(true), use_plt_offset_(false), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
@@ -1134,8 +1136,12 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value(
       else
 	return sym->value() + addend;
     }
-  gold_assert(this->local_sym_index_ != SECTION_CODE
-	      && this->local_sym_index_ != TARGET_CODE
+  if (this->local_sym_index_ == SECTION_CODE)
+    {
+      gold_assert(!this->use_plt_offset_);
+      return this->u1_.os->address() + addend;
+    }
+  gold_assert(this->local_sym_index_ != TARGET_CODE
               && this->local_sym_index_ != INVALID_CODE
 	      && this->local_sym_index_ != 0
               && !this->is_section_symbol_);
diff --git a/gold/output.h b/gold/output.h
index 25a6b89a0da..98c07fccfe6 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -1046,11 +1046,11 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   // A reloc against the STT_SECTION symbol of an output section.
 
   Output_reloc(Output_section* os, unsigned int type, Output_data* od,
-	       Address address);
+	       Address address, bool is_relative);
 
   Output_reloc(Output_section* os, unsigned int type,
-               Sized_relobj<size, big_endian>* relobj,
-	       unsigned int shndx, Address address);
+	       Sized_relobj<size, big_endian>* relobj, unsigned int shndx,
+	       Address address, bool is_relative);
 
   // An absolute relocation with no symbol.
 
@@ -1296,14 +1296,15 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   // A reloc against the STT_SECTION symbol of an output section.
 
   Output_reloc(Output_section* os, unsigned int type, Output_data* od,
-	       Address address, Addend addend)
-    : rel_(os, type, od, address), addend_(addend)
+	       Address address, Addend addend, bool is_relative)
+    : rel_(os, type, od, address, is_relative), addend_(addend)
   { }
 
   Output_reloc(Output_section* os, unsigned int type,
                Sized_relobj<size, big_endian>* relobj,
-	       unsigned int shndx, Address address, Addend addend)
-    : rel_(os, type, relobj, shndx, address), addend_(addend)
+	       unsigned int shndx, Address address, Addend addend,
+	       bool is_relative)
+    : rel_(os, type, relobj, shndx, address, is_relative), addend_(addend)
   { }
 
   // An absolute relocation with no symbol.
@@ -1745,13 +1746,13 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   void
   add_output_section(Output_section* os, unsigned int type,
 		     Output_data* od, Address address)
-  { this->add(od, Output_reloc_type(os, type, od, address)); }
+  { this->add(od, Output_reloc_type(os, type, od, address, false)); }
 
   void
   add_output_section(Output_section* os, unsigned int type, Output_data* od,
 		     Sized_relobj<size, big_endian>* relobj,
                      unsigned int shndx, Address address)
-  { this->add(od, Output_reloc_type(os, type, relobj, shndx, address)); }
+  { this->add(od, Output_reloc_type(os, type, relobj, shndx, address, false)); }
 
   void
   add_output_section_generic(Output_section* os, unsigned int type,
@@ -1760,7 +1761,8 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   {
     gold_assert(addend == 0);
     this->add(od, Output_reloc_type(os, type, od,
-				    convert_types<Address, uint64_t>(address)));
+				    convert_types<Address, uint64_t>(address),
+				    false));
   }
 
   void
@@ -1773,9 +1775,24 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
     Sized_relobj<size, big_endian>* sized_relobj =
       static_cast<Sized_relobj<size, big_endian>*>(relobj);
     this->add(od, Output_reloc_type(os, type, sized_relobj, shndx,
-				    convert_types<Address, uint64_t>(address)));
+				    convert_types<Address, uint64_t>(address),
+				    false));
   }
 
+  // As above, but the reloc TYPE is relative
+
+  void
+  add_output_section_relative(Output_section* os, unsigned int type,
+			      Output_data* od, Address address)
+  { this->add(od, Output_reloc_type(os, type, od, address, true)); }
+
+  void
+  add_output_section_relative(Output_section* os, unsigned int type,
+			      Output_data* od,
+			      Sized_relobj<size, big_endian>* relobj,
+			      unsigned int shndx, Address address)
+  { this->add(od, Output_reloc_type(os, type, relobj, shndx, address, true)); }
+
   // Add an absolute relocation.
 
   void
@@ -2021,14 +2038,14 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   void
   add_output_section(Output_section* os, unsigned int type, Output_data* od,
 		     Address address, Addend addend)
-  { this->add(od, Output_reloc_type(os, type, od, address, addend)); }
+  { this->add(od, Output_reloc_type(os, type, od, address, addend, false)); }
 
   void
   add_output_section(Output_section* os, unsigned int type, Output_data* od,
                      Sized_relobj<size, big_endian>* relobj,
 		     unsigned int shndx, Address address, Addend addend)
   { this->add(od, Output_reloc_type(os, type, relobj, shndx, address,
-                                    addend)); }
+                                    addend, false)); }
 
   void
   add_output_section_generic(Output_section* os, unsigned int type,
@@ -2037,7 +2054,8 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   {
     this->add(od, Output_reloc_type(os, type, od,
 				    convert_types<Address, uint64_t>(address),
-				    convert_types<Addend, uint64_t>(addend)));
+				    convert_types<Addend, uint64_t>(addend),
+				    false));
   }
 
   void
@@ -2050,7 +2068,26 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
       static_cast<Sized_relobj<size, big_endian>*>(relobj);
     this->add(od, Output_reloc_type(os, type, sized_relobj, shndx,
 				    convert_types<Address, uint64_t>(address),
-				    convert_types<Addend, uint64_t>(addend)));
+				    convert_types<Addend, uint64_t>(addend),
+				    false));
+  }
+
+  // As above, but the reloc TYPE is relative
+
+  void
+  add_output_section_relative(Output_section* os, unsigned int type,
+			      Output_data* od, Address address, Addend addend)
+  { this->add(od, Output_reloc_type(os, type, od, address, addend, true)); }
+
+  void
+  add_output_section_relative(Output_section* os, unsigned int type,
+			      Output_data* od,
+			      Sized_relobj<size, big_endian>* relobj,
+			      unsigned int shndx, Address address,
+			      Addend addend)
+  {
+    this->add(od, Output_reloc_type(os, type, relobj, shndx,
+				    address, addend, true));
   }
 
   // Add an absolute relocation.