[llvm] fa210dd - [Thumb] Baseline test for incorrect relocation with -ffunction-sections

Alex Richardson via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 9 02:54:03 PDT 2022


Author: Alex Richardson
Date: 2022-08-09T09:53:47Z
New Revision: fa210dd67b458f7a11631c7fb2eebb05f4849ce5

URL: https://github.com/llvm/llvm-project/commit/fa210dd67b458f7a11631c7fb2eebb05f4849ce5
DIFF: https://github.com/llvm/llvm-project/commit/fa210dd67b458f7a11631c7fb2eebb05f4849ce5.diff

LOG: [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

Added: 
    llvm/test/CodeGen/ARM/thumb-function-section-reloc.ll

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/test/CodeGen/ARM/thumb-function-section-reloc.ll b/llvm/test/CodeGen/ARM/thumb-function-section-reloc.ll
new file mode 100644
index 000000000000..31f6ae2dc58c
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/thumb-function-section-reloc.ll
@@ -0,0 +1,97 @@
+;; -ffunction-sections previously resulted in call relocations against the
+;; .text.foo section symbol instead of the actual function symbol.
+;; However, that results in a relocation against a symbol without the LSB set,
+;; so the linker thinks it is not linking against a Thumb symbol.
+;; Check that we use a relocation against the symbol for calls to functions
+;; marked as dso_local (foo$local)
+;; NB: Right now only R_ARM_PREL31 and R_ARM_ABS32 are converted to section
+;; plus offset, so this test can't use a call.
+; RUN: llc -mtriple=armv7a-none-linux-gnueabi --function-sections -o - --relocation-model=pic %s | FileCheck %s
+; RUN: llc -mtriple=armv7a-none-linux-gnueabi --function-sections --filetype=obj -o %t --relocation-model=pic %s
+; RUN: llvm-readobj -r --symbols %t | FileCheck %s --check-prefix=RELOCS
+;; Do not autogen (we check directives that are normally filtered out):
+; UTC-ARGS: --disable
+
+; RELOCS-LABEL: Relocations [
+; RELOCS-NEXT:   Section (5) .rel.ARM.exidx.text._ZdlPv {
+; RELOCS-NEXT:     0x0 R_ARM_PREL31 .text._ZdlPv
+; RELOCS-NEXT:   }
+; RELOCS-NEXT:   Section (7) .rel.text.test {
+; RELOCS-NEXT:     0x4 R_ARM_CALL _ZdlPv
+; FIXME: these two relocation should not be against the section!
+; RELOCS-NEXT:     0xC R_ARM_ABS32 .text._ZdlPv
+; RELOCS-NEXT:     0x10 R_ARM_ABS32 .text._ZdlPv
+; RELOCS-NEXT:     0x1C R_ARM_REL32 _ZdlPv
+; RELOCS-NEXT:   }
+; RELOCS-NEXT:   Section (9) .rel.ARM.exidx.text.test {
+; RELOCS-NEXT:     0x0 R_ARM_PREL31 .text.test
+; RELOCS-NEXT:   }
+; RELOCS-NEXT:   Section (11) .rel.data {
+; RELOCS-NEXT:     0x0 R_ARM_ABS32 _ZdlPv
+; RELOCS-NEXT:   }
+; RELOCS-NEXT: ]
+
+; RELOCS-LABEL: Symbols [
+; RELOCS: Symbol {
+; FIXME: we should include the symbol in the symbol table!
+; RELOCS-NOT:    Name: .L_ZdlPv$local
+; RELOCS-TODO:   Name: .L_ZdlPv$local
+; RELOCS-TODO:   Value: 0x1
+; RELOCS-TODO:   Size: 2
+; RELOCS-TODO:   Binding: Local (0x0)
+; RELOCS-TODO:   Type: Function (0x2)
+; RELOCS-TODO:   Other: 0
+; RELOCS-TODO:   Section: .text._ZdlPv (
+; RELOCS-TODO: }
+
+define dso_local void @_ZdlPv(ptr %ptr) local_unnamed_addr nounwind "target-features"="+armv7-a,+thumb-mode" {
+; CHECK-LABEL: 	.section	.text._ZdlPv,"ax",%progbits
+; CHECK-NEXT: 	.globl	_ZdlPv                          @ -- Begin function _ZdlPv
+; CHECK-NEXT: 	.p2align	1
+; CHECK-NEXT: 	.type	_ZdlPv,%function
+; CHECK-NEXT: 	.code	16                              @ @_ZdlPv
+; CHECK-NEXT: 	.thumb_func
+; CHECK-NEXT: _ZdlPv:
+; CHECK-NEXT: .L_ZdlPv$local:
+; CHECK-NEXT: 	.fnstart
+; CHECK-NEXT: @ %bb.0:
+; CHECK-NEXT: 	bx	lr
+; CHECK-NEXT: .Lfunc_end0:
+; CHECK-NEXT: 	.size	_ZdlPv, .Lfunc_end0-_ZdlPv
+; CHECK-NEXT: 	.cantunwind
+; CHECK-NEXT: 	.fnend
+  ret void
+}
+
+define ptr @test(ptr %ptr) nounwind {
+; CHECK-LABEL: test:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    .save {r11, lr}
+; CHECK-NEXT:    push {r11, lr}
+; CHECK-NEXT:    bl _ZdlPv{{$}}
+; CHECK-NEXT:    ldr r0, .LCPI1_0
+; CHECK-NEXT:    @APP
+; CHECK-NEXT:    .long .L_ZdlPv$local
+; CHECK-NEXT:    @NO_APP
+; CHECK-NEXT:    @APP
+; CHECK-NEXT:    .Ltmp0:
+; CHECK-NEXT:    .reloc .Ltmp0, R_ARM_ABS32, .L_ZdlPv$local
+; CHECK-NEXT:    .long 0
+; CHECK-NEXT:    @NO_APP
+; CHECK-NEXT:  .LPC1_0:
+; CHECK-NEXT:    add r0, pc, r0
+; CHECK-NEXT:    pop {r11, pc}
+; CHECK-NEXT:    .p2align 2
+; CHECK-NEXT:  @ %bb.1:
+; CHECK-NEXT:  .LCPI1_0:
+; CHECK-NEXT:    .long _ZdlPv-(.LPC1_0+8)
+entry:
+  call void @_ZdlPv(ptr %ptr)
+  ; This inline assembly is needed to highlight the missing Thumb LSB since
+  ; only R_ARM_ABS32 is converted to section+offset
+  tail call void asm sideeffect ".4byte .L_ZdlPv$$local", ""()
+  tail call void asm sideeffect ".reloc ., R_ARM_ABS32, .L_ZdlPv$$local\0A.4byte 0", ""()
+  ret ptr @_ZdlPv
+}
+
+ at fnptr = hidden local_unnamed_addr global ptr @_ZdlPv


        


More information about the llvm-commits mailing list