aboutsummaryrefslogtreecommitdiff
path: root/gold/tilegx.cc
diff options
context:
space:
mode:
authorWalter Lee <walt@tilera.com>2012-10-03 00:58:03 +0000
committerWalter Lee <walt@tilera.com>2012-10-03 00:58:03 +0000
commite867b64722d18cb3672b4a07ee2685d7018c220b (patch)
tree0649c5cdf406946b7272dce3593c970ecb4ceb2f /gold/tilegx.cc
parenta330419054a2ec6f88c132182c673d26882ea3c9 (diff)
downloadgdb-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.cc22
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;
}
}