This is the mail archive of the mailing list for the binutils project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] [RFC] nios2: Fix initial PLT entry population

When compiling the "orc" package using OE, the following assertion triggers:
BFD (GNU Binutils) 2.25.1 assertion fail

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

    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 <>
Cc: Chung-Lin Tang <>
Cc: Ley Foon Tan <>
Cc: Sandra Loosemore <>
Cc: Thomas Chou <>
 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);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]