Skip to content

Commit

Permalink
Added all data Integer processing instructions without S + ADDS and s…
Browse files Browse the repository at this point in the history
…tarted ANDS
  • Loading branch information
sschriner committed Sep 23, 2020
1 parent f292370 commit b83e040
Show file tree
Hide file tree
Showing 11 changed files with 560 additions and 8 deletions.
9 changes: 8 additions & 1 deletion remill/Arch/AArch32/Arch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ void AArch32Arch::PopulateBasicBlockFunction(llvm::Module *module,
<< "the bitcode module";

auto &context = module->getContext();
// auto u8 = llvm::Type::getInt8Ty(context);
auto u8 = llvm::Type::getInt8Ty(context);
// auto u16 = llvm::Type::getInt16Ty(context);
auto u32 = llvm::Type::getInt32Ty(context);
// auto u64 = llvm::Type::getInt64Ty(context);
Expand Down Expand Up @@ -157,10 +157,17 @@ void AArch32Arch::PopulateBasicBlockFunction(llvm::Module *module,
SUB_REG(LR, gpr.r14.dword, u32, R14);
SUB_REG(PC, gpr.r15.dword, u32, R15);

REG(N, sr.n, u8);
REG(C, sr.c, u8);
REG(Z, sr.z, u8);
REG(V, sr.v, u8);

const auto pc_arg = NthArgument(bb_func, kPCArgNum);
const auto state_ptr_arg = NthArgument(bb_func, kStatePointerArgNum);
ir.CreateStore(pc_arg, ir.CreateAlloca(addr, nullptr, "NEXT_PC"));

auto zero_c = ir.CreateAlloca(u8, nullptr, "ZERO_C");
ir.CreateStore(llvm::Constant::getNullValue(u8), zero_c);
ir.CreateAlloca(u32, nullptr, "SUPPRESS_WRITEBACK");
(void) this->RegisterByName("PC")->AddressOf(state_ptr_arg, ir);
}
Expand Down
108 changes: 106 additions & 2 deletions remill/Arch/AArch32/Decode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ static Operand::ShiftRegister::Shift GetOperandShift(Shift s) {
static void AddShiftRegOperand(Instruction &inst,
uint32_t reg_num, uint32_t shift_type,
uint32_t shift_size) {
auto is_rrx = false;
if (!shift_size && shift_type == Shift::kShiftROR) {
shift_size = 1;
is_rrx = true;

This comment has been minimized.

Copy link
@pgoodman

pgoodman Sep 23, 2020

Collaborator

Let's use this below on line 114.

}
if (!shift_size) {
AddIntRegOp(inst, reg_num, 32, Operand::kActionRead);
} else {
Expand All @@ -117,6 +122,66 @@ static void AddShiftRegOperand(Instruction &inst,
}
}

static void AddShiftCarryOperand(Instruction &inst,
uint32_t reg_num, uint32_t shift_type,
uint32_t shift_size, const char * carry_reg_name) {
inst.operands.emplace_back();
auto &op = inst.operands.back();
op.shift_reg.extract_size = 1;
op.shift_reg.extend_op = Operand::ShiftRegister::kExtendUnsigned;

auto is_rrx = false;
if (!shift_size && shift_type == Shift::kShiftROR) {
shift_size = 1;
is_rrx = true;
}

if (!shift_size) {
op.shift_reg.reg.name = carry_reg_name;
op.shift_reg.reg.size = 8;
op.shift_reg.shift_op = Operand::ShiftRegister::kShiftLeftWithZeroes;
op.shift_reg.shift_size = 0;
} else {
op.shift_reg.reg.name = kIntRegName[reg_num];
op.shift_reg.reg.size = 32;
switch (static_cast<Shift>(shift_type)) {
case Shift::kShiftASR:
op.shift_reg.shift_size = shift_size - 1;
op.shift_reg.shift_op = Operand::ShiftRegister::kShiftSignedRight;
break;
case Shift::kShiftLSL:
op.shift_reg.shift_size = 32 - shift_size;
op.shift_reg.shift_op = Operand::ShiftRegister::kShiftUnsignedRight;
break;
case Shift::kShiftLSR:
op.shift_reg.shift_size = shift_size - 1;
op.shift_reg.shift_op = Operand::ShiftRegister::kShiftUnsignedRight;
break;
case Shift::kShiftROR:
if (is_rrx) {

} else {
op.shift_reg.shift_size = (shift_size + 31) % 32;
op.shift_reg.shift_op = Operand::ShiftRegister::kShiftUnsignedRight;
}
break;
}

if (shift_type == Shift::kShiftLSR || shift_type == Shift::kShiftASR) {
if (!shift_size) {

This comment has been minimized.

Copy link
@pgoodman

pgoodman Sep 23, 2020

Collaborator

I don't think this condition is reachable, as this code is dominated by a check 9n line 139 if (!shift_size).

shift_size = 32;
}
} else if (shift_type == Shift::kShiftROR) {
LOG_IF(FATAL, !shift_size)

This comment has been minimized.

Copy link
@pgoodman

pgoodman Sep 23, 2020

Collaborator

We can remove this.

<< "Invalid use of AddShiftRegOperand RRX shifts not supported";
}
op.shift_reg.shift_size = shift_size;
op.type = Operand::kTypeShiftRegister;
op.size = 32;
op.action = Operand::kActionRead;
}
}

// Decode the condition field and fil in the instruction conditions accordingly
static void DecodeCondition(Instruction &inst, uint32_t cond) {
inst.conditions.emplace_back();
Expand Down Expand Up @@ -214,6 +279,40 @@ static void DecodeCondition(Instruction &inst, uint32_t cond) {
}
}

//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)
// High 3 bit opc and low bit s, opc:s
static const char * const kIdpNames[] = {
[0b0000] = "ANDrr",
[0b0001] = "ANDSrr",
[0b0010] = "EORrr",
[0b0011] = "EORSrr",
[0b0100] = "SUBrr",
[0b0101] = "SUBSrr",
[0b0110] = "RSBrr",
[0b0111] = "RSBSrr",
[0b1000] = "ADDrr",
[0b1001] = "ADDSrr",
[0b1010] = "ADCrr",
[0b1011] = "ADCSrr",
[0b1100] = "SBCrr",
[0b1101] = "SBCSrr",
[0b1110] = "RSCrr",
[0b1111] = "RSCSrr"
};

static bool TryDecodeIntegerDataProcessing(Instruction &inst, uint32_t bits) {
const IntDataProcessing enc = {bits};
if (enc.cond == 0b1111u) {
Expand All @@ -222,14 +321,19 @@ static bool TryDecodeIntegerDataProcessing(Instruction &inst, uint32_t bits) {
if (enc.opc == 0b010u || enc.opc == 0b100u) {

}

inst.function = kIdpNames[ (enc.opc << 1u) | enc.s];
DecodeCondition(inst, enc.cond);
AddIntRegOp(inst, enc.rd, 32, Operand::kActionWrite);
AddIntRegOp(inst, enc.rn, 32, Operand::kActionRead);
AddShiftRegOperand(inst, enc.rm, enc.type, enc.imm5);

if (enc.rd == kPCRegNum) {
inst.category = Instruction::kCategoryIndirectJump;
if (enc.s) { // Updates the flags (condition codes)
inst.category = Instruction::kCategoryError;
return false;
} else {
inst.category = Instruction::kCategoryIndirectJump;
}
} else {
inst.category = Instruction::kCategoryNormal;
}
Expand Down
3 changes: 3 additions & 0 deletions remill/Arch/AArch32/Runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ function(add_runtime_helper target_name address_bit_size little_endian)
INSTALLDESTINATION "${install_folder}"

DEPENDENCIES
"${CMAKE_SOURCE_DIR}/remill/Arch/AArch32/Semantics/BINARY.cpp"
"${CMAKE_SOURCE_DIR}/remill/Arch/AArch32/Semantics/FLAGS.cpp"


)
endfunction()
Expand Down
8 changes: 4 additions & 4 deletions remill/Arch/AArch32/Runtime/Instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
#include "remill/Arch/Runtime/Intrinsics.h"
#include "remill/Arch/Runtime/Operators.h"
#include "remill/Arch/AArch32/Runtime/State.h"
//#include "remill/Arch/AArch32/Runtime/Types.h"
//#include "remill/Arch/AArch32/Runtime/Operators.h"
#include "remill/Arch/AArch32/Runtime/Types.h"
#include "remill/Arch/AArch32/Runtime/Operators.h"

// clang-format on

Expand Down Expand Up @@ -56,9 +56,9 @@ DEF_ISEL(UNSUPPORTED_INSTRUCTION) = HandleUnsupported;
DEF_ISEL(INVALID_INSTRUCTION) = HandleInvalidInstruction;

// clang-format off
//#include "remill/Arch/AArch64/Semantics/FLAGS.cpp"
#include "remill/Arch/AArch32/Semantics/FLAGS.cpp"
//
//#include "remill/Arch/AArch64/Semantics/BINARY.cpp"
#include "remill/Arch/AArch32/Semantics/BINARY.cpp"
//#include "remill/Arch/AArch64/Semantics/BITBYTE.cpp"
//#include "remill/Arch/AArch64/Semantics/BRANCH.cpp"
//#include "remill/Arch/AArch64/Semantics/CALL_RET.cpp"
Expand Down
32 changes: 32 additions & 0 deletions remill/Arch/AArch32/Runtime/Operators.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2017 Trail of Bits, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

namespace {

// Read a register directly. Sometimes this is needed for suppressed operands.
ALWAYS_INLINE static addr_t _Read(Memory *, Reg reg) {
return reg.aword;
}

// Write directly to a register. This is sometimes needed for suppressed
// register operands.
ALWAYS_INLINE static void _Write(Memory *, Reg &reg, addr_t val) {
reg.aword = val;
}

} // namespace
28 changes: 28 additions & 0 deletions remill/Arch/AArch32/Runtime/State.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,38 @@ struct alignas(8) GPR final {

} __attribute__((packed));

// System registers affecting control and status of the machine.
struct alignas(8) SR final {

uint8_t _2;
uint8_t n; // Negative condition flag.
uint8_t _3;
uint8_t z; // Zero condition flag
uint8_t _4;
uint8_t c; // Carry condition flag
uint8_t _5;
uint8_t v; // Overflow condition flag

uint8_t _6;
uint8_t ixc; // Inexact (cumulative).
uint8_t _7;
uint8_t ofc; // Overflow (cumulative).
uint8_t _8;
uint8_t ufc; // Underflow (cumulative).
uint8_t _9;
uint8_t idc; // Input denormal (cumulative).
uint8_t _10;
uint8_t ioc; // Invalid operation (cumulative).

uint8_t _padding[6];
} __attribute__((packed));

struct alignas(16) State final : public ArchState {


GPR gpr; // 528 bytes.
SR sr;
uint64_t _0;


} __attribute__((packed));
Expand Down
73 changes: 73 additions & 0 deletions remill/Arch/AArch32/Runtime/Types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2017 Trail of Bits, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

// We need this for boolean conditions, used in branch instructions.
typedef RnW<uint8_t> R8W;

typedef RnW<uint8_t> R8W;
typedef RnW<uint16_t> R16W;

// Note: AArch64 zero-extends like x86, but the smallest register size that
// can be accessed is 32 bits.
typedef RnW<uint32_t> R32W;

//typedef Rn<uint8_t> R8;
//typedef Rn<uint16_t> R16;
typedef Rn<uint32_t> R32;

typedef Vn<vec8_t> V8;
typedef Vn<vec16_t> V16;
typedef Vn<vec32_t> V32;
typedef Vn<vec64_t> V64;
typedef Vn<vec128_t> V128;
typedef VnW<vec128_t> V128W;

typedef MnW<uint8_t> M8W;
typedef MnW<uint16_t> M16W;
typedef MnW<uint32_t> M32W;
typedef MnW<uint64_t> M64W;

typedef MVnW<vec8_t> MV8W;
typedef MVnW<vec16_t> MV16W;
typedef MVnW<vec32_t> MV32W;
typedef MVnW<vec64_t> MV64W;
typedef MVnW<vec128_t> MV128W;

typedef Mn<uint8_t> M8;
typedef Mn<uint16_t> M16;

typedef Mn<uint32_t> M32;
typedef Mn<uint64_t> M64;

typedef MVn<vec8_t> MV8;
typedef MVn<vec16_t> MV16;
typedef MVn<vec32_t> MV32;
typedef MVn<vec64_t> MV64;
typedef MVn<vec128_t> MV128;
typedef MVn<vec256_t> MV256;

typedef In<uint8_t> I8;
typedef In<uint16_t> I16;
typedef In<uint32_t> I32;
typedef In<uint64_t> I64;

typedef In<float32_t> F32;
typedef In<float64_t> F64;

typedef In<addr_t> PC;
typedef In<addr_t> ADDR;
Loading

0 comments on commit b83e040

Please sign in to comment.