PC relative handling and instr category for AArch32 (#499)

* changes in AArch32 decoder to test using opt fuzz
This commit is contained in:
kumarak
2021-03-31 16:31:17 -04:00
committed by GitHub
parent eec3dee7b4
commit 2b241b83c0
11 changed files with 245 additions and 148 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ typedef RnW<uint32_t> R32W;
typedef Rn<uint8_t> R8;
//typedef Rn<uint16_t> R16;
// typedef Rn<uint16_t> R16;
typedef Rn<uint32_t> R32;
typedef Vn<vec8_t> V8;
+3
View File
@@ -60,6 +60,9 @@ class Operand {
kTypeImmediate,
kTypeAddress,
kTypeExpression,
kTypeRegisterExpression,
kTypeImmediateExpression,
kTypeAddressExpression,
} type;
enum Action { kActionInvalid, kActionRead, kActionWrite } action;
+1 -2
View File
@@ -252,8 +252,7 @@ std::string ModuleName(const std::unique_ptr<llvm::Module> &module);
// Replace all uses of a constant `old_c` with `new_c` inside of `module`.
//
// Returns the number of constant uses of `old_c`.
unsigned ReplaceAllUsesOfConstant(llvm::Constant *old_c,
llvm::Constant *new_c,
unsigned ReplaceAllUsesOfConstant(llvm::Constant *old_c, llvm::Constant *new_c,
llvm::Module *module);
// Move a function from one module into another module.
+1 -1
View File
@@ -124,7 +124,7 @@ void AArch32Arch::PopulateBasicBlockFunction(llvm::Module *module,
// auto v512 = llvm::ArrayType::get(llvm::Type::getInt8Ty(context), 512u / 8u);
auto addr = llvm::Type::getIntNTy(context, address_size);
//auto zero_addr_val = llvm::Constant::getNullValue(addr);
// auto zero_addr_val = llvm::Constant::getNullValue(addr);
const auto entry_block = &bb_func->getEntryBlock();
llvm::IRBuilder<> ir(entry_block);
+194 -128
View File
@@ -15,6 +15,7 @@
*/
#include <glog/logging.h>
#include <optional>
#include "Arch.h"
@@ -24,7 +25,7 @@ namespace remill {
namespace {
//Integer Data Processing (three register, register shift)
// Integer Data Processing (three register, register shift)
union IntDataProcessingRRRR {
uint32_t flat;
struct {
@@ -43,7 +44,7 @@ union IntDataProcessingRRRR {
} __attribute__((packed));
static_assert(sizeof(IntDataProcessingRRRR) == 4, " ");
//Integer Data Processing (three register, immediate shift)
// Integer Data Processing (three register, immediate shift)
union IntDataProcessingRRRI {
uint32_t flat;
struct {
@@ -61,7 +62,7 @@ union IntDataProcessingRRRI {
} __attribute__((packed));
static_assert(sizeof(IntDataProcessingRRRI) == 4, " ");
//Integer Data Processing (2 register and immediate, immediate shift)
// Integer Data Processing (2 register and immediate, immediate shift)
union IntDataProcessingRRI {
uint32_t flat;
struct {
@@ -618,7 +619,7 @@ static void AddShiftThenExtractOp(Instruction &inst,
op.action = Operand::kActionRead;
}
//static void AddExtractThenShiftOp(Instruction &inst,
// static void AddExtractThenShiftOp(Instruction &inst,
// Operand::ShiftRegister::Shift shift_op,
// Operand::ShiftRegister::Extend extend_op,
// const char *reg_name, unsigned reg_size,
@@ -633,7 +634,7 @@ static void AddShiftThenExtractOp(Instruction &inst,
// shift_reg.shift_first = false;
// auto &op = inst.EmplaceOperand(shift_reg);
// op.action = Operand::kActionRead;
//}
// }
// Note: Order is significant; extracted bits may be casted to this type.
@@ -999,7 +1000,12 @@ static bool DecodeCondition(Instruction &inst, uint32_t cond) {
}
std::optional<uint64_t> EvalReg(const Instruction &inst,
const Operand::Register &op) {
const Operand::Register &op,
bool &uses_linkreg) {
if (!uses_linkreg) {
uses_linkreg = (op.name == kIntRegName[kLRRegNum] || op.name == "LR");
}
if (op.name == kIntRegName[kPCRegNum] || op.name == "PC") {
return inst.pc;
} else if (op.name == "NEXT_PC") {
@@ -1071,16 +1077,16 @@ std::optional<uint64_t> EvalExtract(const Operand::ShiftRegister &op,
}
}
std::optional<uint64_t> EvalOperand(const Instruction &inst,
const Operand &op) {
std::optional<uint64_t> EvalOperand(const Instruction &inst, const Operand &op,
bool &uses_linkreg) {
switch (op.type) {
case Operand::kTypeInvalid: return std::nullopt;
case Operand::kTypeImmediate: return op.imm.val;
case Operand::kTypeRegister: return EvalReg(inst, op.reg);
case Operand::kTypeRegister: return EvalReg(inst, op.reg, uses_linkreg);
case Operand::kTypeAddress: {
auto seg_val = EvalReg(inst, op.addr.segment_base_reg);
auto base_val = EvalReg(inst, op.addr.base_reg);
auto index_val = EvalReg(inst, op.addr.index_reg);
auto seg_val = EvalReg(inst, op.addr.segment_base_reg, uses_linkreg);
auto base_val = EvalReg(inst, op.addr.base_reg, uses_linkreg);
auto index_val = EvalReg(inst, op.addr.index_reg, uses_linkreg);
if (!seg_val || !base_val || !index_val) {
return std::nullopt;
@@ -1091,16 +1097,21 @@ std::optional<uint64_t> EvalOperand(const Instruction &inst,
(static_cast<int64_t>(*index_val) * op.addr.scale) +
op.addr.displacement);
}
case Operand::kTypeShiftRegister:
case Operand::kTypeShiftRegister: {
if (op.shift_reg.shift_first) {
return EvalExtract(
op.shift_reg,
EvalShift(op.shift_reg, EvalReg(inst, op.shift_reg.reg)));
EvalShift(op.shift_reg,
EvalReg(inst, op.shift_reg.reg, uses_linkreg)));
} else {
return EvalShift(
op.shift_reg,
EvalExtract(op.shift_reg, EvalReg(inst, op.shift_reg.reg)));
EvalExtract(op.shift_reg,
EvalReg(inst, op.shift_reg.reg, uses_linkreg)));
}
}
case Operand::kTypeRegisterExpression:
return EvalReg(inst, op.reg, uses_linkreg);
default: return std::nullopt;
}
}
@@ -1120,10 +1131,35 @@ static bool EvalPCDest(Instruction &inst, const bool s, const unsigned int rd,
inst.category = Instruction::kCategoryError;
return false;
} else {
auto src1 = EvalOperand(inst, inst.operands[1]);
auto src2 = EvalOperand(inst, inst.operands[2]);
if (!src1 || !src2) {
// HACK(akshayk): EvalPCDest is only getting called from the instruction
// decode function emplace 5 operands to the vector. Added
// assert check to make sure it is not getting called else
// where. Update it to pass source operand as parameter
// and use them to identify the instruction category
CHECK(inst.operands.size() == 5)
<< "Failed to evaluate PC registers due to missing source operands;";
// NOTE(akshayk): LR register can be used in source expression to update PC.
// These instructions will be of return type. Check if either
// of the operand uses link register to update the PC
// e.g: add pc, lr, #4
//
bool uses_linkreg = false;
auto src1 = EvalOperand(inst, inst.operands[3], uses_linkreg);
auto src2 = EvalOperand(inst, inst.operands[4], uses_linkreg);
if (uses_linkreg) {
// NOTE(akshayk): conditional return `movne pc, lr`
if (is_cond) {
inst.branch_not_taken_pc = inst.next_pc;
inst.category = Instruction::kCategoryConditionalFunctionReturn;
} else {
inst.category = Instruction::kCategoryFunctionReturn;
}
} else if (!src1 || !src2) {
inst.category = Instruction::kCategoryIndirectJump;
} else {
auto res = evaluator(*src1, *src2);
@@ -1195,20 +1231,20 @@ static const char *const kIdpNamesRRR[] = {
[0b1100] = "SBCrr", [0b1101] = "SBCSrr", [0b1110] = "RSCrr",
[0b1111] = "RSCSrr"};
//000 AND, ANDS (register)
//001 EOR, EORS (register)
//010 0 != 1101 SUB, SUBS (register) — SUB
//010 0 1101 SUB, SUBS (SP minus register) — SUB
//010 1 != 1101 SUB, SUBS (register) — SUBS
//010 1 1101 SUB, SUBS (SP minus register) — SUBS
//011 RSB, RSBS (register)
//100 0 != 1101 ADD, ADDS (register) — ADD
//100 0 1101 ADD, ADDS (SP plus register) — ADD
//100 1 != 1101 ADD, ADDS (register) — ADDS
//100 1 1101 ADD, ADDS (SP plus register) — ADDS
//101 ADC, ADCS (register)
//110 SBC, SBCS (register)
//111 RSC, RSCS (register)
// 000 AND, ANDS (register)
// 001 EOR, EORS (register)
// 010 0 != 1101 SUB, SUBS (register) — SUB
// 010 0 1101 SUB, SUBS (SP minus register) — SUB
// 010 1 != 1101 SUB, SUBS (register) — SUBS
// 010 1 1101 SUB, SUBS (SP minus register) — SUBS
// 011 RSB, RSBS (register)
// 100 0 != 1101 ADD, ADDS (register) — ADD
// 100 0 1101 ADD, ADDS (SP plus register) — ADD
// 100 1 != 1101 ADD, ADDS (register) — ADDS
// 100 1 1101 ADD, ADDS (SP plus register) — ADDS
// 101 ADC, ADCS (register)
// 110 SBC, SBCS (register)
// 111 RSC, RSCS (register)
static bool TryDecodeIntegerDataProcessingRRRI(Instruction &inst,
uint32_t bits) {
const IntDataProcessingRRRI enc = {bits};
@@ -1243,22 +1279,22 @@ static bool TryDecodeIntegerDataProcessingRRRR(Instruction &inst,
return true;
}
//000 AND, ANDS (immediate)
//001 EOR, EORS (immediate)
//010 0 != 11x1 SUB, SUBS (immediate) — SUB
//010 0 1101 SUB, SUBS (SP minus immediate) — SUB
//010 0 1111 ADR — A2 (alias of subtract)
//010 1 != 1101 SUB, SUBS (immediate) — SUBS
//010 1 1101 SUB, SUBS (SP minus immediate) — SUBS
//011 RSB, RSBS (immediate)
//100 0 != 11x1 ADD, ADDS (immediate) — ADD
//100 0 1101 ADD, ADDS (SP plus immediate) — ADD
//100 0 1111 ADR — A1 (alias of add)
//100 1 != 1101 ADD, ADDS (immediate) — ADDS
//100 1 1101 ADD, ADDS (SP plus immediate) — ADDS
//101 ADC, ADCS (immediate)
//110 SBC, SBCS (immediate)
//111 RSC, RSCS (immediate)
// 000 AND, ANDS (immediate)
// 001 EOR, EORS (immediate)
// 010 0 != 11x1 SUB, SUBS (immediate) — SUB
// 010 0 1101 SUB, SUBS (SP minus immediate) — SUB
// 010 0 1111 ADR — A2 (alias of subtract)
// 010 1 != 1101 SUB, SUBS (immediate) — SUBS
// 010 1 1101 SUB, SUBS (SP minus immediate) — SUBS
// 011 RSB, RSBS (immediate)
// 100 0 != 11x1 ADD, ADDS (immediate) — ADD
// 100 0 1101 ADD, ADDS (SP plus immediate) — ADD
// 100 0 1111 ADR — A1 (alias of add)
// 100 1 != 1101 ADD, ADDS (immediate) — ADDS
// 100 1 1101 ADD, ADDS (SP plus immediate) — ADDS
// 101 ADC, ADCS (immediate)
// 110 SBC, SBCS (immediate)
// 111 RSC, RSCS (immediate)
static bool TryDecodeIntegerDataProcessingRRI(Instruction &inst,
uint32_t bits) {
const IntDataProcessingRRI enc = {bits};
@@ -1289,16 +1325,16 @@ static const char *const kMulAccRRR[] = {
[0b1100] = "SMULL", [0b1101] = "SMULLS", [0b1110] = "SMLAL",
[0b1111] = "SMLALS"};
//000 MUL, MULS
//001 MLA, MLAS
//010 0 UMAAL - writes to RdHi + RdLo, read RdHi
//010 1 UNALLOCATED
//011 0 MLS
//011 1 UNALLOCATED
//100 UMULL, UMULLS - writes to RdHi + RdLo
//101 UMLAL, UMLALS - writes to RdHi + RdLo, read RdHi
//110 SMULL, SMULLS - writes to RdHi + RdLo
//111 SMLAL, SMLALS - writes to RdHi + RdLo, read RdHi
// 000 MUL, MULS
// 001 MLA, MLAS
// 010 0 UMAAL - writes to RdHi + RdLo, read RdHi
// 010 1 UNALLOCATED
// 011 0 MLS
// 011 1 UNALLOCATED
// 100 UMULL, UMULLS - writes to RdHi + RdLo
// 101 UMLAL, UMLALS - writes to RdHi + RdLo, read RdHi
// 110 SMULL, SMULLS - writes to RdHi + RdLo
// 111 SMLAL, SMLALS - writes to RdHi + RdLo, read RdHi
static bool TryDecodeMultiplyAndAccumulate(Instruction &inst, uint32_t bits) {
const MultiplyAndAccumulate enc = {bits};
@@ -1573,8 +1609,8 @@ static const char *const kLoadSWUB[] = {
};
// P:W o2 o1 Rn
//!= 01 0 1 1111 LDR (literal)
//!= 01 1 1 1111 LDRB (literal)
// != 01 0 1 1111 LDR (literal)
// != 01 1 1 1111 LDRB (literal)
// 00 0 0 STR (immediate) — post-indexed
// 00 0 1 != 1111 LDR (immediate) — post-indexed
// 00 1 0 STRB (immediate) — post-indexed
@@ -1623,6 +1659,26 @@ static bool TryDecodeLoadStoreWordUBIL(Instruction &inst, uint32_t bits) {
disp = -disp;
}
// NOTE(akshayk): The PC of the instruction being fetched is generally of the PC of the
// executing instruction. This is the legacy pipeline effect which the ARM
// processor carry. The PC during an instruction execution you see will be
// "address of the executing instruction +8" for ARM and "address of the
// executing instruction +4" for Thumb; The decoder should also handle it
// and add offset to `disp`
//
// TODO(akshayk): Decoder does not support thumb architecture; use offset 8 for the ARM;
// Update it accordingly after adding support for thumb
//
// 0: e59f2008 ldr r2, [pc, #8] ; 10 <0x10>
// 4: e3510001 cmp r1, #1
// 8: 01a00002 moveq r0, r2
// c: e1a0f00e mov pc, lr
// 10: ca4227c5 .word 0xca4227c5
if (enc.rn == kPCRegNum) {
disp = disp + 8;
}
// Not Indexing
if (!is_index) {
AddAddrRegOp(inst, kIntRegName[enc.rn], kMemSize, kMemAction, pc_adjust);
@@ -1697,6 +1753,7 @@ static bool TryDecodeLoadStoreWordUBReg(Instruction &inst, uint32_t bits) {
}
AddShiftRegImmOperand(inst, enc.rm, enc.type, enc.imm5, 0u);
auto disp_expr = inst.operands.back().expr;
auto disp_op = llvm::Instruction::Add;
inst.operands.pop_back();
@@ -1750,11 +1807,11 @@ static const char *const kLoadStoreDHSB[] = {
[0b11101] = "LDRHp", [0b11110] = "LDRSBp", [0b11111] = "LDRSHp",
};
//P:W o1 Rn op2
// P:W o1 Rn op2
// 0 1111 10 LDRD (literal) if Rt<0> == '1' t2 == 15 || wback then UNPREDICTABLE;
//!= 01 1 1111 01 LDRH (literal) if t == 15 || wback then UNPREDICTABLE;
//!= 01 1 1111 10 LDRSB (literal) if t == 15 || wback then UNPREDICTABLE;
//!= 01 1 1111 11 LDRSH (literal) if t == 15 || wback then UNPREDICTABLE;
// != 01 1 1111 01 LDRH (literal) if t == 15 || wback then UNPREDICTABLE;
// != 01 1 1111 10 LDRSB (literal) if t == 15 || wback then UNPREDICTABLE;
// != 01 1 1111 11 LDRSH (literal) if t == 15 || wback then UNPREDICTABLE;
// 00 0 != 1111 10 LDRD (immediate) — post-indexed if t2 == 15 wback && (n == t || n == t2) then UNPREDICTABLE;
// 00 0 01 STRH (immediate) — post-indexed if t == 15 wback && (n == 15 || n == t) then UNPREDICTABLE;
// 00 0 11 STRD (immediate) — post-indexed if t2 == 15 wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
@@ -2221,10 +2278,10 @@ static InstEval *kLogArithEvaluators[] = {
},
};
//00 ORR, ORRS (register) -- rd, rn, & rm
//01 MOV, MOVS (register) -- rd, & rm only
//10 BIC, BICS (register) -- rd, rn, & rm
//11 MVN, MVNS (register) -- rd, & rm only
// 00 ORR, ORRS (register) -- rd, rn, & rm
// 01 MOV, MOVS (register) -- rd, & rm only
// 10 BIC, BICS (register) -- rd, rn, & rm
// 11 MVN, MVNS (register) -- rd, & rm only
static const char *const kLogicalArithmeticRRRI[] = {
[0b000] = "ORRrr", [0b001] = "ORRSrr", [0b010] = "MOVrr",
[0b011] = "MOVSrr", [0b100] = "BICrr", [0b101] = "BICSrr",
@@ -2253,7 +2310,12 @@ static bool TryLogicalArithmeticRRRI(Instruction &inst, uint32_t bits) {
AddImmOp(inst, ~0u);
}
AddShiftRegImmOperand(inst, enc.rm, enc.type, enc.imm5, enc.s);
if (enc.type) {
AddShiftRegImmOperand(inst, enc.rm, enc.type, enc.imm5, enc.s);
} else {
AddIntRegOp(inst, enc.rm, 32, Operand::kActionRead);
}
return EvalPCDest(inst, enc.s, enc.rd, kLogArithEvaluators[enc.opc >> 1u],
is_cond);
}
@@ -2271,7 +2333,6 @@ static bool TryLogicalArithmeticRRRR(Instruction &inst, uint32_t bits) {
inst.function = kLogicalArithmeticRRRI[enc.opc << 1u | enc.s];
DecodeCondition(inst, enc.cond);
AddIntRegOp(inst, enc.rd, 32, Operand::kActionWrite);
// enc.opc == x0
@@ -2345,10 +2406,10 @@ static bool TryDecodeMoveHalfword(Instruction &inst, uint32_t bits) {
return true;
}
//00 TST (register)
//01 TEQ (register)
//10 CMP (register)
//11 CMN (register)
// 00 TST (register)
// 01 TEQ (register)
// 10 CMP (register)
// 11 CMN (register)
static const char *const kIntegerTestAndCompareR[] = {
[0b00] = "TSTr",
[0b01] = "TEQr",
@@ -2408,9 +2469,9 @@ static bool TryIntegerTestAndCompareRI(Instruction &inst, uint32_t bits) {
}
// cond H
//!= 1111 0 B
//!= 1111 1 BL, BLX (immediate) — A1
//1111 BL, BLX (immediate) — A2
// != 1111 0 B
// != 1111 1 BL, BLX (immediate) — A1
// 1111 BL, BLX (immediate) — A2
// Branch (immediate)
static bool TryBranchImm(Instruction &inst, uint32_t bits) {
const BranchI enc = {bits};
@@ -2508,17 +2569,20 @@ static bool TryDecodeBX(Instruction &inst, uint32_t bits) {
AddAddrRegOp(inst, "NEXT_PC", 32u, Operand::kActionRead, 0);
} else if (enc.Rm == kLRRegNum) {
inst.category = Instruction::kCategoryFunctionReturn;
AddAddrRegOp(inst, "NEXT_PC", 32u, Operand::kActionRead, 0);
} else if (is_cond) {
inst.category = Instruction::kCategoryConditionalIndirectJump;
AddAddrRegOp(inst, "NEXT_PC", 32u, Operand::kActionRead, 0);
} else if (enc.op1 == 0b01) {
inst.category = Instruction::kCategoryIndirectJump;
AddAddrRegOp(inst, "NEXT_PC", 32u, Operand::kActionRead, 0);
}
} else if (is_cond) {
inst.category = Instruction::kCategoryConditionalDirectFunctionCall;
AddAddrRegOp(inst, "NEXT_PC", 32u, Operand::kActionRead, 0);
} else {
inst.category = Instruction::kCategoryDirectFunctionCall;
AddAddrRegOp(inst, "NEXT_PC", 32u, Operand::kActionRead, 0);
}
Operand::Register reg;
@@ -2727,35 +2791,35 @@ static bool TryBitExtract(Instruction &inst, uint32_t bits) {
}
// op0 op1
//00xxx Parallel Arithmetic
//01000 101 SEL
//01000 001 UNALLOCATED
//01000 xx0 PKHBT, PKHTB
//01001 x01 UNALLOCATED
//01001 xx0 UNALLOCATED
//0110x x01 UNALLOCATED
//0110x xx0 UNALLOCATED
//01x10 001 Saturate 16-bit
//01x10 101 UNALLOCATED
//01x11 x01 Reverse Bit/Byte
//01x1x xx0 Saturate 32-bit
//01xxx 111 UNALLOCATED
//01xxx 011 Extend and Add
//10xxx Signed multiply, Divide
//11000 000 Unsigned Sum of Absolute Differences
//11000 100 UNALLOCATED
//11001 x00 UNALLOCATED
//1101x x00 UNALLOCATED
//110xx 111 UNALLOCATED
//1110x 111 UNALLOCATED
//1110x x00 Bitfield Insert
//11110 111 UNALLOCATED
//11111 111 Permanently UNDEFINED
//1111x x00 UNALLOCATED
//11x0x x10 UNALLOCATED
//11x1x x10 Bitfield Extract
//11xxx 011 UNALLOCATED
//11xxx x01 UNALLOCATED
// 00xxx Parallel Arithmetic
// 01000 101 SEL
// 01000 001 UNALLOCATED
// 01000 xx0 PKHBT, PKHTB
// 01001 x01 UNALLOCATED
// 01001 xx0 UNALLOCATED
// 0110x x01 UNALLOCATED
// 0110x xx0 UNALLOCATED
// 01x10 001 Saturate 16-bit
// 01x10 101 UNALLOCATED
// 01x11 x01 Reverse Bit/Byte
// 01x1x xx0 Saturate 32-bit
// 01xxx 111 UNALLOCATED
// 01xxx 011 Extend and Add
// 10xxx Signed multiply, Divide
// 11000 000 Unsigned Sum of Absolute Differences
// 11000 100 UNALLOCATED
// 11001 x00 UNALLOCATED
// 1101x x00 UNALLOCATED
// 110xx 111 UNALLOCATED
// 1110x 111 UNALLOCATED
// 1110x x00 Bitfield Insert
// 11110 111 UNALLOCATED
// 11111 111 Permanently UNDEFINED
// 1111x x00 UNALLOCATED
// 11x0x x10 UNALLOCATED
// 11x1x x10 Bitfield Extract
// 11xxx 011 UNALLOCATED
// 11xxx x01 UNALLOCATED
static TryDecode *TryMedia(uint32_t bits) {
const Media enc = {bits};
@@ -2835,22 +2899,22 @@ static TryDecode *TryMedia(uint32_t bits) {
}
}
//00 001 UNALLOCATED
//00 010 UNALLOCATED
//00 011 UNALLOCATED
//00 110 UNALLOCATED
//01 001 BX
//01 010 BXJ
//01 011 BLX (register)
//01 110 UNALLOCATED
//10 001 UNALLOCATED
//10 010 UNALLOCATED
//10 011 UNALLOCATED
//10 110 UNALLOCATED
//11 001 CLZ
//11 010 UNALLOCATED
//11 011 UNALLOCATED
//11 110 ERET
// 00 001 UNALLOCATED
// 00 010 UNALLOCATED
// 00 011 UNALLOCATED
// 00 110 UNALLOCATED
// 01 001 BX
// 01 010 BXJ
// 01 011 BLX (register)
// 01 110 UNALLOCATED
// 10 001 UNALLOCATED
// 10 010 UNALLOCATED
// 10 011 UNALLOCATED
// 10 110 UNALLOCATED
// 11 001 CLZ
// 11 010 UNALLOCATED
// 11 011 UNALLOCATED
// 11 110 ERET
// 111 Exception Generation
// 000 Move special register (register)
// 100 Cyclic Redundancy Check
@@ -3118,7 +3182,7 @@ static TryDecode *kMLoadStore[] = {
};
// Corresponds to: Data-processing and miscellaneous instructions
//op0 op1 op2 op3 op4
// op0 op1 op2 op3 op4
// 0 1 != 00 1 Extra load/store
// 0 0xxxx 1 00 1 Multiply and Accumulate
// 0 1xxxx 1 00 1 Synchronization primitives and Load-Acquire/Store-Release
@@ -3157,6 +3221,7 @@ static TryDecode *TryDataProcessingAndMisc(uint32_t bits) {
return nullptr;
}
}
// op1 == 10xx0
} else if (((enc.op1 >> 3) == 0b10u) && !(enc.op1 & 0b00001u)) {
@@ -3168,6 +3233,7 @@ static TryDecode *TryDataProcessingAndMisc(uint32_t bits) {
} else {
return TryHalfwordDecodeMultiplyAndAccumulate;
}
// op1 != 10xx0
} else {
@@ -3196,10 +3262,10 @@ static TryDecode *TryDataProcessingAndMisc(uint32_t bits) {
// Instructions are grouped into subsets based on this the top level and then
// into smaller sets.
// cond op0 op1
//!= 1111 00x Data-processing and miscellaneous instructions
//!= 1111 010 Load/Store Word, Unsigned Byte (immediate, literal)
//!= 1111 011 0 Load/Store Word, Unsigned Byte (register)
//!= 1111 011 1 Media instructions
// != 1111 00x Data-processing and miscellaneous instructions
// != 1111 010 Load/Store Word, Unsigned Byte (immediate, literal)
// != 1111 011 0 Load/Store Word, Unsigned Byte (register)
// != 1111 011 1 Media instructions
// 10x Branch, branch with link, and block data transfer
// 11x System register access, Advanced SIMD, floating-point, and Supervisor call
// 1111 0xx Unconditional instructions
@@ -3299,7 +3365,7 @@ bool AArch32Arch::DecodeInstruction(uint64_t address,
auto decoder = TryDecodeTopLevelEncodings(bits);
if (!decoder) {
LOG(ERROR) << "unhandled bits";
LOG(ERROR) << "unhandled bits " << std::hex << bits << std::dec;
return false;
}
+6 -6
View File
@@ -64,15 +64,15 @@ DEF_ISEL(INVALID_INSTRUCTION) = HandleInvalidInstruction;
#include "lib/Arch/AArch32/Semantics/BITBYTE.cpp"
#include "lib/Arch/AArch32/Semantics/BRANCH.cpp"
//#include "lib/Arch/AArch32/Semantics/CALL_RET.cpp"
// #include "lib/Arch/AArch32/Semantics/CALL_RET.cpp"
#include "lib/Arch/AArch32/Semantics/COND.cpp"
//#include "lib/Arch/AArch32/Semantics/CONVERT.cpp"
//#include "lib/Arch/AArch32/Semantics/DATAXFER.cpp"
// #include "lib/Arch/AArch32/Semantics/CONVERT.cpp"
// #include "lib/Arch/AArch32/Semantics/DATAXFER.cpp"
#include "lib/Arch/AArch32/Semantics/MISC.cpp"
//#include "lib/Arch/AArch32/Semantics/SHIFT.cpp"
//#include "lib/Arch/AArch32/Semantics/SIMD.cpp"
//#include "lib/Arch/AArch32/Semantics/SYSTEM.cpp"
// #include "lib/Arch/AArch32/Semantics/SHIFT.cpp"
// #include "lib/Arch/AArch32/Semantics/SIMD.cpp"
// #include "lib/Arch/AArch32/Semantics/SYSTEM.cpp"
// clang-format on
+2 -2
View File
@@ -160,7 +160,7 @@ template <typename F, typename T>
ALWAYS_INLINE static auto CheckedFloatUnaryOp(State &state, F func, T arg1)
-> decltype(func(arg1)) {
//state.sr.idc |= IsDenormal(arg1);
// state.sr.idc |= IsDenormal(arg1);
auto old_except = __remill_fpu_exception_test_and_clear(0, FE_ALL_EXCEPT);
BarrierReorder();
auto res = func(arg1);
@@ -176,7 +176,7 @@ ALWAYS_INLINE static auto CheckedFloatBinOp(State &state, F func, T arg1,
T arg2)
-> decltype(func(arg1, arg2)) {
//state.sr.idc |= IsDenormal(arg1) | IsDenormal(arg2);
// state.sr.idc |= IsDenormal(arg1) | IsDenormal(arg2);
auto old_except = __remill_fpu_exception_test_and_clear(0, FE_ALL_EXCEPT);
BarrierReorder();
auto res = func(arg1, arg2);
+3 -3
View File
@@ -421,12 +421,12 @@ DEF_ISEL(LDMDA) = LDM;
DEF_ISEL(STM) = STMDB;
DEF_ISEL(LDM) = LDM;
//DEF_ISEL(STMu) = STMu;
// DEF_ISEL(STMu) = STMu;
DEF_ISEL(STMDB) = STMDB;
DEF_ISEL(LDMDB) = LDM;
//DEF_ISEL(LDMu) = LDMu;
// DEF_ISEL(LDMu) = LDMu;
DEF_ISEL(STMIB) = STMDB;
DEF_ISEL(LDMIB) = LDM;
//DEF_ISEL(LDMe) = LDMe;
// DEF_ISEL(LDMe) = LDMe;
+8 -4
View File
@@ -272,7 +272,10 @@ std::string Operand::Serialize(void) const {
ss << ")"; // End of `(ADDR_`.
break;
}
case Operand::kTypeExpression: ss << expr->Serialize(); break;
case Operand::kTypeExpression:
case Operand::kTypeRegisterExpression:
case Operand::kTypeImmediateExpression:
case Operand::kTypeAddressExpression: ss << expr->Serialize(); break;
}
ss << ")";
return ss.str();
@@ -384,8 +387,9 @@ OperandExpression *Instruction::EmplaceUnaryOp(unsigned opcode,
Operand &Instruction::EmplaceOperand(const Operand::Register &reg_op) {
operands.emplace_back();
auto &op = operands.back();
op.type = Operand::kTypeExpression;
op.type = Operand::kTypeRegisterExpression;
op.size = reg_op.size;
op.reg.name = reg_op.name;
if (auto reg = arch->RegisterByName(reg_op.name)) {
op.expr = EmplaceRegister(reg);
} else {
@@ -405,7 +409,7 @@ Operand &Instruction::EmplaceOperand(const Operand::Immediate &imm_op) {
op.expr =
EmplaceConstant(llvm::ConstantInt::get(ty, imm_op.val, imm_op.is_signed));
op.size = arch->address_size;
op.type = Operand::kTypeExpression;
op.type = Operand::kTypeImmediateExpression;
return op;
}
@@ -631,7 +635,7 @@ Operand &Instruction::EmplaceOperand(const Operand::Address &addr_op) {
addr = EmplaceUnaryOp(llvm::Instruction::ZExt, addr, word_type);
}
op.expr = addr;
op.type = Operand::kTypeExpression;
op.type = Operand::kTypeAddressExpression;
return op;
}
+3
View File
@@ -869,6 +869,9 @@ InstructionLifter::LiftOperand(Instruction &inst, llvm::BasicBlock *block,
return LiftAddressOperand(inst, block, state_ptr, arg, arch_op);
case Operand::kTypeExpression:
case Operand::kTypeRegisterExpression:
case Operand::kTypeImmediateExpression:
case Operand::kTypeAddressExpression:
return LiftExpressionOperand(inst, block, state_ptr, arg, arch_op);
}
+23 -1
View File
@@ -1,6 +1,12 @@
#!/usr/bin/env python3
# Copyright 2020, Trail of Bits, Inc. All rights reserved.
#
# Copyright (c) 2021-present, Trail of Bits, Inc.
# All rights reserved.
#
# This source code is licensed in accordance with the terms specified in
# the LICENSE file found in the root directory of this source tree.
#
import argparse
import itertools
@@ -14,6 +20,18 @@ import shutil
REFLOW_COMMENT = "// !!! REFLOW-COMMENT"
def add_space_in_comm(line):
unindented_line = line.lstrip("\t ")
if unindented_line.startswith("//"):
if len(unindented_line) == 2:
return line
# if it does not have a space, reformat it
if unindented_line[2] != " ":
line_pos = line.find("//")
res = line[:line_pos+2] + " " + line[line_pos+2:]
return res
return line
def find_comment_lines(path):
new_lines = []
@@ -182,6 +200,10 @@ def main():
new_lines, has_error = run_clang_format_on_lines(
args.format_exe, format_file, cxx_file, new_lines)
if not has_error:
for i, line in enumerate(new_lines):
new_line = add_space_in_comm(line)
if new_line != line:
new_lines[i] = new_line
fixup_file(cxx_file, new_lines, old_comments)
if in_place_files: