Skip to content

Commit fa210dd

Browse files
committed
[Thumb] Baseline test for incorrect relocation with -ffunction-sections
When calling a dso_local function, we end up creating a call against the .Lfoo$local label. This might be converted to a relocation against a section if there is such a matching one (which is a lot more likely with -ffunction-sections) and then the LSB (Thumb flag) will be lost. I originally noticed this with Morello LLVM (which uses the LSB to indicate a C64 encoding mode function). The missing LSB meant that ld.lld would insert a thunk that switches encoding mode which then resulted in errors at runtime since functions were being entered with the wrong encoding mode. Since the Morello backend is not upstream, I looked if any in-tree backends could also be affected by the missing STT_FUNC flag and noticed that Thumb is also affected (although the bug is rather difficult to trigger - it currently requires inline assembly). Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D131432
1 parent 9a2b14a commit fa210dd

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
;; -ffunction-sections previously resulted in call relocations against the
2+
;; .text.foo section symbol instead of the actual function symbol.
3+
;; However, that results in a relocation against a symbol without the LSB set,
4+
;; so the linker thinks it is not linking against a Thumb symbol.
5+
;; Check that we use a relocation against the symbol for calls to functions
6+
;; marked as dso_local (foo$local)
7+
;; NB: Right now only R_ARM_PREL31 and R_ARM_ABS32 are converted to section
8+
;; plus offset, so this test can't use a call.
9+
; RUN: llc -mtriple=armv7a-none-linux-gnueabi --function-sections -o - --relocation-model=pic %s | FileCheck %s
10+
; RUN: llc -mtriple=armv7a-none-linux-gnueabi --function-sections --filetype=obj -o %t --relocation-model=pic %s
11+
; RUN: llvm-readobj -r --symbols %t | FileCheck %s --check-prefix=RELOCS
12+
;; Do not autogen (we check directives that are normally filtered out):
13+
; UTC-ARGS: --disable
14+
15+
; RELOCS-LABEL: Relocations [
16+
; RELOCS-NEXT: Section (5) .rel.ARM.exidx.text._ZdlPv {
17+
; RELOCS-NEXT: 0x0 R_ARM_PREL31 .text._ZdlPv
18+
; RELOCS-NEXT: }
19+
; RELOCS-NEXT: Section (7) .rel.text.test {
20+
; RELOCS-NEXT: 0x4 R_ARM_CALL _ZdlPv
21+
; FIXME: these two relocation should not be against the section!
22+
; RELOCS-NEXT: 0xC R_ARM_ABS32 .text._ZdlPv
23+
; RELOCS-NEXT: 0x10 R_ARM_ABS32 .text._ZdlPv
24+
; RELOCS-NEXT: 0x1C R_ARM_REL32 _ZdlPv
25+
; RELOCS-NEXT: }
26+
; RELOCS-NEXT: Section (9) .rel.ARM.exidx.text.test {
27+
; RELOCS-NEXT: 0x0 R_ARM_PREL31 .text.test
28+
; RELOCS-NEXT: }
29+
; RELOCS-NEXT: Section (11) .rel.data {
30+
; RELOCS-NEXT: 0x0 R_ARM_ABS32 _ZdlPv
31+
; RELOCS-NEXT: }
32+
; RELOCS-NEXT: ]
33+
34+
; RELOCS-LABEL: Symbols [
35+
; RELOCS: Symbol {
36+
; FIXME: we should include the symbol in the symbol table!
37+
; RELOCS-NOT: Name: .L_ZdlPv$local
38+
; RELOCS-TODO: Name: .L_ZdlPv$local
39+
; RELOCS-TODO: Value: 0x1
40+
; RELOCS-TODO: Size: 2
41+
; RELOCS-TODO: Binding: Local (0x0)
42+
; RELOCS-TODO: Type: Function (0x2)
43+
; RELOCS-TODO: Other: 0
44+
; RELOCS-TODO: Section: .text._ZdlPv (
45+
; RELOCS-TODO: }
46+
47+
define dso_local void @_ZdlPv(ptr %ptr) local_unnamed_addr nounwind "target-features"="+armv7-a,+thumb-mode" {
48+
; CHECK-LABEL: .section .text._ZdlPv,"ax",%progbits
49+
; CHECK-NEXT: .globl _ZdlPv @ -- Begin function _ZdlPv
50+
; CHECK-NEXT: .p2align 1
51+
; CHECK-NEXT: .type _ZdlPv,%function
52+
; CHECK-NEXT: .code 16 @ @_ZdlPv
53+
; CHECK-NEXT: .thumb_func
54+
; CHECK-NEXT: _ZdlPv:
55+
; CHECK-NEXT: .L_ZdlPv$local:
56+
; CHECK-NEXT: .fnstart
57+
; CHECK-NEXT: @ %bb.0:
58+
; CHECK-NEXT: bx lr
59+
; CHECK-NEXT: .Lfunc_end0:
60+
; CHECK-NEXT: .size _ZdlPv, .Lfunc_end0-_ZdlPv
61+
; CHECK-NEXT: .cantunwind
62+
; CHECK-NEXT: .fnend
63+
ret void
64+
}
65+
66+
define ptr @test(ptr %ptr) nounwind {
67+
; CHECK-LABEL: test:
68+
; CHECK: @ %bb.0: @ %entry
69+
; CHECK-NEXT: .save {r11, lr}
70+
; CHECK-NEXT: push {r11, lr}
71+
; CHECK-NEXT: bl _ZdlPv{{$}}
72+
; CHECK-NEXT: ldr r0, .LCPI1_0
73+
; CHECK-NEXT: @APP
74+
; CHECK-NEXT: .long .L_ZdlPv$local
75+
; CHECK-NEXT: @NO_APP
76+
; CHECK-NEXT: @APP
77+
; CHECK-NEXT: .Ltmp0:
78+
; CHECK-NEXT: .reloc .Ltmp0, R_ARM_ABS32, .L_ZdlPv$local
79+
; CHECK-NEXT: .long 0
80+
; CHECK-NEXT: @NO_APP
81+
; CHECK-NEXT: .LPC1_0:
82+
; CHECK-NEXT: add r0, pc, r0
83+
; CHECK-NEXT: pop {r11, pc}
84+
; CHECK-NEXT: .p2align 2
85+
; CHECK-NEXT: @ %bb.1:
86+
; CHECK-NEXT: .LCPI1_0:
87+
; CHECK-NEXT: .long _ZdlPv-(.LPC1_0+8)
88+
entry:
89+
call void @_ZdlPv(ptr %ptr)
90+
; This inline assembly is needed to highlight the missing Thumb LSB since
91+
; only R_ARM_ABS32 is converted to section+offset
92+
tail call void asm sideeffect ".4byte .L_ZdlPv$$local", ""()
93+
tail call void asm sideeffect ".reloc ., R_ARM_ABS32, .L_ZdlPv$$local\0A.4byte 0", ""()
94+
ret ptr @_ZdlPv
95+
}
96+
97+
@fnptr = hidden local_unnamed_addr global ptr @_ZdlPv

0 commit comments

Comments
 (0)