diff options
author | Walter Lee <walt@tilera.com> | 2012-10-03 00:58:03 +0000 |
---|---|---|
committer | Walter Lee <walt@tilera.com> | 2012-10-03 00:58:03 +0000 |
commit | e867b64722d18cb3672b4a07ee2685d7018c220b (patch) | |
tree | 0649c5cdf406946b7272dce3593c970ecb4ceb2f /gold/tilegx.cc | |
parent | a330419054a2ec6f88c132182c673d26882ea3c9 (diff) | |
download | gdb-e867b64722d18cb3672b4a07ee2685d7018c220b.zip gdb-e867b64722d18cb3672b4a07ee2685d7018c220b.tar.gz gdb-e867b64722d18cb3672b4a07ee2685d7018c220b.tar.bz2 |
Adjust the value of _GLOBAL_OFFSET_TABLE_ for got bigger than 0x8000
bytes, so that the 16 bit relocations have a greater chance of
working.
* tilegx.cc (Target_tilegx::do_finalize_sections): Adjust
global_offset_table_ value for larget got.
(Target_tilegx::Relocate::relocate): Handle adjusted got value.
Diffstat (limited to 'gold/tilegx.cc')
-rw-r--r-- | gold/tilegx.cc | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/gold/tilegx.cc b/gold/tilegx.cc index 037bf54..a209a97 100644 --- a/gold/tilegx.cc +++ b/gold/tilegx.cc @@ -4256,6 +4256,13 @@ Target_tilegx<size, big_endian>::do_finalize_sections( { uint64_t data_size = this->got_->current_data_size(); symtab->get_sized_symbol<size>(sym)->set_symsize(data_size); + + // If the .got section is more than 0x8000 bytes, we add + // 0x8000 to the value of _GLOBAL_OFFSET_TABLE_, so that 16 + // bit relocations have a greater chance of working. + if (data_size >= 0x8000) + symtab->get_sized_symbol<size>(sym)->set_value( + symtab->get_sized_symbol<size>(sym)->value() + 0x8000); } if (parameters->doing_static_link() @@ -4347,7 +4354,10 @@ Target_tilegx<size, big_endian>::Relocate::relocate( // Get the GOT offset if needed. // For tilegx, the GOT pointer points to the start of the GOT section. bool have_got_offset = false; - unsigned int got_offset = 0; + int got_offset = 0; + int got_base = target->got_ != NULL + ? target->got_->current_data_size() >= 0x8000 ? 0x8000 : 0 + : 0; unsigned int got_type = GOT_TYPE_STANDARD; bool always_apply_relocation = false; switch (r_type) @@ -4361,13 +4371,14 @@ Target_tilegx<size, big_endian>::Relocate::relocate( if (gsym != NULL) { gold_assert(gsym->has_got_offset(got_type)); - got_offset = gsym->got_offset(got_type); + got_offset = gsym->got_offset(got_type) - got_base; } else { unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info()); gold_assert(object->local_has_got_offset(r_sym, got_type)); - got_offset = object->local_got_offset(r_sym, got_type); + got_offset = + object->local_got_offset(r_sym, got_type) - got_base; } have_got_offset = true; break; @@ -4590,12 +4601,13 @@ Target_tilegx<size, big_endian>::Relocate::relocate( if (have_got_offset) { if (gsym != NULL) { gold_assert(gsym->has_got_offset(got_type)); - got_offset = gsym->got_offset(got_type); + got_offset = gsym->got_offset(got_type) - got_base; } else { unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info()); gold_assert(object->local_has_got_offset(r_sym, got_type)); - got_offset = object->local_got_offset(r_sym, got_type); + got_offset = + object->local_got_offset(r_sym, got_type) - got_base; } } |