Commit 99178dd4 authored by swift_gan's avatar swift_gan Committed by swift_gan

[NativeHook]fix arm32

parent 5e1e5cb7
...@@ -47,22 +47,30 @@ void AssemblerA32::Movt(RegisterA32 &rd, U16 imm16) { ...@@ -47,22 +47,30 @@ void AssemblerA32::Movt(RegisterA32 &rd, U16 imm16) {
} }
void AssemblerA32::Mov(RegisterA32 &rd, U32 imm32) { void AssemblerA32::Mov(RegisterA32 &rd, U32 imm32) {
U16 immH = BITS16H(imm32);
U16 immL = BITS16L(imm32); U16 immL = BITS16L(imm32);
U16 immH = BITS16H(imm32);
Mov(rd, immL); Mov(rd, immL);
Movt(rd, immH); Movt(rd, immH);
} }
void AssemblerA32::Ldr(RegisterA32 &rt, Label *label) { void AssemblerA32::Ldr(RegisterA32 &rt, Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_LIT)(INST_T32(LDR_LIT)::LDR, rt, *label))); Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_LIT)(INST_T32(LDR_LIT)::LDR, INST_T32(LDR_LIT)::UnSign, rt, *label)));
} }
void AssemblerA32::Ldrb(RegisterA32 &rt, Label *label) { void AssemblerA32::Ldrb(RegisterA32 &rt, Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_LIT)(INST_T32(LDR_LIT)::LDRB, rt, *label))); Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_LIT)(INST_T32(LDR_LIT)::LDRB, INST_T32(LDR_LIT)::UnSign,rt, *label)));
} }
void AssemblerA32::Ldrh(RegisterA32 &rt, Label *label) { void AssemblerA32::Ldrh(RegisterA32 &rt, Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_LIT)(INST_T32(LDR_LIT)::LDRH, rt, *label))); Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_LIT)(INST_T32(LDR_LIT)::LDRH, INST_T32(LDR_LIT)::UnSign,rt, *label)));
}
void AssemblerA32::Ldrsb(RegisterA32 &rt, Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_LIT)(INST_T32(LDR_LIT)::LDRB, INST_T32(LDR_LIT)::Sign,rt, *label)));
}
void AssemblerA32::Ldrsh(RegisterA32 &rt, Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T32(LDR_LIT)(INST_T32(LDR_LIT)::LDRH, INST_T32(LDR_LIT)::Sign,rt, *label)));
} }
void AssemblerA32::Ldr(RegisterA32 &rt, const MemOperand &operand) { void AssemblerA32::Ldr(RegisterA32 &rt, const MemOperand &operand) {
...@@ -153,4 +161,8 @@ void AssemblerA32::Push(RegisterA32 &rt) { ...@@ -153,4 +161,8 @@ void AssemblerA32::Push(RegisterA32 &rt) {
} }
} }
void AssemblerA32::Adr(RegisterA32 &rd, Label *label) {
Emit(reinterpret_cast<Unit<Base>*>(new INST_T16(ADR)(rd, *label)));
}
...@@ -37,6 +37,8 @@ namespace SandHook { ...@@ -37,6 +37,8 @@ namespace SandHook {
void Ldr(RegisterA32 &rt, Label* label); void Ldr(RegisterA32 &rt, Label* label);
void Ldrb(RegisterA32 &rt, Label* label); void Ldrb(RegisterA32 &rt, Label* label);
void Ldrh(RegisterA32 &rt, Label* label); void Ldrh(RegisterA32 &rt, Label* label);
void Ldrsb(RegisterA32 &rt, Label* label);
void Ldrsh(RegisterA32 &rt, Label* label);
void Ldr(RegisterA32 &rt, const MemOperand& operand); void Ldr(RegisterA32 &rt, const MemOperand& operand);
void Ldrb(RegisterA32 &rt, const MemOperand& operand); void Ldrb(RegisterA32 &rt, const MemOperand& operand);
...@@ -63,6 +65,8 @@ namespace SandHook { ...@@ -63,6 +65,8 @@ namespace SandHook {
void Pop(RegisterA32& rt); void Pop(RegisterA32& rt);
void Push(RegisterA32& rt); void Push(RegisterA32& rt);
void Adr(RegisterA32& rd, Label* label);
public: public:
CodeContainer codeContainer = CodeContainer(nullptr); CodeContainer codeContainer = CodeContainer(nullptr);
}; };
......
...@@ -49,7 +49,7 @@ void *InlineHookArm32Android::inlineHook(void *origin, void *replace) { ...@@ -49,7 +49,7 @@ void *InlineHookArm32Android::inlineHook(void *origin, void *replace) {
Label* origin_addr_label = new Label(); Label* origin_addr_label = new Label();
__ Ldr(PC, origin_addr_label); __ Ldr(PC, origin_addr_label);
__ Emit(origin_addr_label); __ Emit(origin_addr_label);
__ Emit((Addr) getThumbPC(reinterpret_cast<void *>(reinterpret_cast<Addr>(originCode) + codeContainerInline->size()))); __ Emit((Addr) getThumbPC(reinterpret_cast<void *>(reinterpret_cast<Addr>(originCode) + relocate.curOffset)));
__ finish(); __ finish();
#undef __ #undef __
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#define DECODE_OFFSET(bits, ext) signExtend32(bits + ext, COMBINE(get()->imm##bits, 0, ext)) #define DECODE_OFFSET(bits, ext) signExtend32(bits + ext, COMBINE(get()->imm##bits, 0, ext))
#define ENCODE_OFFSET(bits, ext) get()->imm##bits = TruncateToUint##bits(offset >> ext) #define ENCODE_OFFSET(bits, ext) get()->imm##bits = TruncateToUint##bits(offset >> ext)
#define CODE_OFFSET(I) inst->offset + 2 * inst->size() #define CODE_OFFSET(I) I->offset + I->instType() == A32 ? 2 * 4 : 2 * 2
using namespace SandHook::RegistersA32; using namespace SandHook::RegistersA32;
......
...@@ -34,11 +34,12 @@ DEFINE_STRUCT_T32(B32) { ...@@ -34,11 +34,12 @@ DEFINE_STRUCT_T32(B32) {
InstT32 op:2; InstT32 op:2;
}; };
DEFINE_OPCODE_T32(LDR_LIT, 0b11111000) DEFINE_OPCODE_T32(LDR_LIT, 0b1111100)
DEFINE_STRUCT_T32(LDR_LIT) { DEFINE_STRUCT_T32(LDR_LIT) {
InstT32 op:7; InstT32 op:7;
InstT32 U:1; InstT32 U:1;
InstT32 opcode:8; InstT32 S:1;
InstT32 opcode:7;
InstT32 imm12:12; InstT32 imm12:12;
InstT32 rt:T32_REG_WIDE; InstT32 rt:T32_REG_WIDE;
}; };
......
...@@ -220,9 +220,9 @@ T16_ADR::T16_ADR(T16_STRUCT_ADR *inst) : T16_INST_PC_REL(inst) { ...@@ -220,9 +220,9 @@ T16_ADR::T16_ADR(T16_STRUCT_ADR *inst) : T16_INST_PC_REL(inst) {
decode(inst); decode(inst);
} }
T16_ADR::T16_ADR(RegisterA32 *rd, Off offset) : rd(rd), offset(offset) {} T16_ADR::T16_ADR(RegisterA32 &rd, Off offset) : rd(&rd), offset(offset) {}
T16_ADR::T16_ADR(RegisterA32 *rd, Label &label) : rd(rd) { T16_ADR::T16_ADR(RegisterA32 &rd, Label &label) : rd(&rd) {
bindLabel(label); bindLabel(label);
} }
...@@ -235,6 +235,11 @@ Addr T16_ADR::getImmPCOffsetTarget() { ...@@ -235,6 +235,11 @@ Addr T16_ADR::getImmPCOffsetTarget() {
return RoundDown((Addr) getPC() + offset, 4); return RoundDown((Addr) getPC() + offset, 4);
} }
void T16_ADR::onOffsetApply(Off offset) {
this->offset = offset;
get()->imm8 = (U32)offset >> 2;
}
void T16_ADR::decode(T16_STRUCT_ADR *inst) { void T16_ADR::decode(T16_STRUCT_ADR *inst) {
offset = getImmPCOffset(); offset = getImmPCOffset();
DECODE_RD(Reg); DECODE_RD(Reg);
......
...@@ -61,15 +61,11 @@ namespace SandHook { ...@@ -61,15 +61,11 @@ namespace SandHook {
} }
void *getPC() override { void *getPC() override {
return reinterpret_cast<void *>((Addr) Instruction<Inst>::getPC() + 2 * size()); return reinterpret_cast<void *>((Addr) Instruction<Inst>::getPC() + 2 * 2);
} }
Addr getVPC() override { Addr getVPC() override {
return Instruction<Inst>::getVPC() + 2 * size(); return Instruction<Inst>::getVPC() + 2 * 2;
}
static inline U32 zeroExtend32(unsigned int bits, U32 value) {
return value << (32 - bits);
} }
static inline S32 signExtend32(unsigned int bits, U32 value) { static inline S32 signExtend32(unsigned int bits, U32 value) {
...@@ -295,9 +291,9 @@ namespace SandHook { ...@@ -295,9 +291,9 @@ namespace SandHook {
T16_ADR(T16_STRUCT_ADR *inst); T16_ADR(T16_STRUCT_ADR *inst);
T16_ADR(RegisterA32 *rd, Off offset); T16_ADR(RegisterA32 &rd, Off offset);
T16_ADR(RegisterA32 *rd, Label &label); T16_ADR(RegisterA32 &rd, Label &label);
DEFINE_IS(ADR) DEFINE_IS(ADR)
...@@ -307,6 +303,8 @@ namespace SandHook { ...@@ -307,6 +303,8 @@ namespace SandHook {
Addr getImmPCOffsetTarget() override; Addr getImmPCOffsetTarget() override;
void onOffsetApply(Off offset) override;
void decode(T16_STRUCT_ADR *inst) override; void decode(T16_STRUCT_ADR *inst) override;
void assembler() override; void assembler() override;
......
...@@ -31,7 +31,9 @@ void T32_UNKNOW::assembler() { ...@@ -31,7 +31,9 @@ void T32_UNKNOW::assembler() {
} }
T32_B32::T32_B32(T32_STRUCT_B32 *inst) : T32_INST_PC_REL(inst) {} T32_B32::T32_B32(T32_STRUCT_B32 *inst) : T32_INST_PC_REL(inst) {
decode(inst);
}
T32_B32::T32_B32(T32_B32::OP op, T32_B32::X x, Off offset) : op(op), x(x), offset(offset) {} T32_B32::T32_B32(T32_B32::OP op, T32_B32::X x, Off offset) : op(op), x(x), offset(offset) {}
...@@ -42,15 +44,14 @@ T32_B32::T32_B32(T32_B32::OP op, T32_B32::X x, Label &label) : op(op), x(x) { ...@@ -42,15 +44,14 @@ T32_B32::T32_B32(T32_B32::OP op, T32_B32::X x, Label &label) : op(op), x(x) {
Off T32_B32::getImmPCOffset() { Off T32_B32::getImmPCOffset() {
U32 S = get()->S; U32 S = get()->S;
U32 imm21 = COMBINE(get()->imm10, get()->imm11, 11); U32 imm21 = COMBINE(get()->imm10, get()->imm11, 11);
U32 i1 = (get()->J1 ^ S) ? 0 : 1; if (get()->X == 0) {
U32 i2 = (get()->J2 ^ S) ? 0 : 1; imm21 -= BIT(imm21, 0);
U32 i1i2 = COMBINE(i1, i2, 1);
U32 Si1i2 = COMBINE(S, i1i2, 2);
//BLX
if (op == BL && x == thumb) {
INST_ASSERT((imm21 & 0x1) == 0x1);
} }
return signExtend32(25, COMBINE(Si1i2, imm21, 21) << 0); U32 i1 = !(get()->J1 ^ S);
U32 i2 = !(get()->J2 ^ S);
U32 i1i2 = COMBINE(i1, i2, 1);
U32 Si1i2 = COMBINE(-S, i1i2, 2);
return signExtend32(25, COMBINE(Si1i2, imm21, 21) << 1);
} }
void T32_B32::decode(T32_STRUCT_B32 *inst) { void T32_B32::decode(T32_STRUCT_B32 *inst) {
...@@ -63,7 +64,7 @@ void T32_B32::assembler() { ...@@ -63,7 +64,7 @@ void T32_B32::assembler() {
SET_OPCODE(B32); SET_OPCODE(B32);
ENCODE_OP; ENCODE_OP;
get()->X = x; get()->X = x;
U32 imm24 = TruncateToUint25(offset) >> 0; U32 imm24 = TruncateToUint25(offset) >> 1;
get()->imm11 = BITS(imm24, 0, 10); get()->imm11 = BITS(imm24, 0, 10);
get()->imm10 = BITS(imm24, 11, 20); get()->imm10 = BITS(imm24, 11, 20);
get()->S = BIT(imm24, 23); get()->S = BIT(imm24, 23);
...@@ -72,15 +73,23 @@ void T32_B32::assembler() { ...@@ -72,15 +73,23 @@ void T32_B32::assembler() {
if (i1 == 1) { if (i1 == 1) {
get()->J1 = get()->S; get()->J1 = get()->S;
} else { } else {
get()->J1 = ~get()->S; get()->J1 = !get()->S;
} }
if (i2 == 1) { if (i2 == 1) {
get()->J2 = get()->S; get()->J2 = get()->S;
} else { } else {
get()->J2 = ~get()->S; get()->J2 = !get()->S;
} }
} }
Addr T32_B32::getImmPCOffsetTarget() {
if (x == arm) {
void* base = reinterpret_cast<void *>(ALIGN((Addr)getPC(), 4));
return offset + reinterpret_cast<Addr>(base);
} else {
return T32_INST_PC_REL::getImmPCOffsetTarget();
}
}
T32_LDR_UIMM::T32_LDR_UIMM(T32_STRUCT_LDR_UIMM *inst) : InstructionT32(inst) {} T32_LDR_UIMM::T32_LDR_UIMM(T32_STRUCT_LDR_UIMM *inst) : InstructionT32(inst) {}
...@@ -109,10 +118,10 @@ T32_LDR_LIT::T32_LDR_LIT(T32_STRUCT_LDR_LIT *inst) : T32_INST_PC_REL(inst) { ...@@ -109,10 +118,10 @@ T32_LDR_LIT::T32_LDR_LIT(T32_STRUCT_LDR_LIT *inst) : T32_INST_PC_REL(inst) {
decode(inst); decode(inst);
} }
T32_LDR_LIT::T32_LDR_LIT(OP op, RegisterA32 &rt, Off offset) : op(op), rt(&rt), offset(offset) {} T32_LDR_LIT::T32_LDR_LIT(OP op, S s, RegisterA32 &rt, Off offset) : op(op), s(s), rt(&rt), offset(offset) {}
T32_LDR_LIT::T32_LDR_LIT(OP op, RegisterA32 &rt, Label& label) : op(op), rt(&rt) { T32_LDR_LIT::T32_LDR_LIT(OP op, S s, RegisterA32 &rt, Label& label) : op(op), s(s), rt(&rt) {
bindLabel(label); bindLabel(label);
} }
...@@ -134,6 +143,7 @@ void T32_LDR_LIT::onOffsetApply(Off offset) { ...@@ -134,6 +143,7 @@ void T32_LDR_LIT::onOffsetApply(Off offset) {
void T32_LDR_LIT::decode(T32_STRUCT_LDR_LIT *inst) { void T32_LDR_LIT::decode(T32_STRUCT_LDR_LIT *inst) {
DECODE_OP; DECODE_OP;
DECODE_RT(Reg); DECODE_RT(Reg);
s = S(inst->S);
offset = getImmPCOffset(); offset = getImmPCOffset();
} }
...@@ -141,6 +151,7 @@ void T32_LDR_LIT::assembler() { ...@@ -141,6 +151,7 @@ void T32_LDR_LIT::assembler() {
SET_OPCODE(LDR_LIT); SET_OPCODE(LDR_LIT);
ENCODE_OP; ENCODE_OP;
ENCODE_RT; ENCODE_RT;
get()->S = s;
if (offset >= 0) { if (offset >= 0) {
get()->U = add; get()->U = add;
get()->imm12 = static_cast<InstT32>(offset); get()->imm12 = static_cast<InstT32>(offset);
...@@ -160,6 +171,7 @@ T32_MOV_MOVT_IMM::T32_MOV_MOVT_IMM(T32_MOV_MOVT_IMM::OP op, RegisterA32 &rd, U16 ...@@ -160,6 +171,7 @@ T32_MOV_MOVT_IMM::T32_MOV_MOVT_IMM(T32_MOV_MOVT_IMM::OP op, RegisterA32 &rd, U16
imm16(imm16) {} imm16(imm16) {}
void T32_MOV_MOVT_IMM::decode(T32_STRUCT_MOV_MOVT_IMM *inst) { void T32_MOV_MOVT_IMM::decode(T32_STRUCT_MOV_MOVT_IMM *inst) {
DECODE_OP;
DECODE_RD(Reg); DECODE_RD(Reg);
U16 imm4i = COMBINE(inst->imm4, inst->i, 1); U16 imm4i = COMBINE(inst->imm4, inst->i, 1);
U16 imm38 = COMBINE(inst->imm3, inst->imm8, 8); U16 imm38 = COMBINE(inst->imm3, inst->imm8, 8);
...@@ -169,6 +181,7 @@ void T32_MOV_MOVT_IMM::decode(T32_STRUCT_MOV_MOVT_IMM *inst) { ...@@ -169,6 +181,7 @@ void T32_MOV_MOVT_IMM::decode(T32_STRUCT_MOV_MOVT_IMM *inst) {
void T32_MOV_MOVT_IMM::assembler() { void T32_MOV_MOVT_IMM::assembler() {
SET_OPCODE_MULTI(MOV_MOVT_IMM, 1); SET_OPCODE_MULTI(MOV_MOVT_IMM, 1);
SET_OPCODE_MULTI(MOV_MOVT_IMM, 2); SET_OPCODE_MULTI(MOV_MOVT_IMM, 2);
ENCODE_OP;
ENCODE_RD; ENCODE_RD;
get()->imm8 = BITS(imm16, 0, 7); get()->imm8 = BITS(imm16, 0, 7);
get()->imm3 = BITS(imm16, 8 ,10); get()->imm3 = BITS(imm16, 8 ,10);
......
...@@ -62,11 +62,11 @@ namespace SandHook { ...@@ -62,11 +62,11 @@ namespace SandHook {
} }
void *getPC() override { void *getPC() override {
return reinterpret_cast<void *>((Addr) Instruction<Inst>::getPC() + 2 * size()); return reinterpret_cast<void *>((Addr) Instruction<Inst>::getPC() + 2 * 2);
} }
Addr getVPC() override { Addr getVPC() override {
return Instruction<Inst>::getVPC() + 2 * size(); return Instruction<Inst>::getVPC() + 2 * 2;
} }
static inline S32 signExtend32(unsigned int bits, U32 value) { static inline S32 signExtend32(unsigned int bits, U32 value) {
...@@ -150,6 +150,8 @@ namespace SandHook { ...@@ -150,6 +150,8 @@ namespace SandHook {
DEFINE_IS(B32) DEFINE_IS(B32)
Addr getImmPCOffsetTarget() override;
Off getImmPCOffset() override; Off getImmPCOffset() override;
void decode(T32_STRUCT_B32 *inst) override; void decode(T32_STRUCT_B32 *inst) override;
...@@ -192,18 +194,23 @@ namespace SandHook { ...@@ -192,18 +194,23 @@ namespace SandHook {
LDRH = 0b0111111 LDRH = 0b0111111
}; };
enum S { enum U {
cmp = 0b0, cmp = 0b0,
add = 0b1 add = 0b1
}; };
enum S {
UnSign = 0b0,
Sign = 0b1
};
T32_LDR_LIT(); T32_LDR_LIT();
T32_LDR_LIT(T32_STRUCT_LDR_LIT *inst); T32_LDR_LIT(T32_STRUCT_LDR_LIT *inst);
T32_LDR_LIT(OP op, RegisterA32 &rt, Off offset); T32_LDR_LIT(OP op, S s, RegisterA32 &rt, Off offset);
T32_LDR_LIT(OP op, RegisterA32 &rt, Label& label); T32_LDR_LIT(OP op, S s, RegisterA32 &rt, Label& label);
DEFINE_IS(LDR_LIT) DEFINE_IS(LDR_LIT)
...@@ -219,6 +226,7 @@ namespace SandHook { ...@@ -219,6 +226,7 @@ namespace SandHook {
public: public:
OP op; OP op;
S s;
RegisterA32* rt; RegisterA32* rt;
Off offset; Off offset;
}; };
......
...@@ -27,6 +27,9 @@ CodeRelocateA32::CodeRelocateA32(AssemblerA32 &assembler) : CodeRelocate(assembl ...@@ -27,6 +27,9 @@ CodeRelocateA32::CodeRelocateA32(AssemblerA32 &assembler) : CodeRelocate(assembl
bool CodeRelocateA32::visit(Unit<Base> *unit, void *pc) { bool CodeRelocateA32::visit(Unit<Base> *unit, void *pc) {
relocate(reinterpret_cast<Instruction<Base> *>(unit), __ getPC()); relocate(reinterpret_cast<Instruction<Base> *>(unit), __ getPC());
curOffset += unit->size(); curOffset += unit->size();
if (unit->refcount() == 0) {
delete unit;
}
return true; return true;
} }
...@@ -56,12 +59,33 @@ void* CodeRelocateA32::relocate(Instruction<Base> *instruction, void *toPc) thro ...@@ -56,12 +59,33 @@ void* CodeRelocateA32::relocate(Instruction<Base> *instruction, void *toPc) thro
if (!instruction->pcRelate()) { if (!instruction->pcRelate()) {
__ Emit(instruction); __ Emit(instruction);
instruction->ref();
return curPc; return curPc;
} }
switch (instruction->instCode()) {
CASE(T16, B) if (instruction->instType() == thumb32) {
default: switch (instruction->instCode()) {
__ Emit(instruction); CASE(T32, B32)
CASE(T32, LDR_LIT)
default:
__ Emit(instruction);
instruction->ref();
}
} else if (instruction->instType() == thumb16) {
switch (instruction->instCode()) {
CASE(T16, B)
CASE(T16, B_COND)
CASE(T16, BX_BLX)
CASE(T16, CBZ_CBNZ)
CASE(T16, ADR)
CASE(T16, LDR_LIT)
default:
__ Emit(instruction);
instruction->ref();
}
} else {
__ Emit(instruction);
instruction->ref();
} }
return curPc; return curPc;
} }
...@@ -69,17 +93,42 @@ void* CodeRelocateA32::relocate(Instruction<Base> *instruction, void *toPc) thro ...@@ -69,17 +93,42 @@ void* CodeRelocateA32::relocate(Instruction<Base> *instruction, void *toPc) thro
IMPL_RELOCATE(T16, B_COND) { IMPL_RELOCATE(T16, B_COND) {
if (inRelocateRange(CODE_OFFSET(inst), sizeof(InstT16))) {
__ B(inst->condition, getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
return;
}
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inst->condition == al) {
Label* target_label = new Label;
__ Ldr(PC, target_label);
__ Emit(target_label);
__ Emit(targetAddr);
} else {
Label* true_label = new Label();
Label* false_label = new Label();
Label* target_label = new Label;
__ B(inst->condition, true_label);
__ B(false_label);
__ Emit(true_label);
__ Ldr(PC, target_label);
__ Emit(target_label);
__ Emit(targetAddr);
__ Emit(false_label);
}
} }
IMPL_RELOCATE(T16, B) { IMPL_RELOCATE(T16, B) {
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inRelocateRange(CODE_OFFSET(inst), sizeof(InstT16))) { if (inRelocateRange(CODE_OFFSET(inst), sizeof(InstT16))) {
__ B(getLaterBindLabel(CODE_OFFSET(inst) + curOffset)); __ B(getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
return; return;
} }
Addr targetAddr = inst->getImmPCOffsetTarget();
Label* target_label = new Label(); Label* target_label = new Label();
__ Ldr(PC, target_label); __ Ldr(PC, target_label);
__ Emit(target_label); __ Emit(target_label);
...@@ -88,25 +137,130 @@ IMPL_RELOCATE(T16, B) { ...@@ -88,25 +137,130 @@ IMPL_RELOCATE(T16, B) {
} }
IMPL_RELOCATE(T16, BX_BLX) { IMPL_RELOCATE(T16, BX_BLX) {
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
inst->ref();
} }
IMPL_RELOCATE(T16, CBZ_CBNZ) { IMPL_RELOCATE(T16, CBZ_CBNZ) {
inst->ref();
if (inRelocateRange(CODE_OFFSET(inst), sizeof(InstT16))) {
inst->bindLabel(*getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
return;
}
Addr targetAddr = inst->getImmPCOffsetTarget();
Label* true_label = new Label;
Label* false_label = new Label;
Label* target_label = new Label();
inst->bindLabel(*true_label);
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
__ B(false_label);
__ Emit(true_label);
__ Ldr(PC, target_label);
__ Emit(target_label);
__ Emit((Addr) getThumbPC(reinterpret_cast<void *>(targetAddr)));
__ Emit(false_label);
} }
IMPL_RELOCATE(T16, LDR_LIT) { IMPL_RELOCATE(T16, LDR_LIT) {
if (inRelocateRange(CODE_OFFSET(inst), sizeof(InstT16))) {
__ Ldr(*inst->rt, getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
return;
}
Addr targetAddr = inst->getImmPCOffsetTarget();
__ Mov(*inst->rt, targetAddr);
__ Ldr(*inst->rt, MemOperand(inst->rt, 0));
} }
IMPL_RELOCATE(T16, ADR) { IMPL_RELOCATE(T16, ADR) {
if (inRelocateRange(CODE_OFFSET(inst), sizeof(InstT16))) {
__ Adr(*inst->rd, getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
return;
}
Addr targetAddr = inst->getImmPCOffsetTarget();
__ Mov(*inst->rd, targetAddr);
} }
IMPL_RELOCATE(T32, B32) { IMPL_RELOCATE(T32, B32) {
if (inRelocateRange(CODE_OFFSET(inst), sizeof(InstT16))) {
inst->ref();
inst->bindLabel(*getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
return;
}
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inst->x == T32_B32::thumb) {
//Thumb mode
if (inst->op == T32_B32::BL) {
__ Mov(LR, U32((Addr) toPc + inst->size() + 2 * 2));
}
targetAddr = reinterpret_cast<Addr>(getThumbPC(reinterpret_cast<void *>(targetAddr)));
Label* target_label = new Label();
__ Ldr(PC, target_label);
__ Emit(target_label);
__ Emit(reinterpret_cast<Addr>(targetAddr));
} else {
//to A32 mode
__ Mov(IP, targetAddr);
if (inst->op == T32_B32::BL) {
__ Blx(IP);
} else {
__ Bx(IP);
}
}
} }
IMPL_RELOCATE(T32, LDR_LIT) { IMPL_RELOCATE(T32, LDR_LIT) {
if (inRelocateRange(CODE_OFFSET(inst), sizeof(InstT16))) {
inst->ref();
inst->bindLabel(*getLaterBindLabel(CODE_OFFSET(inst) + curOffset));
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
return;
}
Addr targetAddr = inst->getImmPCOffsetTarget();
__ Mov(*inst->rt, targetAddr);
switch (inst->op) {
case T32_LDR_LIT::LDR:
__ Ldr(*inst->rt, MemOperand(inst->rt, 0));
break;
case T32_LDR_LIT::LDRB:
if (inst->s == T32_LDR_LIT::UnSign) {
__ Ldrb(*inst->rt, MemOperand(inst->rt, 0));
} else {
__ Ldrsb(*inst->rt, MemOperand(inst->rt, 0));
}
break;
case T32_LDR_LIT::LDRH:
if (inst->s == T32_LDR_LIT::UnSign) {
__ Ldrh(*inst->rt, MemOperand(inst->rt, 0));
} else {
__ Ldrsh(*inst->rt, MemOperand(inst->rt, 0));
}
break;
default:
inst->ref();
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
}
} }
\ No newline at end of file
...@@ -27,6 +27,9 @@ CodeRelocateA64::CodeRelocateA64(AssemblerA64 &assembler) : CodeRelocate(assembl ...@@ -27,6 +27,9 @@ CodeRelocateA64::CodeRelocateA64(AssemblerA64 &assembler) : CodeRelocate(assembl
bool CodeRelocateA64::visit(Unit<Base> *unit, void *pc) { bool CodeRelocateA64::visit(Unit<Base> *unit, void *pc) {
relocate(reinterpret_cast<Instruction<Base> *>(unit), __ getPC()); relocate(reinterpret_cast<Instruction<Base> *>(unit), __ getPC());
curOffset += unit->size(); curOffset += unit->size();
if (unit->refcount() == 0) {
delete unit;
}
return true; return true;
} }
...@@ -53,6 +56,7 @@ void* CodeRelocateA64::relocate(Instruction<Base> *instruction, void *toPc) thro ...@@ -53,6 +56,7 @@ void* CodeRelocateA64::relocate(Instruction<Base> *instruction, void *toPc) thro
if (!instruction->pcRelate()) { if (!instruction->pcRelate()) {
__ Emit(instruction); __ Emit(instruction);
instruction->ref();
return curPc; return curPc;
} }
switch (instruction->instCode()) { switch (instruction->instCode()) {
...@@ -64,37 +68,40 @@ void* CodeRelocateA64::relocate(Instruction<Base> *instruction, void *toPc) thro ...@@ -64,37 +68,40 @@ void* CodeRelocateA64::relocate(Instruction<Base> *instruction, void *toPc) thro
CASE(ADR_ADRP) CASE(ADR_ADRP)
default: default:
__ Emit(instruction); __ Emit(instruction);
instruction->ref();
} }
return curPc; return curPc;
} }
IMPL_RELOCATE(B_BL) { IMPL_RELOCATE(B_BL) {
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inRelocateRange(inst->offset, sizeof(InstA64))) { if (inRelocateRange(inst->offset, sizeof(InstA64))) {
if (inst->op == inst->BL) { inst->ref();
__ Bl(getLaterBindLabel(inst->offset + curOffset)); inst->bindLabel(*getLaterBindLabel(inst->offset + curOffset));
} else { __ Emit(reinterpret_cast<Instruction<Base>*>(inst));
__ B(getLaterBindLabel(inst->offset + curOffset));
}
return; return;
} }
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inst->op == inst->BL) { if (inst->op == inst->BL) {
__ Mov(LR, (Addr)inst->getPC() + inst->size()); __ Mov(LR, (Addr)toPc + inst->size());
} }
__ Mov(IP1, targetAddr); __ Mov(IP1, targetAddr);
__ Br(IP1); __ Br(IP1);
} }
IMPL_RELOCATE(B_COND) { IMPL_RELOCATE(B_COND) {
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inRelocateRange(inst->offset, sizeof(InstA64))) { if (inRelocateRange(inst->offset, sizeof(InstA64))) {
__ B(inst->condition, getLaterBindLabel(inst->offset + curOffset)); inst->ref();
inst->bindLabel(*getLaterBindLabel(inst->offset + curOffset));
__ Emit(reinterpret_cast<Instruction<Base>*>(inst));
return; return;
} }
Addr targetAddr = inst->getImmPCOffsetTarget();
Label *true_label = new Label(); Label *true_label = new Label();
Label *false_label = new Label(); Label *false_label = new Label();
...@@ -110,17 +117,15 @@ IMPL_RELOCATE(B_COND) { ...@@ -110,17 +117,15 @@ IMPL_RELOCATE(B_COND) {
IMPL_RELOCATE(TBZ_TBNZ) { IMPL_RELOCATE(TBZ_TBNZ) {
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inRelocateRange(inst->offset, sizeof(InstA64))) { if (inRelocateRange(inst->offset, sizeof(InstA64))) {
if (inst->op == INST_A64(TBZ_TBNZ)::TBNZ) { inst->ref();
__ Tbnz(*inst->rt, inst->bit, getLaterBindLabel(inst->offset + curOffset)); inst->bindLabel(*getLaterBindLabel(inst->offset + curOffset));
} else { __ Emit(reinterpret_cast<Instruction<Base>*>(inst));
__ Tbz(*inst->rt, inst->bit, getLaterBindLabel(inst->offset + curOffset));
}
return; return;
} }
Addr targetAddr = inst->getImmPCOffsetTarget();
Label *true_label = new Label(); Label *true_label = new Label();
Label *false_label = new Label(); Label *false_label = new Label();
...@@ -139,17 +144,16 @@ IMPL_RELOCATE(TBZ_TBNZ) { ...@@ -139,17 +144,16 @@ IMPL_RELOCATE(TBZ_TBNZ) {
} }
IMPL_RELOCATE(CBZ_CBNZ) { IMPL_RELOCATE(CBZ_CBNZ) {
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inRelocateRange(inst->offset, sizeof(InstA64))) { if (inRelocateRange(inst->offset, sizeof(InstA64))) {
if (inst->op == INST_A64(CBZ_CBNZ)::CBNZ) { inst->ref();
__ Cbnz(*inst->rt, getLaterBindLabel(inst->offset + curOffset)); inst->bindLabel(*getLaterBindLabel(inst->offset + curOffset));
} else { __ Emit(reinterpret_cast<Instruction<Base>*>(inst));
__ Cbz(*inst->rt, getLaterBindLabel(inst->offset + curOffset));
}
return; return;
} }
Addr targetAddr = inst->getImmPCOffsetTarget();
Label *true_label = new Label(); Label *true_label = new Label();
Label *false_label = new Label(); Label *false_label = new Label();
...@@ -174,23 +178,9 @@ IMPL_RELOCATE(LDR_LIT) { ...@@ -174,23 +178,9 @@ IMPL_RELOCATE(LDR_LIT) {
WRegister* rtW = WReg(inst->rt->getCode()); WRegister* rtW = WReg(inst->rt->getCode());
if (inRelocateRange(inst->offset, sizeof(Addr))) { if (inRelocateRange(inst->offset, sizeof(Addr))) {
switch (inst->op) { inst->ref();
case INST_A64(LDR_LIT)::LDR_X: inst->bindLabel(*getLaterBindLabel(inst->offset + curOffset));
__ Ldr(*rtX, getLaterBindLabel(inst->offset + curOffset)); __ Emit(reinterpret_cast<Instruction<Base>*>(inst));
break;
case INST_A64(LDR_LIT)::LDR_W:
__ Ldr(*rtW, getLaterBindLabel(inst->offset + curOffset));
break;
case INST_A64(LDR_LIT)::LDR_SW:
__ Ldrsw(*rtX, getLaterBindLabel(inst->offset + curOffset));
break;
case INST_A64(LDR_LIT)::LDR_PRFM:
__ Push(X0);
__ Mov(X0, targetAddr);
__ Ldrsw(X0, MemOperand(rtX, 0, Offset));
__ Pop(X0);
break;
}
return; return;
} }
...@@ -217,5 +207,10 @@ IMPL_RELOCATE(LDR_LIT) { ...@@ -217,5 +207,10 @@ IMPL_RELOCATE(LDR_LIT) {
} }
IMPL_RELOCATE(ADR_ADRP) { IMPL_RELOCATE(ADR_ADRP) {
if (inRelocateRange(inst->offset, sizeof(Addr))) {
__ Mov(*inst->rd, (Addr) toPc);
}
__ Mov(*inst->rd, inst->getImmPCOffsetTarget()); __ Mov(*inst->rd, inst->getImmPCOffsetTarget());
} }
...@@ -80,6 +80,18 @@ namespace SandHook { ...@@ -80,6 +80,18 @@ namespace SandHook {
return sizeof(Raw); return sizeof(Raw);
} }
inline U8 ref() {
return ++ref_count;
}
inline U8 release() {
return --ref_count;
}
inline U8 refcount() {
return ref_count;
}
virtual ~Unit() { virtual ~Unit() {
if (auto_alloc) { if (auto_alloc) {
free(raw); free(raw);
...@@ -87,9 +99,10 @@ namespace SandHook { ...@@ -87,9 +99,10 @@ namespace SandHook {
} }
private: private:
Raw* raw; Raw* raw = nullptr;
Addr vPos; Addr vPos = 0;
bool auto_alloc = false; bool auto_alloc = false;
U8 ref_count = 0;
}; };
} }
......
...@@ -94,6 +94,8 @@ T AlignDown(T pointer, ...@@ -94,6 +94,8 @@ T AlignDown(T pointer,
return (T)(pointer_raw & ~mask); return (T)(pointer_raw & ~mask);
} }
#define ALIGN(value, align) value - value % align
template<typename T> template<typename T>
struct Identity { struct Identity {
using type = T; using type = T;
...@@ -204,6 +206,16 @@ inline int32_t ExtractSignedBitfield32(int msb, int lsb, U32 x) { ...@@ -204,6 +206,16 @@ inline int32_t ExtractSignedBitfield32(int msb, int lsb, U32 x) {
} }
template <typename T>
inline T SignExtend(T val, int bitSize) {
T mask = (T(2) << (bitSize - 1)) - T(1);
val &= mask;
T sign_bits = -((val >> (bitSize - 1)) << bitSize);
val |= sign_bits;
return val;
}
inline U16 BITS16L(U32 value) { inline U16 BITS16L(U32 value) {
return static_cast<U16>(value & 0xffff); return static_cast<U16>(value & 0xffff);
} }
......
...@@ -35,13 +35,13 @@ namespace SandHook { ...@@ -35,13 +35,13 @@ namespace SandHook {
delete laterBindlabels; delete laterBindlabels;
} }
protected: public:
CodeContainer* codeContainer; CodeContainer* codeContainer;
std::mutex* relocateLock = new std::mutex(); std::mutex* relocateLock = new std::mutex();
std::map<Addr, Label*>* laterBindlabels = new std::map<Addr, Label*>(); std::map<Addr, Label*>* laterBindlabels = new std::map<Addr, Label*>();
Addr startAddr; Addr startAddr = 0;
Addr length; Addr length = 0;
Addr curOffset; Addr curOffset = 0;
}; };
} }
......
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