Linking large Hexagon binaries (e.g. ASan runtime with >8 MiB of text) fails with R_HEX_B22_PCREL / R_HEX_PLT_B22_PCREL relocation overflow on calls to PLT entries, even though the thunk infrastructure exists and needsThunks is set. needsThunk() always used s.getVA() to compute the branch destination, even for PLT calls where the actual destination is the PLT entry. This meant the distance check used the wrong address and failed to create thunks when the PLT entry was out of B22_PCREL range. Fix by using s.getPltVA() when expr == R_PLT_PC. Also override getThunkSectionSpacing() so ThunkSections are pre-created at appropriate intervals for large binaries.
127 lines
4.6 KiB
ArmAsm
127 lines
4.6 KiB
ArmAsm
# REQUIRES: hexagon
|
|
# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-linux-musl %s -o %t.o
|
|
# RUN: ld.lld %t.o -o %t
|
|
# RUN: llvm-objdump -d %t 2>&1 | \
|
|
# RUN: FileCheck --check-prefixes=CHECK-NONPIC,CHECK %s
|
|
# RUN: llvm-mc -filetype=obj \
|
|
# RUN: -triple=hexagon-unknown-linux-musl %s -o %t.o
|
|
# RUN: ld.lld --pie %t.o -o %t
|
|
# RUN: llvm-objdump -d %t 2>&1 | \
|
|
# RUN: FileCheck --check-prefixes=CHECK-PIC,CHECK %s
|
|
|
|
## Packets with pc-relative relocations are more interesting because
|
|
## the offset must be relative to the start of the source, destination
|
|
## packets and not necessarily the instruction word containing the jump/call.
|
|
|
|
# CHECK: Disassembly of section .text:
|
|
|
|
# CHECK-NONPIC: 000200b4 <myfn_b>:
|
|
# CHECK-NONPIC: { jumpr r31 }
|
|
# CHECK-PIC: 00010150 <myfn_b>:
|
|
# CHECK-PIC: { jumpr r31 }
|
|
.globl myfn_b
|
|
.type myfn_b, @function
|
|
myfn_b:
|
|
jumpr r31
|
|
.size myfn_b, .-myfn_b
|
|
|
|
# CHECK-PIC: 00010154 <main>:
|
|
.globl main
|
|
.type main, @function
|
|
main:
|
|
{ r0 = #0
|
|
call myfn_a }
|
|
# CHECK-PIC: { call 0x101a4 <__hexagon_thunk_myfn_a_from_.text.thunk>
|
|
# CHECK-NONPIC: { call 0x20108 <__hexagon_thunk_myfn_a_from_.text.thunk>
|
|
# CHECK-NEXT: r0 = #0x0 }
|
|
call myfn_a
|
|
# CHECK-PIC: call 0x101a4 <__hexagon_thunk_myfn_a_from_.text.thunk>
|
|
# CHECK-NONPIC: call 0x20108 <__hexagon_thunk_myfn_a_from_.text.thunk>
|
|
call myfn_b
|
|
# CHECK-PIC-NEXT: call 0x10150 <myfn_b>
|
|
# CHECK-NONPIC-NEXT: call 0x200b4 <myfn_b>
|
|
|
|
{ r2 = add(r0, r1)
|
|
if (p0) call #myfn_b
|
|
if (!p0) call #myfn_a }
|
|
# CHECK-PIC-NEXT: { if (p0) call 0x10150 <myfn_b>
|
|
# CHECK-PIC-NEXT: if (!p0) call 0x101a4 <__hexagon_thunk_myfn_a_from_.text.thunk>
|
|
# CHECK-NONPIC-NEXT: { if (p0) call 0x200b4 <myfn_b>
|
|
# CHECK-NONPIC-NEXT: if (!p0) call 0x20108 <__hexagon_thunk_myfn_a_from_.text.thunk>
|
|
|
|
# CHECK-NEXT: r2 = add(r0,r1) }
|
|
|
|
{ r2 = add(r0, r1)
|
|
if (p0) call #myfn_a
|
|
if (!p0) call #myfn_a }
|
|
# CHECK-PIC-NEXT: { if (p0) call 0x101a4 <__hexagon_thunk_myfn_a_from_.text.thunk>
|
|
# CHECK-PIC-NEXT: if (!p0) call 0x101a4 <__hexagon_thunk_myfn_a_from_.text.thunk>
|
|
# CHECK-NONPIC-NEXT: { if (p0) call 0x20108 <__hexagon_thunk_myfn_a_from_.text.thunk>
|
|
# CHECK-NONPIC-NEXT: if (!p0) call 0x20108 <__hexagon_thunk_myfn_a_from_.text.thunk>
|
|
# CHECK-NEXT: r2 = add(r0,r1) }
|
|
|
|
{ r2 = add(r0, r1)
|
|
r1 = r4
|
|
r4 = r5
|
|
if (r0 == #0) jump:t #myfn_a }
|
|
# CHECK-PIC-NEXT: { if (r0==#0) jump:t 0x101a4
|
|
# CHECK-NONPIC-NEXT: { if (r0==#0) jump:t 0x20108
|
|
# CHECK-NEXT: r2 = add(r0,r1)
|
|
# CHECK-NEXT: r1 = r4; r4 = r5 }
|
|
|
|
{ r2 = add(r0, r1)
|
|
r4 = r5
|
|
if (r0 <= #0) jump:t #myfn_a
|
|
p1 = cmp.eq(r0, #0); if (p1.new) jump:nt #myfn_a }
|
|
# CHECK-NONPIC-NEXT: { if (r0<=#0) jump:t 0x20108
|
|
# CHECK-NONPIC-NEXT: p1 = cmp.eq(r0,#0x0); if (p1.new) jump:nt 0x20108 <__hexagon_thunk_myfn_a_from_.text.thunk>
|
|
# CHECK-PIC-NEXT: { if (r0<=#0) jump:t 0x101a4
|
|
# CHECK-PIC-NEXT: p1 = cmp.eq(r0,#0x0); if (p1.new) jump:nt 0x101a4 <__hexagon_thunk_myfn_a_from_.text.thunk>
|
|
# CHECK-NEXT: r2 = add(r0,r1)
|
|
# CHECK-NEXT: r4 = r5 }
|
|
|
|
{r0 = #0; jump #myfn_a}
|
|
# CHECK-PIC-NEXT: { r0 = #0x0 ; jump 0x101a4 <__hexagon_thunk_myfn_a_from_.text.thunk> }
|
|
# CHECK-NONPIC-NEXT: { r0 = #0x0 ; jump 0x20108 <__hexagon_thunk_myfn_a_from_.text.thunk> }
|
|
{r0 = #0; jump #myfn_b}
|
|
# CHECK-PIC-NEXT: { r0 = #0x0 ; jump 0x10150 <myfn_b> }
|
|
# CHECK-NONPIC-NEXT: { r0 = #0x0 ; jump 0x200b4 <myfn_b> }
|
|
jumpr r31
|
|
.size main, .-main
|
|
|
|
.section .text.foo
|
|
.skip 0x1000000
|
|
|
|
.globl myfn_a
|
|
.type myfn_a, @function
|
|
myfn_a:
|
|
{r0 = #0; jump #myfn_b}
|
|
jumpr r31
|
|
.size myfn_a, .-myfn_a
|
|
|
|
# CHECK-NONPIC: 00020108 <__hexagon_thunk_myfn_a_from_.text.thunk>:
|
|
# CHECK-NONPIC-NEXT: { immext(#0x1000000)
|
|
# CHECK-NONPIC-NEXT: jump 0x1020110 <myfn_a> }
|
|
|
|
# CHECK-PIC: 000101a4 <__hexagon_thunk_myfn_a_from_.text.thunk>:
|
|
# CHECK-PIC-NEXT: { immext(#0x1000000)
|
|
# CHECK-PIC-NEXT: r14 = add(pc,##0x100000c) }
|
|
# CHECK-PIC-NEXT: { jumpr r14 }
|
|
|
|
# CHECK-NONPIC: 01020110 <myfn_a>:
|
|
# CHECK-NONPIC-NEXT: { r0 = #0x0 ; jump 0x1020118 <__hexagon_thunk_myfn_b_from_.text.thunk> }
|
|
# CHECK-NONPIC-NEXT: { jumpr r31 }
|
|
|
|
# CHECK-NONPIC: 01020118 <__hexagon_thunk_myfn_b_from_.text.thunk>:
|
|
# CHECK-NONPIC-NEXT: { immext(#0xfeffff80)
|
|
# CHECK-NONPIC-NEXT: jump 0x200b4 <myfn_b> }
|
|
|
|
# CHECK-PIC: 010101b0 <myfn_a>:
|
|
# CHECK-PIC-NEXT: { r0 = #0x0 ; jump 0x10101b8 <__hexagon_thunk_myfn_b_from_.text.thunk> }
|
|
# CHECK-PIC-NEXT: { jumpr r31 }
|
|
|
|
# CHECK-PIC: 010101b8 <__hexagon_thunk_myfn_b_from_.text.thunk>:
|
|
# CHECK-PIC-NEXT: { immext(#0xfeffff80)
|
|
# CHECK-PIC-NEXT: r14 = add(pc,##0xfeffff98) }
|
|
# CHECK-PIC-NEXT: { jumpr r14 }
|