[PATCH] D23312: [Thumb] Validate branch target for CBZ/CBNZ instructions.

Prakhar Bahuguna via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 9 05:27:38 PDT 2016


prakhar created this revision.
prakhar added reviewers: rengolin, t.p.northover.
prakhar added a subscriber: llvm-commits.
Herald added a subscriber: rengolin.

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.

https://reviews.llvm.org/D23312

Files:
  lib/Target/ARM/AsmParser/ARMAsmParser.cpp
  lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
  test/MC/ARM/thumb-cb-negative-offsets.s
  test/MC/ARM/thumb-diagnostics.s

Index: test/MC/ARM/thumb-diagnostics.s
===================================================================
--- test/MC/ARM/thumb-diagnostics.s
+++ test/MC/ARM/thumb-diagnostics.s
@@ -235,6 +235,18 @@
 @ CHECK-ERRORS: error: branch target out of range
 
 @------------------------------------------------------------------------------
+@ CBZ/CBNZ - out of range immediates for branches
+ at ------------------------------------------------------------------------------
+
+        cbz    r0, #-4
+        cbnz   r0, #-8
+
+@ CHECK-ERRORS-V7M: error: branch target out of range
+@ CHECK-ERRORS-V7M: error: branch target out of range
+@ CHECK-ERRORS-V8: error: branch target out of range
+@ CHECK-ERRORS-V8: error: branch target out of range
+
+ at ------------------------------------------------------------------------------
 @ SEV/WFE/WFI/YIELD - are not supported pre v6M or v6T2
 @------------------------------------------------------------------------------
         sev
Index: test/MC/ARM/thumb-cb-negative-offsets.s
===================================================================
--- /dev/null
+++ test/MC/ARM/thumb-cb-negative-offsets.s
@@ -0,0 +1,10 @@
+@ 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
Index: lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
===================================================================
--- lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
+++ lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
@@ -578,6 +578,11 @@
     // Offset by 4, and don't encode the low two bits.
     return ((Value - 4) >> 2) & 0xff;
   case ARM::fixup_arm_thumb_cb: {
+    // CB instructions cannot branch backwards with a negative offset
+    if (Ctx && (int64_t)Value < 0) {
+      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;
Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp
===================================================================
--- lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -860,6 +860,16 @@
     return true;
   }
 
+  bool isPositiveOffset() const {
+    if (!isImm()) return false;
+    const MCExpr *ref = getImm();
+
+    if (ref->getKind() == MCExpr::Constant)
+      return dyn_cast<MCConstantExpr>(ref)->getValue() > 0;
+
+    return true;
+  }
+
   // checks whether this operand is an unsigned offset which fits is a field
   // of specified width and scaled by a specific number of bits
   template<unsigned width, unsigned scale>
@@ -6684,6 +6694,12 @@
       return Error(Operands[Op]->getStartLoc(), "branch target out of range");
     break;
   }
+  case ARM::tCBZ:
+  case ARM::tCBNZ: {
+    if (!static_cast<ARMOperand &>(*Operands[2]).isPositiveOffset())
+      return Error(Operands[2]->getStartLoc(), "branch target out of range");
+    break;
+  }
   case ARM::MOVi16:
   case ARM::t2MOVi16:
   case ARM::t2MOVTi16:


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D23312.67323.patch
Type: text/x-patch
Size: 3329 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160809/5c2c7dd1/attachment.bin>


More information about the llvm-commits mailing list