diff options
author | Doug Kwan <dougkwan@google.com> | 2009-11-09 23:16:55 +0000 |
---|---|---|
committer | Doug Kwan <dougkwan@google.com> | 2009-11-09 23:16:55 +0000 |
commit | 43d12afeb988b9f78691fb861a2027730427da2e (patch) | |
tree | ecf151d75aa53300a60eb337c4239f5946ff5487 /gold/arm.cc | |
parent | ac33a407acc5d00aa5a8617d4272b6a2ad01c480 (diff) | |
download | gdb-43d12afeb988b9f78691fb861a2027730427da2e.zip gdb-43d12afeb988b9f78691fb861a2027730427da2e.tar.gz gdb-43d12afeb988b9f78691fb861a2027730427da2e.tar.bz2 |
2009-11-10 Doug Kwan <dougkwan@google.com>
* arm.cc (Arm_relobj::do_relocate_sections): Remove options parameter
in method declaration.
(Target_arm::relocate_stub): New method declaration.
(Target_arm::default_target): Change to return a pointer instead of
a const reference.
(Reloc_stub::stub_type_for_reloc): Adjust for the change in
Target_arm::default_target.
(Arm_Relobj::do_relocate_sections): Remove options paramater in
method definition.
(Target_arm::relocate_section): Adjust view.
(Target_arm::relocate_stub): New method definition.
Diffstat (limited to 'gold/arm.cc')
-rw-r--r-- | gold/arm.cc | 107 |
1 files changed, 89 insertions, 18 deletions
diff --git a/gold/arm.cc b/gold/arm.cc index 4e6c6a1..6058637d 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -972,8 +972,7 @@ class Arm_relobj : public Sized_relobj<32, big_endian> Stringpool_template<char>*); void - do_relocate_sections(const General_options& options, - const Symbol_table* symtab, const Layout* layout, + do_relocate_sections(const Symbol_table* symtab, const Layout* layout, const unsigned char* pshdrs, typename Sized_relobj<32, big_endian>::Views* pivews); @@ -1315,13 +1314,20 @@ class Target_arm : public Sized_target<32, big_endian> bool, const unsigned char*, Arm_address, section_size_type); + // Relocate a stub. + void + relocate_stub(Reloc_stub*, const Relocate_info<32, big_endian>*, + Output_section*, unsigned char*, Arm_address, + section_size_type); + // Get the default ARM target. - static const Target_arm<big_endian>& + static Target_arm<big_endian>* default_target() { gold_assert(parameters->target().machine_code() == elfcpp::EM_ARM && parameters->target().is_big_endian() == big_endian); - return static_cast<const Target_arm<big_endian>&>(parameters->target()); + return static_cast<Target_arm<big_endian>*>( + parameters->sized_target<32, big_endian>()); } // Whether relocation type uses LSB to distinguish THUMB addresses. @@ -2388,21 +2394,21 @@ Reloc_stub::stub_type_for_reloc( bool thumb_only; if (parameters->target().is_big_endian()) { - const Target_arm<true>& big_endian_target = + const Target_arm<true>* big_endian_target = Target_arm<true>::default_target(); - may_use_blx = big_endian_target.may_use_blx(); - should_force_pic_veneer = big_endian_target.should_force_pic_veneer(); - thumb2 = big_endian_target.using_thumb2(); - thumb_only = big_endian_target.using_thumb_only(); + may_use_blx = big_endian_target->may_use_blx(); + should_force_pic_veneer = big_endian_target->should_force_pic_veneer(); + thumb2 = big_endian_target->using_thumb2(); + thumb_only = big_endian_target->using_thumb_only(); } else { - const Target_arm<false>& little_endian_target = + const Target_arm<false>* little_endian_target = Target_arm<false>::default_target(); - may_use_blx = little_endian_target.may_use_blx(); - should_force_pic_veneer = little_endian_target.should_force_pic_veneer(); - thumb2 = little_endian_target.using_thumb2(); - thumb_only = little_endian_target.using_thumb_only(); + may_use_blx = little_endian_target->may_use_blx(); + should_force_pic_veneer = little_endian_target->should_force_pic_veneer(); + thumb2 = little_endian_target->using_thumb2(); + thumb_only = little_endian_target->using_thumb_only(); } int64_t branch_offset = (int64_t)destination - location; @@ -3380,15 +3386,14 @@ Arm_relobj<big_endian>::do_count_local_symbols( template<bool big_endian> void Arm_relobj<big_endian>::do_relocate_sections( - const General_options& options, const Symbol_table* symtab, const Layout* layout, const unsigned char* pshdrs, typename Sized_relobj<32, big_endian>::Views* pviews) { // Call parent to relocate sections. - Sized_relobj<32, big_endian>::do_relocate_sections(options, symtab, layout, - pshdrs, pviews); + Sized_relobj<32, big_endian>::do_relocate_sections(symtab, layout, pshdrs, + pviews); // We do not generate stubs if doing a relocatable link. if (parameters->options().relocatable()) @@ -3401,7 +3406,6 @@ Arm_relobj<big_endian>::do_relocate_sections( Target_arm<big_endian>::default_target(); Relocate_info<32, big_endian> relinfo; - relinfo.options = &options; relinfo.symtab = symtab; relinfo.layout = layout; relinfo.object = this; @@ -4775,6 +4779,28 @@ Target_arm<big_endian>::relocate_section( typedef typename Target_arm<big_endian>::Relocate Arm_relocate; gold_assert(sh_type == elfcpp::SHT_REL); + Arm_input_section<big_endian>* arm_input_section = + this->find_arm_input_section(relinfo->object, relinfo->data_shndx); + + // This is an ARM input section and the view covers the whole output + // section. + if (arm_input_section != NULL) + { + gold_assert(needs_special_offset_handling); + Arm_address section_address = arm_input_section->address(); + section_size_type section_size = arm_input_section->data_size(); + + gold_assert((arm_input_section->address() >= address) + && ((arm_input_section->address() + + arm_input_section->data_size()) + <= (address + view_size))); + + off_t offset = section_address - address; + view += offset; + address += offset; + view_size = section_size; + } + gold::relocate_section<32, big_endian, Target_arm, elfcpp::SHT_REL, Arm_relocate>( relinfo, @@ -5614,6 +5640,51 @@ Target_arm<big_endian>::do_relax( return any_stub_table_changed; } +// Relocate a stub. + +template<bool big_endian> +void +Target_arm<big_endian>::relocate_stub( + Reloc_stub* stub, + const Relocate_info<32, big_endian>* relinfo, + Output_section* output_section, + unsigned char* view, + Arm_address address, + section_size_type view_size) +{ + Relocate relocate; + const Stub_template* stub_template = stub->stub_template(); + for (size_t i = 0; i < stub_template->reloc_count(); i++) + { + size_t reloc_insn_index = stub_template->reloc_insn_index(i); + const Insn_template* insn = &stub_template->insns()[reloc_insn_index]; + + unsigned int r_type = insn->r_type(); + section_size_type reloc_offset = stub_template->reloc_offset(i); + section_size_type reloc_size = insn->size(); + gold_assert(reloc_offset + reloc_size <= view_size); + + // This is the address of the stub destination. + Arm_address target = stub->reloc_target(i); + Symbol_value<32> symval; + symval.set_output_value(target); + + // Synthesize a fake reloc just in case. We don't have a symbol so + // we use 0. + unsigned char reloc_buffer[elfcpp::Elf_sizes<32>::rel_size]; + memset(reloc_buffer, 0, sizeof(reloc_buffer)); + elfcpp::Rel_write<32, big_endian> reloc_write(reloc_buffer); + reloc_write.put_r_offset(reloc_offset); + reloc_write.put_r_info(elfcpp::elf_r_info<32>(0, r_type)); + elfcpp::Rel<32, big_endian> rel(reloc_buffer); + + relocate.relocate(relinfo, this, output_section, + this->fake_relnum_for_stubs, rel, r_type, + NULL, &symval, view + reloc_offset, + address + reloc_offset, reloc_size); + } +} + // The selector for arm object files. template<bool big_endian> |