mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-12 14:06:36 +00:00
[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
This commit is contained in:
parent
3fdcf4e64c
commit
2e2846c8af
@ -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:
|
||||
|
@ -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;
|
||||
|
19
test/MC/ARM/thumb-cb-negative-offsets.s
Normal file
19
test/MC/ARM/thumb-cb-negative-offsets.s
Normal file
@ -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
|
@ -234,6 +234,23 @@ error: invalid operand for instruction
|
||||
@ CHECK-ERRORS: error: branch target out of range
|
||||
@ 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
|
||||
@------------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user