-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Reland "[llvm][ARM] Add Addend Checks for MOVT and MOVW instructions. (PR #111970)" #112877
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reland "[llvm][ARM] Add Addend Checks for MOVT and MOVW instructions. (PR #111970)" #112877
Conversation
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/pr-subscribers-backend-arm Author: Jack Styles (Stylie777) ChangesChange relanded after feedback on failures and improvements to the check of the addend. 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 Full diff: https://github.com/llvm/llvm-project/pull/112877.diff 5 Files Affected:
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 @@
+@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
+
+@CHECK: error: Relocation Not In Range
+@CHECK: movw r1, #:lower16:v + -65536
+@CHECK: ^
+@CHECK: error: Relocation Not In Range
+@CHECK: movt r1, #:upper16:v + 65536
+@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 @@
+@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
+
+@CHECK-NOT: error: Relocation Not In Range
+@CHECK-NOT: movw r1, #:lower16:v + -20000
+@CHECK-NOT: ^
+@CHECK-NOT: error: Relocation Not In Range
+@CHECK-NOT: movt r1, #:upper16:v + 20000
+@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 -
|
@llvm/pr-subscribers-mc Author: Jack Styles (Stylie777) ChangesChange relanded after feedback on failures and improvements to the check of the addend. 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 Full diff: https://github.com/llvm/llvm-project/pull/112877.diff 5 Files Affected:
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 @@
+@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
+
+@CHECK: error: Relocation Not In Range
+@CHECK: movw r1, #:lower16:v + -65536
+@CHECK: ^
+@CHECK: error: Relocation Not In Range
+@CHECK: movt r1, #:upper16:v + 65536
+@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 @@
+@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
+
+@CHECK-NOT: error: Relocation Not In Range
+@CHECK-NOT: movw r1, #:lower16:v + -20000
+@CHECK-NOT: ^
+@CHECK-NOT: error: Relocation Not In Range
+@CHECK-NOT: movt r1, #:upper16:v + 20000
+@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 -
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, LGTM assuming tests all now passing.
Yes @jthackray I have tested locally and all tests are passing. |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/30/builds/8673 Here is the relevant piece of the build log for the reference
|
Change relanded after feedback on failures and improvements to the check of the addend. Original PR #111970
Changes from original patch:
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