[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] [RFC] nios2: Fix initial PLT entry population
From: |
Marek Vasut |
Subject: |
[PATCH] [RFC] nios2: Fix initial PLT entry population |
Date: |
Thu, 26 Nov 2015 16:28:32 +0100 |
When compiling the "orc" package using OE, the following assertion triggers:
.../sysroots/x86_64-linux/usr/libexec/nios2-poky-linux/gcc/nios2-poky-linux/5.2.0/ld:
BFD (GNU Binutils) 2.25.1 assertion fail
.../work/x86_64-linux/binutils-cross-nios2/2.25.1-r0/git/bfd/elf32-nios2.c:1038
I investigated this and found out that the following condition occurs:
nios2_elf32_finish_dynamic_sections(), at line 4410 , code starting with
the condition "if (splt->size > 0) ...":
sgotplt->output_section->vma = 0x895c0
sgotplt->output_offset = 0x0
got_address = 0x895c0
splt->output_section->vma = 0x95c0
splt->output_offset = 0x0
corrected = 0x7fffc
Shortly after, the following code is executed, which triggers the assertion:
4424 nios2_elf32_install_imm16 (splt, 12, (corrected & 0xffff) + 4);
4425 nios2_elf32_install_imm16 (splt, 16, (corrected & 0xffff) + 8);
The assertion is triggered because (0x7fffc & 0xffff) + 4 == 0x10000 and
0x10000 > 0xffff .
Looking at the code which is installed as the first entry in PLT, I think
this patch might solve the issue, but I'd like to hear your feedback please.
The following 6 instructions are installed as the first entry in PLT. I am
adding comments below each instruction to explain why I think my change is
correct:
nextpc r14
r14 = PC + 4 , which is address of the movhi instruction below.
This is also why the $corrected variable was decremented by 4
in the code I think, since further down in this code, it's loading
data using the ldw instruction relative to the first instruction
of this code, which is the nextpc.
movhi r13, %hiadj(_GLOBAL_OFFSET_TABLE_)
r13 = _GLOBAL_OFFSET_TABLE_ & 0xffff0000 , top 16 bits of the GOT
offset from 0x0 .
add r13, r13, r14
r13 += r14 , calculate the current GOT position and place it into r13
ldw r14, %lo(_GLOBAL_OFFSET_TABLE_+4)(r13)
r14 = (r14 & 0xffff0000) | load_lower_16_bits_from_GOT+4();
The r14 still contains the offset of the "movhi" instruction
above and the ldw will replace the bottom 16 bits with the
value at address of GOT+4.
ldw r13, %lo(_GLOBAL_OFFSET_TABLE_+8)(r13)
r13 = (r13 & 0xffff0000) | load_lower_16_bits_from_GOT+8();
The r13 still contains the offset of the "movhi" instruction
above and the ldw will replace the bottom 16 bits with the
value at address of GOT+8.
jmp r13
Jump to address in r13.
The _GLOBAL_OFFSET_TABLE_ above is populated with the $corrected variable.
I suspect that if we don't pre-decrement the $corrected variable, but will
instead modify the load offsets in the ldw instructions, the assertion will
not trigger and the code will still be correct.
I am worried about breaking the ABI though and/or possible side-effects.
Signed-off-by: Marek Vasut <address@hidden>
---
bfd/elf32-nios2.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c
index 0105b70..0b01d57 100644
--- a/bfd/elf32-nios2.c
+++ b/bfd/elf32-nios2.c
@@ -4405,11 +4405,12 @@ nios2_elf32_finish_dynamic_sections (bfd *output_bfd,
if (info->shared)
{
bfd_vma corrected = got_address - (splt->output_section->vma
- + splt->output_offset + 4);
+ + splt->output_offset);
+
nios2_elf32_install_data (splt, nios2_so_plt0_entry, 0, 6);
nios2_elf32_install_imm16 (splt, 4, hiadj (corrected));
- nios2_elf32_install_imm16 (splt, 12, (corrected & 0xffff) + 4);
- nios2_elf32_install_imm16 (splt, 16, (corrected & 0xffff) + 8);
+ nios2_elf32_install_imm16 (splt, 12, corrected & 0xffff);
+ nios2_elf32_install_imm16 (splt, 16, corrected & 0xffff);
}
else
{
--
2.6.2
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH] [RFC] nios2: Fix initial PLT entry population,
Marek Vasut <=