https://sourceware.org/bugzilla/show_bug.cgi?id=33556

            Bug ID: 33556
           Summary: [RISC-V] Incorrect relaxation for call to weak
                    absolute symbol at 0
           Product: binutils
           Version: 2.45
            Status: UNCONFIRMED
          Severity: minor
          Priority: P2
         Component: binutils
          Assignee: unassigned at sourceware dot org
          Reporter: davidegrayson at gmail dot com
  Target Milestone: ---

I found a case where the GNU linker performs an erroneous RISCV-V relaxation.
It changes the 8-byte R_RISCV_CALL_PLT into a 4-byte R_RISCV_JAL, which only
works if the relocation is within 1 MB of the target, but it should not
do that because the relocation is at address 0x10000000 and the target is 0.

This incorrect relaxation prevents the linker from producing correct code
and results in the error:

    (.text+0x0): relocation truncated to fit: R_RISCV_JAL against `*UND*'

Here is the code that reproduces this:

==== weird.asm ====

    .text
    .global _start
_start:
    .weak _foo
    call _foo
_foo = 0


==== pc64k.ld ====

MEMORY {
  ROM (r): ORIGIN = 0x10000000, LENGTH = 64K
  RAM : ORIGIN = 0x20000000, LENGTH = 64K
}
ENTRY(_start)
SECTIONS {
  .text : { *(.text .text.*) } >ROM
  .data : { *(.data .data.*) } >RAM
  .bss (NOLOAD) : { *(.bss .bss.*) } >RAM
}


==== build.sh ====

riscv64-unknown-elf-as -mabi=ilp32 -march=rv32i weird.asm -o weird.o
riscv64-unknown-elf-ld -melf32lriscv --relax --gc-sections -Tpc64k.ld weird.o
-o weird.elf

====


Several things make the bug go away:
- Changing the value of _foo to 1.
- Removing the MEMORY directives from the linker script.
- Removing the ".weak" directive.
- Removing the "_foo = 0" line, which defines _foo as an absolute symbol.

I haven't looked at the GNU linker code very much so I don't have any ideas
about why this is happening.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to