Commit 83751ac9 authored by swift_gan's avatar swift_gan Committed by swift_gan

add B.cond & TBZ_TBNZ

parent 91f6050c
...@@ -93,7 +93,7 @@ void A64_MOV_WIDE::assembler() { ...@@ -93,7 +93,7 @@ void A64_MOV_WIDE::assembler() {
void A64_MOV_WIDE::decode(aarch64_mov_wide *inst) { void A64_MOV_WIDE::decode(aarch64_mov_wide *inst) {
imme = static_cast<U16>(inst->imm16); imme = static_cast<U16>(inst->imm16);
shift = static_cast<U8>(inst->hw * 16); shift = static_cast<U8>(inst->hw * 16);
op = static_cast<OP>(inst->opc); op = OP(inst->opc);
if (inst->sf == 1) { if (inst->sf == 1) {
rd = XRegister::get(static_cast<U8>(inst->rd)); rd = XRegister::get(static_cast<U8>(inst->rd));
} else { } else {
...@@ -120,7 +120,7 @@ ADDR A64_B_BL::getImmPCOffset() { ...@@ -120,7 +120,7 @@ ADDR A64_B_BL::getImmPCOffset() {
} }
void A64_B_BL::decode(aarch64_b_bl *inst) { void A64_B_BL::decode(aarch64_b_bl *inst) {
op = static_cast<OP>(inst->op); op = OP(inst->op);
offset = getImmPCOffset(); offset = getImmPCOffset();
} }
...@@ -136,14 +136,22 @@ void A64_B_BL::assembler() { ...@@ -136,14 +136,22 @@ void A64_B_BL::assembler() {
A64_CBZ_CBNZ::A64_CBZ_CBNZ() {} A64_CBZ_CBNZ::A64_CBZ_CBNZ() {}
A64_CBZ_CBNZ::A64_CBZ_CBNZ(aarch64_cbz_cbnz *inst) : A64_INST_PC_REL(inst) {} A64_CBZ_CBNZ::A64_CBZ_CBNZ(aarch64_cbz_cbnz *inst) : A64_INST_PC_REL(inst) {
decode(inst);
}
A64_CBZ_CBNZ::A64_CBZ_CBNZ(A64_CBZ_CBNZ::OP op, ADDR offset, RegisterA64 *rt) : op(op),
offset(offset),
rt(rt) {
assembler();
}
ADDR A64_CBZ_CBNZ::getImmPCOffset() { ADDR A64_CBZ_CBNZ::getImmPCOffset() {
return signExtend64(19 + 2, COMBINE(get()->imm19, 0b00, 2)); return signExtend64(19 + 2, COMBINE(get()->imm19, 0b00, 2));
} }
void A64_CBZ_CBNZ::decode(aarch64_cbz_cbnz *inst) { void A64_CBZ_CBNZ::decode(aarch64_cbz_cbnz *inst) {
op = static_cast<OP>(get()->op); op = OP(get()->op);
if (inst->sf == 1) { if (inst->sf == 1) {
rt = XRegister::get(static_cast<U8>(inst->rt)); rt = XRegister::get(static_cast<U8>(inst->rt));
} else { } else {
...@@ -160,3 +168,70 @@ void A64_CBZ_CBNZ::assembler() { ...@@ -160,3 +168,70 @@ void A64_CBZ_CBNZ::assembler() {
get()->imm19 = TruncateToUint19(offset); get()->imm19 = TruncateToUint19(offset);
} }
//B.Cond
A64_B_COND::A64_B_COND() {}
A64_B_COND::A64_B_COND(aarch64_b_cond *inst) : A64_INST_PC_REL(inst) {
decode(inst);
}
A64_B_COND::A64_B_COND(Condition condition, ADDR offset) : condition(condition), offset(offset) {
assembler();
}
ADDR A64_B_COND::getImmPCOffset() {
return signExtend64(19 + 2, COMBINE(get()->imm19, 0b00, 2));
}
void A64_B_COND::decode(aarch64_b_cond *inst) {
condition = Condition(inst->cond);
offset = getImmPCOffset();
}
void A64_B_COND::assembler() {
get()->opcode = CBZ_B_COND_OPCODE;
get()->cond = condition;
get()->imm19 = TruncateToUint19(offset);
}
//TBZ TBNZ
A64_TBZ_TBNZ::A64_TBZ_TBNZ() {}
A64_TBZ_TBNZ::A64_TBZ_TBNZ(aarch64_tbz_tbnz *inst) : A64_INST_PC_REL(inst) {
decode(inst);
}
A64_TBZ_TBNZ::A64_TBZ_TBNZ(A64_TBZ_TBNZ::OP op, RegisterA64 *rt, U32 bit, ADDR offset) : op(op),
rt(rt),
bit(bit),
offset(offset) {
assembler();
}
ADDR A64_TBZ_TBNZ::getImmPCOffset() {
return signExtend64(14, get()->imm14) << 2;
}
void A64_TBZ_TBNZ::decode(aarch64_tbz_tbnz *inst) {
bit = COMBINE(inst->b5, inst->b40, 5);
if (inst->b5 == 1) {
rt = XRegister::get(static_cast<U8>(inst->rt));
} else {
rt = WRegister::get(static_cast<U8>(inst->rt));
}
op = OP(inst->op);
offset = getImmPCOffset();
}
void A64_TBZ_TBNZ::assembler() {
get()->opcode = TBZ_TBNZ_OPCODE;
get()->op = op;
get()->b5 = rt->is64Bit() ? 1 : 0;
get()->rt = rt->getCode();
get()->b40 = BITS(bit, sizeof(U32) - 5, sizeof(U32));
get()->imm14 = TruncateToUint14(offset);
}
\ No newline at end of file
...@@ -220,6 +220,12 @@ namespace SandHook { ...@@ -220,6 +220,12 @@ namespace SandHook {
A64_CBZ_CBNZ(aarch64_cbz_cbnz *inst); A64_CBZ_CBNZ(aarch64_cbz_cbnz *inst);
A64_CBZ_CBNZ(OP op, ADDR offset, RegisterA64 *rt);
inline U32 instCode() override {
return op == CBZ ? CompareBranchOp::CBZ : CompareBranchOp::CBNZ;
}
ADDR getImmPCOffset() override; ADDR getImmPCOffset() override;
void decode(aarch64_cbz_cbnz *inst) override; void decode(aarch64_cbz_cbnz *inst) override;
...@@ -232,6 +238,62 @@ namespace SandHook { ...@@ -232,6 +238,62 @@ namespace SandHook {
RegisterA64* rt; RegisterA64* rt;
}; };
class A64_B_COND : public A64_INST_PC_REL<aarch64_b_cond> {
public:
A64_B_COND();
A64_B_COND(aarch64_b_cond *inst);
A64_B_COND(Condition condition, ADDR offset);
inline U32 instCode() override {
return B_cond;
}
ADDR getImmPCOffset() override;
void decode(aarch64_b_cond *inst) override;
void assembler() override;
private:
Condition condition;
ADDR offset;
};
class A64_TBZ_TBNZ : public A64_INST_PC_REL<aarch64_tbz_tbnz> {
public:
enum OP {
TBZ,
TBNZ
};
A64_TBZ_TBNZ();
A64_TBZ_TBNZ(aarch64_tbz_tbnz *inst);
A64_TBZ_TBNZ(OP op, RegisterA64 *rt, U32 bit, ADDR offset);
inline U32 instCode() override {
return op == TBZ ? TestBranchOp::TBZ : TestBranchOp::TBNZ;
};
ADDR getImmPCOffset() override;
void decode(aarch64_tbz_tbnz *inst) override;
void assembler() override;
private:
OP op;
RegisterA64* rt;
U32 bit;
ADDR offset;
};
} }
} }
......
...@@ -52,4 +52,34 @@ enum UnconditionalBranchOp { ...@@ -52,4 +52,34 @@ enum UnconditionalBranchOp {
BL = UnconditionalBranchFixed | 0x80000000 BL = UnconditionalBranchFixed | 0x80000000
}; };
// Compare and branch.
enum CompareBranchOp {
CompareBranchFixed = 0x34000000,
CompareBranchFMask = 0x7E000000,
CompareBranchMask = 0xFF000000,
CBZ_w = CompareBranchFixed | 0x00000000,
CBZ_x = CompareBranchFixed | 0x80000000,
CBZ = CBZ_w,
CBNZ_w = CompareBranchFixed | 0x01000000,
CBNZ_x = CompareBranchFixed | 0x81000000,
CBNZ = CBNZ_w
};
// Conditional branch.
enum ConditionalBranchOp {
ConditionalBranchFixed = 0x54000000,
ConditionalBranchFMask = 0xFE000000,
ConditionalBranchMask = 0xFF000010,
B_cond = ConditionalBranchFixed | 0x00000000
};
// Test and branch.
enum TestBranchOp {
TestBranchFixed = 0x36000000,
TestBranchFMask = 0x7E000000,
TestBranchMask = 0x7F000000,
TBZ = TestBranchFixed | 0x00000000,
TBNZ = TestBranchFixed | 0x01000000
};
#endif //SANDHOOK_NH_INST_CODE_ARM64_H #endif //SANDHOOK_NH_INST_CODE_ARM64_H
...@@ -37,6 +37,30 @@ enum ImmBranchType { ...@@ -37,6 +37,30 @@ enum ImmBranchType {
TestBranchType = 4 TestBranchType = 4
}; };
// Condition codes.
enum Condition {
eq = 0, // Z set Equal.
ne = 1, // Z clear Not equal.
cs = 2, // C set Carry set.
cc = 3, // C clear Carry clear.
mi = 4, // N set Negative.
pl = 5, // N clear Positive or zero.
vs = 6, // V set Overflow.
vc = 7, // V clear No overflow.
hi = 8, // C set, Z clear Unsigned higher.
ls = 9, // C clear or Z set Unsigned lower or same.
ge = 10, // N == V Greater or equal.
lt = 11, // N != V Less than.
gt = 12, // Z clear, N == V Greater than.
le = 13, // Z set or N != V Less then or equal
al = 14, // Always.
nv = 15, // Behaves as always/al.
// Aliases.
hs = cs, // C set Unsigned higher or same.
lo = cc // C clear Unsigned lower.
};
#define IMM_LO_W 2 #define IMM_LO_W 2
#define IMM_HI_W 19 #define IMM_HI_W 19
struct aarch64_adr_adrp { struct aarch64_adr_adrp {
...@@ -74,4 +98,25 @@ struct aarch64_cbz_cbnz { ...@@ -74,4 +98,25 @@ struct aarch64_cbz_cbnz {
InstA64 rt:5; InstA64 rt:5;
}; };
#define CBZ_B_COND_OPCODE 0b01010100
struct aarch64_b_cond {
InstA64 opcode:8;
InstA64 imm19:19;
InstA64 unkown:1;
InstA64 cond:4;
};
#define TBZ_TBNZ_OPCODE 0b011011
struct aarch64_tbz_tbnz {
InstA64 b5:1;
InstA64 opcode:6;
InstA64 op:1;
InstA64 b40:5;
InstA64 imm14:14;
InstA64 rt:5;
};
#endif //SANDHOOK_NH_INST_AARCH64_H #endif //SANDHOOK_NH_INST_AARCH64_H
...@@ -29,7 +29,8 @@ namespace SandHook { ...@@ -29,7 +29,8 @@ namespace SandHook {
public: public:
Unit() { Unit() {
raw = reinterpret_cast<Raw*>(malloc(sizeof(Raw))); raw = reinterpret_cast<Raw*>(malloc(size()));
memset(raw, 0, size());
auto_alloc = true; auto_alloc = true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment