This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[committed] correct nios2 _gp address computation
- From: Sandra Loosemore <sandra at codesourcery dot com>
- To: "binutils at sourceware dot org" <binutils at sourceware dot org>
- Date: Sun, 27 Dec 2015 13:45:14 -0700
- Subject: [committed] correct nios2 _gp address computation
- Authentication-results: sourceware.org; auth=none
A month or two ago, I noticed that building a complete nios2-linux-gnu
toolchain from mainline sources was dying with GP-relative relocation
overflows in the linker. At first I thought this might have been caused
by an explosion in the size of the GOT (which the linker script locates
at the lower end of the small data area), but on further investigation
it turned out that the value of _gp used internally to determine offsets
for the relocations was being calculated incorrectly. The code has been
like that forever and I'm still rubbing my eyes that we didn't spot this
error long before now. :-(
Comparing this to MIPS and other targets that support GP-relative
addressing, I noticed that the equivalent of nios2_elf_assign_gp in
those backends does something completely different, but I couldn't get
that to work on nios2-linux-gnu (it kept complaining about _gp being
undefined instead of finding the definition in the linker script). So,
I went with the most obvious fix to the existing code. I also checked
in some cleanup of the error message formatting code that I hacked up
while tracking this down.
-Sandra
2015-12-27 Sandra Loosemore <sandra@codesourcery.com>
bfd/
* elf32-nios2.c (nios2_elf_assign_gp): Correct computation of _gp
address.
(nios2_elf32_relocate_section): Tidy code for R_NIOS2_GPREL error
messages.
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c
index 1c54320..babecf3 100644
--- a/bfd/elf32-nios2.c
+++ b/bfd/elf32-nios2.c
@@ -3086,7 +3086,15 @@ lookup:
case bfd_link_hash_defined:
case bfd_link_hash_defweak:
gp_found = TRUE;
- *pgp = lh->u.def.value;
+ {
+ asection *sym_sec = lh->u.def.section;
+ bfd_vma sym_value = lh->u.def.value;
+
+ if (sym_sec->output_section)
+ sym_value = (sym_value + sym_sec->output_offset
+ + sym_sec->output_section->vma);
+ *pgp = sym_value;
+ }
break;
case bfd_link_hash_indirect:
case bfd_link_hash_warning:
@@ -3719,7 +3727,6 @@ nios2_elf32_relocate_section (bfd *output_bfd,
struct elf32_nios2_link_hash_entry *eh;
bfd_vma relocation;
bfd_vma gp;
- bfd_vma reloc_address;
bfd_reloc_status_type r = bfd_reloc_ok;
const char *name = NULL;
int r_type;
@@ -3762,12 +3769,6 @@ nios2_elf32_relocate_section (bfd *output_bfd,
if (bfd_link_relocatable (info))
continue;
- if (sec && sec->output_section)
- reloc_address = (sec->output_section->vma + sec->output_offset
- + rel->r_offset);
- else
- reloc_address = 0;
-
if (howto)
{
switch (howto->type)
@@ -3816,6 +3817,15 @@ nios2_elf32_relocate_section (bfd *output_bfd,
/* Turns an absolute address into a gp-relative address. */
if (!nios2_elf_assign_gp (output_bfd, &gp, info))
{
+ bfd_vma reloc_address;
+
+ if (sec && sec->output_section)
+ reloc_address = (sec->output_section->vma
+ + sec->output_offset
+ + rel->r_offset);
+ else
+ reloc_address = 0;
+
format = _("global pointer relative relocation at address "
"0x%08x when _gp not defined\n");
sprintf (msgbuf, format, reloc_address);
@@ -3825,7 +3835,7 @@ nios2_elf32_relocate_section (bfd *output_bfd,
else
{
bfd_vma symbol_address = rel->r_addend + relocation;
- relocation = relocation + rel->r_addend - gp;
+ relocation = symbol_address - gp;
rel->r_addend = 0;
if (((signed) relocation < -32768
|| (signed) relocation > 32767)
@@ -3833,6 +3843,8 @@ nios2_elf32_relocate_section (bfd *output_bfd,
|| h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak))
{
+ if (h)
+ name = h->root.root.string;
format = _("Unable to reach %s (at 0x%08x) from the "
"global pointer (at 0x%08x) because the "
"offset (%d) is out of the allowed range, "
@@ -3848,7 +3860,6 @@ nios2_elf32_relocate_section (bfd *output_bfd,
rel->r_offset, relocation,
rel->r_addend);
}
-
break;
case R_NIOS2_UJMP:
r = nios2_elf32_do_ujmp_relocate (input_bfd, howto,