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 <ma...@denx.de> --- 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 _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org https://lists.gnu.org/mailman/listinfo/bug-binutils