summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/binutils/bfd/sunos.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/binutils/bfd/sunos.c')
-rw-r--r--gnu/usr.bin/binutils/bfd/sunos.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/gnu/usr.bin/binutils/bfd/sunos.c b/gnu/usr.bin/binutils/bfd/sunos.c
index 30fffae663c..721314dcf75 100644
--- a/gnu/usr.bin/binutils/bfd/sunos.c
+++ b/gnu/usr.bin/binutils/bfd/sunos.c
@@ -659,6 +659,9 @@ struct sunos_link_hash_table
/* The list of dynamic objects needed by dynamic objects included in
the link. */
struct bfd_link_needed_list *needed;
+
+ /* The offset of __GLOBAL_OFFSET_TABLE_ into the .got section. */
+ bfd_vma got_base;
};
/* Routine to create an entry in an SunOS link hash table. */
@@ -721,6 +724,7 @@ sunos_link_hash_table_create (abfd)
ret->dynsymcount = 0;
ret->bucketcount = 0;
ret->needed = NULL;
+ ret->got_base = 0;
return &ret->root.root;
}
@@ -1241,6 +1245,9 @@ bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
*sneedptr = NULL;
*srulesptr = NULL;
+ if (info->relocateable)
+ return true;
+
if (output_bfd->xvec != &MY(vec))
return true;
@@ -1283,7 +1290,18 @@ bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
}
h->root.root.type = bfd_link_hash_defined;
h->root.root.u.def.section = bfd_get_section_by_name (dynobj, ".got");
- h->root.root.u.def.value = 0;
+
+ /* If the .got section is more than 0x1000 bytes, we set
+ __GLOBAL_OFFSET_TABLE_ to be 0x1000 bytes into the section,
+ so that 13 bit relocations have a greater chance of working. */
+ s = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (s != NULL);
+ if (s->_raw_size >= 0x1000)
+ h->root.root.u.def.value = 0x1000;
+ else
+ h->root.root.u.def.value = 0;
+
+ sunos_hash_table (info)->got_base = h->root.root.u.def.value;
}
/* The .dynamic section is always the same size. */
@@ -2515,7 +2533,9 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
*got_offsetp |= 1;
}
- *relocationp = sgot->vma + (*got_offsetp &~ 1);
+ *relocationp = (sgot->vma
+ + (*got_offsetp &~ 1)
+ - sunos_hash_table (info)->got_base);
/* There is nothing else to do for a base relative reloc. */
return true;