diff options
author | Doug Kwan <dougkwan@google.com> | 2010-09-17 23:51:42 +0000 |
---|---|---|
committer | Doug Kwan <dougkwan@google.com> | 2010-09-17 23:51:42 +0000 |
commit | bca7fb637f653f086fcf935585eb6395b3893cf6 (patch) | |
tree | 3875149227fb042bdee85b99c29c47fa431ba015 /gold/arm.cc | |
parent | eab4f823f7793e025759fb47748b4b71bb88dac9 (diff) | |
download | binutils-gdb-bca7fb637f653f086fcf935585eb6395b3893cf6.tar.gz |
2010-09-17 Doug Kwan <dougkwan@google.com>
* arm.cc (Target_arm::Relocate::relocate): Ignore symbol type and
defintion if relocation uses GOT entries of the symbol.
* testsuite/icf_safe_test.sh: Fix test.
* testsuite/icf_safe_so_test.sh: Fix test.
Diffstat (limited to 'gold/arm.cc')
-rw-r--r-- | gold/arm.cc | 71 |
1 files changed, 40 insertions, 31 deletions
diff --git a/gold/arm.cc b/gold/arm.cc index 79a96633d48..d6590f0da5b 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -8582,7 +8582,46 @@ Target_arm<big_endian>::Relocate::relocate( Arm_address thumb_bit = 0; Symbol_value<32> symval; bool is_weakly_undefined_without_plt = false; - if (relnum != Target_arm<big_endian>::fake_relnum_for_stubs) + bool have_got_offset = false; + unsigned int got_offset = 0; + + // If the relocation uses the GOT entry of a symbol instead of the symbol + // itself, we don't care about whether the symbol is defined or what kind + // of symbol it is. + if (reloc_property->uses_got_entry()) + { + // Get the GOT offset. + // The GOT pointer points to the end of the GOT section. + // We need to subtract the size of the GOT section to get + // the actual offset to use in the relocation. + // TODO: We should move GOT offset computing code in TLS relocations + // to here. + switch (r_type) + { + case elfcpp::R_ARM_GOT_BREL: + case elfcpp::R_ARM_GOT_PREL: + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD)); + got_offset = (gsym->got_offset(GOT_TYPE_STANDARD) + - target->got_size()); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, + GOT_TYPE_STANDARD)); + got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD) + - target->got_size()); + } + have_got_offset = true; + break; + + default: + break; + } + } + else if (relnum != Target_arm<big_endian>::fake_relnum_for_stubs) { if (gsym != NULL) { @@ -8651,36 +8690,6 @@ Target_arm<big_endian>::Relocate::relocate( psymval = &symval; } - // Get the GOT offset if needed. - // The GOT pointer points to the end of the GOT section. - // We need to subtract the size of the GOT section to get - // the actual offset to use in the relocation. - bool have_got_offset = false; - unsigned int got_offset = 0; - switch (r_type) - { - case elfcpp::R_ARM_GOT_BREL: - case elfcpp::R_ARM_GOT_PREL: - if (gsym != NULL) - { - gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD)); - got_offset = (gsym->got_offset(GOT_TYPE_STANDARD) - - target->got_size()); - } - else - { - unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info()); - gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD)); - got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD) - - target->got_size()); - } - have_got_offset = true; - break; - - default: - break; - } - // To look up relocation stubs, we need to pass the symbol table index of // a local symbol. unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info()); |