[llvm] Reland "[llvm][ARM] Add Addend Checks for MOVT and MOVW instructions. (PR #111970)" (PR #112877)
Jack Styles via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 21 07:13:04 PDT 2024
https://github.com/Stylie777 updated https://github.com/llvm/llvm-project/pull/112877
>From ea9adf6b9c3e3bbc5d09b7523772bdb8e074a8fb Mon Sep 17 00:00:00 2001
From: Jack Styles <jack.styles at arm.com>
Date: Fri, 18 Oct 2024 10:55:12 +0100
Subject: [PATCH] [ARM][MC] Add Range Checks for MOVT and MOVW Instructions
As per the ARM ABI, the MOVT and MOVW instructions should have
addends that fall within a 16bit signed range. LLVM does not check
this so it is possible to use addends that are beyond the accepted
range. These addends are silently truncated.
A new check is added to ensure the addend falls within the expected
range, rejecting an addend that falls outside with an error.
Information relating to the ABI requirements can be found here:
https://github.com/ARM-software/abi-aa/blob/main/aaelf32/aaelf32.rst#addends-and-pc-bias-compensation
---
llvm/docs/ReleaseNotes.md | 5 +++++
.../Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 11 +++++++++++
llvm/test/MC/ARM/arm-movt-movw-range-fail.s | 13 +++++++++++++
llvm/test/MC/ARM/arm-movt-movw-range-pass.s | 13 +++++++++++++
llvm/test/MC/ARM/macho-movwt.s | 16 ++++++++--------
5 files changed, 50 insertions(+), 8 deletions(-)
create mode 100644 llvm/test/MC/ARM/arm-movt-movw-range-fail.s
create mode 100644 llvm/test/MC/ARM/arm-movt-movw-range-pass.s
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index f8bc7e79239b64..c8f5d22c15472a 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -131,6 +131,11 @@ Changes to the ARM Backend
in leaf functions by default. To eliminate the frame pointer in leaf functions,
you must explicitly use the `-momit-leaf-frame-pointer` option.
+* When using the `MOVT` or `MOVW` instructions, the Assembler will now check to
+ ensure that any addend that is used is within a 16-bit signed value range. If the
+ addend falls outside of this range, the LLVM backend will emit an error like so
+ `Relocation Not In Range`.
+
Changes to the AVR Backend
--------------------------
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
index 1223210a76f6e3..1f07e646e43885 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
@@ -34,6 +34,7 @@
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -445,6 +446,16 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm,
bool IsResolved, MCContext &Ctx,
const MCSubtargetInfo* STI) const {
unsigned Kind = Fixup.getKind();
+ int64_t Addend = Target.getConstant();
+
+ // For MOVW/MOVT Instructions, the fixup value must already be within a
+ // signed 16bit range.
+ if ((Kind == ARM::fixup_arm_movw_lo16 || Kind == ARM::fixup_arm_movt_hi16 ||
+ Kind == ARM::fixup_t2_movw_lo16 || Kind == ARM::fixup_t2_movt_hi16) &&
+ (Addend < minIntN(16) || Addend > maxIntN(16))) {
+ Ctx.reportError(Fixup.getLoc(), "Relocation Not In Range");
+ return 0;
+ }
// MachO tries to make .o files that look vaguely pre-linked, so for MOVW/MOVT
// and .word relocations they put the Thumb bit into the addend if possible.
diff --git a/llvm/test/MC/ARM/arm-movt-movw-range-fail.s b/llvm/test/MC/ARM/arm-movt-movw-range-fail.s
new file mode 100644
index 00000000000000..2961b9bfcb64d2
--- /dev/null
+++ b/llvm/test/MC/ARM/arm-movt-movw-range-fail.s
@@ -0,0 +1,13 @@
+ at RUN: not llvm-mc -triple armv7-eabi -filetype obj -o - %s 2>&1 | FileCheck %s
+
+ .global v
+ .text
+ movw r1, #:lower16:v + -65536
+ movt r1, #:upper16:v + 65536
+
+ at CHECK: error: Relocation Not In Range
+ at CHECK: movw r1, #:lower16:v + -65536
+ at CHECK: ^
+ at CHECK: error: Relocation Not In Range
+ at CHECK: movt r1, #:upper16:v + 65536
+ at CHECK: ^
diff --git a/llvm/test/MC/ARM/arm-movt-movw-range-pass.s b/llvm/test/MC/ARM/arm-movt-movw-range-pass.s
new file mode 100644
index 00000000000000..41f19565a46c4a
--- /dev/null
+++ b/llvm/test/MC/ARM/arm-movt-movw-range-pass.s
@@ -0,0 +1,13 @@
+ at RUN: llvm-mc -triple armv7-eabi -filetype obj -o - %s 2>&1 | FileCheck %s
+
+ .global v
+ .text
+ movw r1, #:lower16:v + -20000
+ movt r1, #:upper16:v + 20000
+
+ at CHECK-NOT: error: Relocation Not In Range
+ at CHECK-NOT: movw r1, #:lower16:v + -20000
+ at CHECK-NOT: ^
+ at CHECK-NOT: error: Relocation Not In Range
+ at CHECK-NOT: movt r1, #:upper16:v + 20000
+ at CHECK-NOT: ^
diff --git a/llvm/test/MC/ARM/macho-movwt.s b/llvm/test/MC/ARM/macho-movwt.s
index 6f067cd86dc15d..b2c0587ca7fe59 100644
--- a/llvm/test/MC/ARM/macho-movwt.s
+++ b/llvm/test/MC/ARM/macho-movwt.s
@@ -8,8 +8,8 @@
movw r0, :lower16:_x+4
movt r0, :upper16:_x+4
- movw r0, :lower16:_x+0x10000
- movt r0, :upper16:_x+0x10000
+ movw r0, :lower16:_x+0x1000
+ movt r0, :upper16:_x+0x1000
.arm
movw r0, :lower16:_x
@@ -18,8 +18,8 @@
movw r0, :lower16:_x+4
movt r0, :upper16:_x+4
- movw r0, :lower16:_x+0x10000
- movt r0, :upper16:_x+0x10000
+ movw r0, :lower16:_x+0x1000
+ movt r0, :upper16:_x+0x1000
@ Enter the bizarre world of MachO relocations. First, they're in reverse order
@ to the actual instructions
@@ -30,10 +30,10 @@
@ Third column identifies ARM/Thumb & HI/LO.
@ CHECK: 0x2C 0 1 1 ARM_RELOC_HALF 0 _x
-@ CHECK: 0x0 0 1 0 ARM_RELOC_PAIR 0 -
+@ CHECK: 0x1000 0 1 0 ARM_RELOC_PAIR 0 -
@ CHECK: 0x28 0 0 1 ARM_RELOC_HALF 0 _x
-@ CHECK: 0x1 0 0 0 ARM_RELOC_PAIR 0 -
+@ CHECK: 0x0 0 0 0 ARM_RELOC_PAIR 0 -
@ CHECK: 0x24 0 1 1 ARM_RELOC_HALF 0 _x
@ CHECK: 0x4 0 1 0 ARM_RELOC_PAIR 0 -
@@ -48,10 +48,10 @@
@ CHECK: 0x0 0 0 0 ARM_RELOC_PAIR 0 -
@ CHECK: 0x14 0 3 1 ARM_RELOC_HALF 0 _x
-@ CHECK: 0x0 0 3 0 ARM_RELOC_PAIR 0 -
+@ CHECK: 0x1000 0 3 0 ARM_RELOC_PAIR 0 -
@ CHECK: 0x10 0 2 1 ARM_RELOC_HALF 0 _x
-@ CHECK: 0x1 0 2 0 ARM_RELOC_PAIR 0 -
+@ CHECK: 0x0 0 2 0 ARM_RELOC_PAIR 0 -
@ CHECK: 0xC 0 3 1 ARM_RELOC_HALF 0 _x
@ CHECK: 0x4 0 3 0 ARM_RELOC_PAIR 0 -
More information about the llvm-commits
mailing list