diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp --- a/lld/ELF/Arch/Hexagon.cpp +++ b/lld/ELF/Arch/Hexagon.cpp @@ -103,13 +103,13 @@ case R_HEX_LO16: return R_ABS; case R_HEX_B9_PCREL: - case R_HEX_B9_PCREL_X: case R_HEX_B13_PCREL: case R_HEX_B15_PCREL: - case R_HEX_B15_PCREL_X: case R_HEX_6_PCREL_X: case R_HEX_32_PCREL: return R_PC; + case R_HEX_B9_PCREL_X: + case R_HEX_B15_PCREL_X: case R_HEX_B22_PCREL: case R_HEX_PLT_B22_PCREL: case R_HEX_B22_PCREL_X: diff --git a/lld/test/ELF/hexagon-plt.s b/lld/test/ELF/hexagon-plt.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/hexagon-plt.s @@ -0,0 +1,102 @@ +# REQUIRES: hexagon +# RUN: echo '.globl bar, weak; .type bar,@function; .type weak,@function; bar: weak:' > %t1.s + +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %t1.s -o %t1.o +# RUN: ld.lld -shared %t1.o -soname=t1.so -o %t1.so +# RUN: llvm-mc -mno-fixup -filetype=obj -triple=hexagon-unknown-elf %s -o %t.o +# RUN: ld.lld %t.o %t1.so -z separate-code -o %t +# RUN: llvm-readelf -S -s %t | FileCheck --check-prefixes=SEC,NM %s +# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s +# RUN: llvm-readelf -x .got.plt %t | FileCheck --check-prefix=GOTPLT %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=DIS %s + +# SEC: .plt PROGBITS {{0*}}00020040 + +## A canonical PLT has a non-zero st_value. bar and weak are called but their +## addresses are not taken, so a canonical PLT is not necessary. +# NM: {{0*}}00000000 0 FUNC GLOBAL DEFAULT UND bar +# NM: {{0*}}00000000 0 FUNC WEAK DEFAULT UND weak + +## The .got.plt slots relocated by .rela.plt point to .plt +## This is required by glibc. +# RELOC: .rela.plt { +# RELOC-NEXT: 0x40078 R_HEX_JMP_SLOT bar 0x0 +# RELOC-NEXT: 0x4007C R_HEX_JMP_SLOT weak 0x0 +# RELOC-NEXT: } +# GOTPLT: section '.got.plt' +# GOTPLT-NEXT: 0x00040068 00000000 00000000 00000000 00000000 +# GOTPLT-NEXT: 0x00040078 00000000 00000000 + +# DIS: _start: +## Direct call +## Call foo directly +# DIS-NEXT: { call 0x2003c } +## Call bar via plt +# DIS-NEXT: { call 0x20060 } +## Call weak via plt +# DIS-NEXT: { call 0x20070 } +# DIS-NEXT: { immext(#0) + +## Call foo directly +# DIS-NEXT: if (p0) jump:nt 0x2003c } +# DIS-NEXT: { immext(#64) +## Call bar via plt +# DIS-NEXT: if (p0) jump:nt 0x20060 } +# DIS-NEXT: { immext(#64) +## Call weak via plt +# DIS-NEXT: if (p0) jump:nt 0x20070 } +# DIS-NEXT: { immext(#0) + +## Call foo directly +# DIS-NEXT: r0 = #0 ; jump 0x2003c } +# DIS-NEXT: { immext(#0) +## Call bar via plt +# DIS-NEXT: r0 = #0 ; jump 0x20060 } +# DIS-NEXT: { immext(#0) +## Call weak via plt +# DIS-NEXT: r0 = #0 ; jump 0x20070 } + +# DIS: foo: +# DIS-NEXT: 2003c: + + +# DIS: Disassembly of section .plt: + +# DIS: 00020040 .plt: +# DIS-NEXT: 20040: { immext(#131072) +# DIS-NEXT: 20044: r28 = add(pc,##131112) } +# DIS-NEXT: 20048: { r14 -= add(r28,#16) +# DIS-NEXT: 2004c: r15 = memw(r28+#8) +# DIS-NEXT: 20050: r28 = memw(r28+#4) } +# DIS-NEXT: 20054: { r14 = asr(r14,#2) +# DIS-NEXT: 20058: jumpr r28 } +# DIS-NEXT: 2005c: { trap0(#219) } +## bar's plt slot +# DIS-NEXT: 20060: { immext(#131072) +# DIS-NEXT: 20064: r14 = add(pc,##131096) } +# DIS-NEXT: 20068: { r28 = memw(r14+#0) } +# DIS-NEXT: 2006c: { jumpr r28 } +## weak's plt slot +# DIS-NEXT: 20070: { immext(#131072) +# DIS-NEXT: 20074: r14 = add(pc,##131084) } +# DIS-NEXT: 20078: { r28 = memw(r14+#0) } +# DIS-NEXT: 2007c: { jumpr r28 } + + +.global _start, foo, bar +.weak weak + +_start: + call foo + call bar + call weak + if (p0) jump foo + if (p0) jump bar + if (p0) jump weak + { r0 = #0; jump foo } + { r0 = #0; jump bar } + { r0 = #0; jump weak } + +## foo is local and non-preemptale, no PLT is generated. +foo: + jumpr r31 diff --git a/lld/test/ELF/hexagon-shared.s b/lld/test/ELF/hexagon-shared.s --- a/lld/test/ELF/hexagon-shared.s +++ b/lld/test/ELF/hexagon-shared.s @@ -1,15 +1,23 @@ # REQUIRES: hexagon -# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %s -o %t +# RUN: llvm-mc -mno-fixup -filetype=obj -triple=hexagon-unknown-elf %s -o %t.o # RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %S/Inputs/hexagon-shared.s -o %t2.o # RUN: ld.lld -shared %t2.o -soname so -o %t3.so -# RUN: ld.lld -shared %t %t3.so -o %t4.so +# RUN: ld.lld -shared %t.o %t3.so -o %t4.so +# RUN: ld.lld -Bsymbolic -shared %t.o %t3.so -o %t5.so # RUN: llvm-objdump -d -j .plt %t4.so | FileCheck --check-prefix=PLT %s # RUN: llvm-objdump -d -j .text %t4.so | FileCheck --check-prefix=TEXT %s # RUN: llvm-objdump -D -j .got %t4.so | FileCheck --check-prefix=GOT %s # RUN: llvm-readelf -r %t4.so | FileCheck --check-prefix=RELO %s +# RUN: llvm-readelf -r %t5.so | FileCheck --check-prefix=SYMBOLIC %s -.global foo -foo: +.global _start, foo, hidden_symbol +.hidden hidden_symbol +_start: +# When -Bsymbolic is specified calls to locally resolvables should +# not generate a plt. +call ##foo +# Calls to hidden_symbols should not trigger a plt. +call ##hidden_symbol # _HEX_32_PCREL .word _DYNAMIC - . @@ -17,6 +25,10 @@ # R_HEX_PLT_B22_PCREL call bar@PLT +# R_HEX_B15_PCREL_X +if (p0) jump bar +# R_HEX_B9_PCREL_X +{ r0 = #0; jump bar } # R_HEX_GOT_11_X and R_HEX_GOT_32_6_X r2=add(pc,##_GLOBAL_OFFSET_TABLE_@PCREL) @@ -26,6 +38,13 @@ # R_HEX_GOT_16_X r0 = add(r1,##bar@GOT) +# foo is local so no plt will be generated +foo: + jumpr lr + +hidden_symbol: + jumpr lr + # R_HEX_32 .data .global var @@ -40,26 +59,37 @@ .word var .size pvar, 4 -# PLT: { immext(#131200 -# PLT: r28 = add(pc,##131252) } -# PLT: { r14 -= add(r28,#16) -# PLT: r15 = memw(r28+#8) -# PLT: r28 = memw(r28+#4) } -# PLT: { r14 = asr(r14,#2) -# PLT: jumpr r28 } -# PLT: { trap0(#219) } -# PLT: immext(#131200) -# PLT: r14 = add(pc,##131236) } -# PLT: r28 = memw(r14+#0) } -# PLT: jumpr r28 } -# TEXT: 10218: 68 00 01 00 00010068 -# TEXT: { call 0x10270 } -# TEXT: r0 = add(r1,##-65548) } +# PLT: { immext(#131264 +# PLT-NEXT: r28 = add(pc,##131268) } +# PLT-NEXT: { r14 -= add(r28,#16) +# PLT-NEXT: r15 = memw(r28+#8) +# PLT-NEXT: r28 = memw(r28+#4) } +# PLT-NEXT: { r14 = asr(r14,#2) +# PLT-NEXT: jumpr r28 } +# PLT-NEXT: { trap0(#219) } +# PLT-NEXT: immext(#131200) +# PLT-NEXT: r14 = add(pc,##131252) } +# PLT-NEXT: r28 = memw(r14+#0) } +# PLT-NEXT: jumpr r28 } + +# TEXT: 8c 00 01 00 0001008c +# TEXT: { call 0x102d0 } +# TEXT: if (p0) jump:nt 0x102d0 +# TEXT: r0 = #0 ; jump 0x102d0 +# TEXT: r0 = add(r1,##-65548) # GOT: .got: -# GOT: 202f8: 00 00 00 00 00000000 +# GOT: 00 00 00 00 00000000 + +# RELO: R_HEX_GLOB_DAT +# RELO: R_HEX_32 +# RELO: Relocation section '.rela.plt' at offset 0x22c contains 2 entries: +# RELO: R_HEX_JMP_SLOT {{.*}} foo +# RELO-NEXT: R_HEX_JMP_SLOT {{.*}} bar +# RELO-NOT: R_HEX_JMP_SLOT {{.*}} hidden -# RELO: 000202f8 00000121 R_HEX_GLOB_DAT -# RELO: 00030300 00000406 R_HEX_32 -# RELO: 00030314 00000122 R_HEX_JMP_SLOT +# Make sure that no PLT is generated for a local call. +# SYMBOLIC: Relocation section '.rela.plt' at offset 0x22c contains 1 entries: +# SYMBOLIC: R_HEX_JMP_SLOT {{.*}} bar +# SYMBOLIC-NOT: R_HEX_JMP_SLOT {{.*}} foo