+ if (sh_type == elfcpp::SHT_REL)
+ this->incremental_relocs_write_reltype<elfcpp::SHT_REL>(
+ relinfo,
+ prelocs,
+ reloc_count,
+ output_section,
+ output_offset,
+ of);
+ else
+ {
+ gold_assert(sh_type == elfcpp::SHT_RELA);
+ this->incremental_relocs_write_reltype<elfcpp::SHT_RELA>(
+ relinfo,
+ prelocs,
+ reloc_count,
+ output_section,
+ output_offset,
+ of);
+ }
+}
+
+// Write the incremental relocs, templatized on the type of the
+// relocation section.
+
+template<int size, bool big_endian>
+template<int sh_type>
+void
+Sized_relobj_file<size, big_endian>::incremental_relocs_write_reltype(
+ const Relocate_info<size, big_endian>* relinfo,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ Address output_offset,
+ Output_file* of)
+{
+ typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reloc;
+ const unsigned int reloc_size =
+ Reloc_types<sh_type, size, big_endian>::reloc_size;
+ const unsigned int sizeof_addr = size / 8;
+ const unsigned int incr_reloc_size =
+ Incremental_relocs_reader<size, big_endian>::reloc_size;
+
+ unsigned int out_shndx = output_section->out_shndx();
+
+ // Get a view for the .gnu_incremental_relocs section.
+
+ Incremental_inputs* inputs = relinfo->layout->incremental_inputs();
+ gold_assert(inputs != NULL);
+ const off_t relocs_off = inputs->relocs_section()->offset();
+ const off_t relocs_size = inputs->relocs_section()->data_size();
+ unsigned char* const view = of->get_output_view(relocs_off, relocs_size);
+
+ for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
+ {
+ Reloc reloc(prelocs);
+
+ // FIXME: Some targets have a non-standard r_info field.
+ typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
+ const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
+ const unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
+
+ if (r_sym < this->local_symbol_count_)
+ continue;
+
+ // Get the new offset--the location in the output section where
+ // this relocation should be applied.
+
+ Address offset = reloc.get_r_offset();
+ if (output_offset != invalid_address)
+ offset += output_offset;
+ else
+ {
+ section_offset_type sot_offset =
+ convert_types<section_offset_type, Address>(offset);
+ section_offset_type new_sot_offset =
+ output_section->output_offset(relinfo->object,
+ relinfo->data_shndx,
+ sot_offset);
+ gold_assert(new_sot_offset != -1);
+ offset += new_sot_offset;
+ }
+
+ // Get the addend.
+ typename elfcpp::Elf_types<size>::Elf_Swxword addend;
+ if (sh_type == elfcpp::SHT_RELA)
+ addend =
+ Reloc_types<sh_type, size, big_endian>::get_reloc_addend(&reloc);
+ else
+ {
+ // FIXME: Get the addend for SHT_REL.
+ addend = 0;
+ }
+
+ // Get the index of the output relocation.
+
+ unsigned int reloc_index =
+ this->next_incremental_reloc_index(r_sym - this->local_symbol_count_);
+
+ // Write the relocation.
+
+ unsigned char* pov = view + reloc_index * incr_reloc_size;
+ elfcpp::Swap<32, big_endian>::writeval(pov, r_type);
+ elfcpp::Swap<32, big_endian>::writeval(pov + 4, out_shndx);
+ elfcpp::Swap<size, big_endian>::writeval(pov + 8, offset);
+ elfcpp::Swap<size, big_endian>::writeval(pov + 8 + sizeof_addr, addend);
+ of->write_output_view(pov - view, incr_reloc_size, view);
+ }