diff options
author | Prakhar Bahuguna <prakhar.bahuguna@arm.com> | 2016-08-15 07:57:44 +0000 |
---|---|---|
committer | Prakhar Bahuguna <prakhar.bahuguna@arm.com> | 2016-08-15 07:57:44 +0000 |
commit | a305a435a6568114022cd684675b4b2ca24cd2da (patch) | |
tree | a4ff195242f54a1fa22f035ace23e67787ae96c0 | |
parent | 196ad0823e67bffef39983fbd9d7c13fb25911b6 (diff) | |
download | bcm5719-llvm-a305a435a6568114022cd684675b4b2ca24cd2da.tar.gz bcm5719-llvm-a305a435a6568114022cd684675b4b2ca24cd2da.zip |
[Thumb] Validate branch target for CBZ/CBNZ instructions.
Summary:
The assembler currently does not check the branch target for CBZ/CBNZ
instructions, which only permit branching forwards with a positive offset. This
adds validation for the branch target to ensure negative PC-relative offsets are
not encoded into the instruction, whether specified as a literal or as an
assembler symbol.
Reviewers: rengolin, t.p.northover
Subscribers: llvm-commits, rengolin
Differential Revision: https://reviews.llvm.org/D23312
llvm-svn: 278659
-rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 5 | ||||
-rw-r--r-- | llvm/test/MC/ARM/thumb-cb-negative-offsets.s | 19 | ||||
-rw-r--r-- | llvm/test/MC/ARM/thumb-diagnostics.s | 17 |
4 files changed, 47 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index b9b665fc1ea..c011c792bff 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -6684,6 +6684,12 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, return Error(Operands[Op]->getStartLoc(), "branch target out of range"); break; } + case ARM::tCBZ: + case ARM::tCBNZ: { + if (!static_cast<ARMOperand &>(*Operands[2]).isUnsignedOffset<6, 1>()) + return Error(Operands[2]->getStartLoc(), "branch target out of range"); + break; + } case ARM::MOVi16: case ARM::t2MOVi16: case ARM::t2MOVTi16: diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 26f96ab77fe..5ac2d65a89e 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -578,6 +578,11 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Offset by 4, and don't encode the low two bits. return ((Value - 4) >> 2) & 0xff; case ARM::fixup_arm_thumb_cb: { + // CB instructions can only branch to offsets in [0, 126] in multiples of 2 + if (Ctx && ((int64_t)Value < 0 || Value > 0x3e || Value & 1)) { + Ctx->reportError(Fixup.getLoc(), "out of range pc-relative fixup value"); + return 0; + } // Offset by 4 and don't encode the lower bit, which is always 0. // FIXME: diagnose if no Thumb2 uint32_t Binary = (Value - 4) >> 1; diff --git a/llvm/test/MC/ARM/thumb-cb-negative-offsets.s b/llvm/test/MC/ARM/thumb-cb-negative-offsets.s new file mode 100644 index 00000000000..cd70126ea95 --- /dev/null +++ b/llvm/test/MC/ARM/thumb-cb-negative-offsets.s @@ -0,0 +1,19 @@ +@ RUN: not llvm-mc -triple thumbv7m-none-eabi -filetype=obj -o /dev/null %s 2>&1 | FileCheck %s +@ RUN: not llvm-mc -triple thumbv8m.base-none-eabi -filetype=obj -o /dev/null %s 2>&1 | FileCheck %s + +label0: + .word 4 + +@ CHECK: out of range pc-relative fixup value + cbz r0, label0 +@ CHECK: out of range pc-relative fixup value + cbnz r0, label0 + +@ CHECK: out of range pc-relative fixup value + cbz r0, label1 +@ CHECK: out of range pc-relative fixup value + cbnz r0, label1 + + .space 1000 +label1: + .word 4 diff --git a/llvm/test/MC/ARM/thumb-diagnostics.s b/llvm/test/MC/ARM/thumb-diagnostics.s index 5dcac90a901..65d8ed6f073 100644 --- a/llvm/test/MC/ARM/thumb-diagnostics.s +++ b/llvm/test/MC/ARM/thumb-diagnostics.s @@ -235,6 +235,23 @@ error: invalid operand for instruction @ CHECK-ERRORS: error: branch target out of range @------------------------------------------------------------------------------ +@ CBZ/CBNZ - out of range immediates for branches +@------------------------------------------------------------------------------ + + cbz r0, #-2 + cbz r0, #0 + cbz r0, #17 + cbnz r0, #126 + cbnz r0, #128 + +@ CHECK-ERRORS-V7M: error: branch target out of range +@ CHECK-ERRORS-V7M: error: invalid operand for instruction +@ CHECK-ERRORS-V7M: error: branch target out of range +@ CHECK-ERRORS-V8: error: branch target out of range +@ CHECK-ERRORS-V8: error: invalid operand for instruction +@ CHECK-ERRORS-V8: error: branch target out of range + +@------------------------------------------------------------------------------ @ SEV/WFE/WFI/YIELD - are not supported pre v6M or v6T2 @------------------------------------------------------------------------------ sev |