[Top][All Lists]

[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:
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 <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);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]