Skip to content

Commit

Permalink
api: Update capstone.
Browse files Browse the repository at this point in the history
  • Loading branch information
zhkl0228 committed Jul 29, 2022
1 parent 4050e3b commit 9506c0d
Show file tree
Hide file tree
Showing 13 changed files with 119 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,14 @@ public EventMemHookNotifier(EventMemHook callback, int type, Object user) {
this.type = type;
this.user = user;
}
public void notifyDataAbort(boolean isWrite, long address) {
public void notifyDataAbort(boolean isWrite, int size, long address) {
if (isWrite) {
if ((type & UnicornConst.UC_HOOK_MEM_WRITE_UNMAPPED) != 0) {
callback.hook(HypervisorBackend.this, address, 0, 0L, user, EventMemHook.UnmappedType.Write);
callback.hook(HypervisorBackend.this, address, size, 0L, user, EventMemHook.UnmappedType.Write);
}
} else {
if ((type & UnicornConst.UC_HOOK_MEM_READ_UNMAPPED) != 0) {
callback.hook(HypervisorBackend.this, address, 0, 0L, user, EventMemHook.UnmappedType.Read);
callback.hook(HypervisorBackend.this, address, size, 0L, user, EventMemHook.UnmappedType.Read);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,22 @@ public boolean removeBreakPoint(long address) {
public void handleUnknownException(int ec, long esr, long far, long virtualAddress) {
switch (ec) {
case EC_DATAABORT:
boolean isv = (esr & ARM_EL_ISV) != 0; // Instruction Syndrome Valid. Indicates whether the syndrome information in ISS[23:14] is valid.
boolean isWrite = ((esr >> 6) & 1) != 0;
int sas = (int) ((esr >> 22) & 3); // Syndrome Access Size. Indicates the size of the access attempted by the faulting operation.
int accessSize = isv ? 1 << sas : 0;
int srt = (int) ((esr >> 16) & 0x1f); // Syndrome Register Transfer. The register number of the Wt/Xt/Rt operand of the faulting instruction.
/*
* Width of the register accessed by the instruction is Sixty-Four.
* 0b0 Instruction loads/stores a 32-bit wide register.
* 0b1 Instruction loads/stores a 64-bit wide register.
*/
boolean sf = ((esr >> 15) & 1) != 0;
if (log.isDebugEnabled()) {
log.debug("handleDataAbort srt=" + srt + ", sf=" + sf + ", accessSize=" + accessSize);
}
if (eventMemHookNotifier != null) {
eventMemHookNotifier.notifyDataAbort(isWrite, virtualAddress);
eventMemHookNotifier.notifyDataAbort(isWrite, accessSize, virtualAddress);
}
break;
case EC_INSNABORT:
Expand Down Expand Up @@ -188,7 +201,7 @@ public void onException() {
return true;
}
case EC_DATAABORT: {
boolean isv = (esr & ARM_EL_ISV) != 0;
boolean isv = (esr & ARM_EL_ISV) != 0; // Instruction Syndrome Valid. Indicates whether the syndrome information in ISS[23:14] is valid.
boolean isWrite = ((esr >> 6) & 1) != 0;
boolean s1ptw = ((esr >> 7) & 1) != 0;
int sas = (int) ((esr >> 22) & 3);
Expand All @@ -199,7 +212,8 @@ public void onException() {
log.debug("handle EC_DATAABORT isv=" + isv + ", isWrite=" + isWrite + ", s1ptw=" + s1ptw + ", len=" + len + ", srt=" + srt + ", dfsc=0x" + Integer.toHexString(dfsc) + ", vaddr=0x" + Long.toHexString(far));
}
if (dfsc == 0x00 && emulator.getFamily() == Family.iOS) {
return handleCommRead(far, elr);
int accessSize = isv ? 1 << sas : 0;
return handleCommRead(far, elr, accessSize);
}
throw new UnsupportedOperationException("handleException ec=0x" + Integer.toHexString(ec) + ", dfsc=0x" + Integer.toHexString(dfsc));
}
Expand Down Expand Up @@ -247,8 +261,16 @@ public void hook_add_new(WriteHook callback, long begin, long end, Object user_d
private void onWatchpoint(long esr, long address) {
boolean write = ((esr >> 6) & 1) == 1;
int status = (int) (esr & 0x3f);
/*
* Cache maintenance. Indicates whether the Watchpoint exception came from a cache maintenance or address translation instruction:
* 0b0 The Watchpoint exception was not generated by the execution of one of the System instructions identified in the description of value 1.
* 0b1 The Watchpoint exception was generated by either the execution of a cache maintenance instruction or by a synchronous Watchpoint exception on the execution of an address translation instruction. The DC ZVA, DC GVA, and DC GZVA instructions are not classified as a cache maintenance instructions, and therefore their execution cannot cause this field to be set to 1.
*/
boolean cm = ((esr >> 8) & 1) == 1;
int wpt = (int) ((esr >> 18) & 0x3f); // Watchpoint number, 0 to 15 inclusive.
boolean wptv = ((esr >> 17) & 1) == 1; // The WPT field is valid, and holds the number of a watchpoint that triggered a Watchpoint exception.
if (log.isDebugEnabled()) {
log.debug("onWatchpoint write=" + write + ", address=0x" + Long.toHexString(address) + ", status=0x" + Integer.toHexString(status));
log.debug("onWatchpoint write=" + write + ", address=0x" + Long.toHexString(address) + ", cm=" + cm + ", wpt=" + wpt + ", wptv=" + wptv + ", status=0x" + Integer.toHexString(status));
}
boolean hit = false;
for (int i = 0; i < watchpoints.length; i++) {
Expand Down Expand Up @@ -310,6 +332,17 @@ public void unhook() {

private CodeHookNotifier codeHookNotifier;

/**
* The local exclusive monitor gets cleared on every exception return,that is, on execution of the ERET instruction.
*
* from: <a href="https://xen-devel.narkive.com/wQw4F6GV/xen-arm-software-step-armv8-pc-stuck-on-instruction">...</a>
* LDAXR sets the 'exclusive monitor' and STXR only succeeds if the exclusive
* monitor is still set. If another CPU accesses the memory protected by the
* exclusive monitor, the monitor is cleared. This is how the spinlock code knows
* it has to re-read its value and try to take the lock again.
* Changing exception level also clears the exclusive monitor, so taking
* single-step exception between a LDAXR/STXR pair means the loop has to be retried.
*/
@Override
public void hook_add_new(CodeHook callback, long begin, long end, Object user_data) throws BackendException {
if (codeHookNotifier != null) {
Expand Down Expand Up @@ -341,7 +374,7 @@ private void onSoftwareStep(long esr, long address, long spsr) {
}
}

private boolean handleCommRead(long vaddr, long elr) {
private boolean handleCommRead(long vaddr, long elr, int accessSize) {
Pointer pointer = UnidbgPointer.pointer(emulator, vaddr);
assert pointer != null;
Pointer pc = UnidbgPointer.pointer(emulator, elr);
Expand All @@ -354,7 +387,7 @@ private boolean handleCommRead(long vaddr, long elr) {
OpInfo opInfo = (OpInfo) insn.getOperands();
if (opInfo.isUpdateFlags() || opInfo.isWriteBack() || !insn.getMnemonic().startsWith("ldr") || vaddr < _COMM_PAGE64_BASE_ADDRESS) {
if (eventMemHookNotifier != null) {
eventMemHookNotifier.notifyDataAbort(false, vaddr);
eventMemHookNotifier.notifyDataAbort(false, accessSize, vaddr);
}
return false;
}
Expand All @@ -366,7 +399,7 @@ private boolean handleCommRead(long vaddr, long elr) {
case 0x58: {
Operand operand = op[0];
OpValue value = operand.getValue();
reg_write(value.getUnicornReg(), 0x0L);
reg_write(insn.mapToUnicornReg(value.getReg()), 0x0L);
hypervisor.reg_set_elr_el1(elr + 4);
return true;
}
Expand All @@ -378,7 +411,7 @@ private boolean handleCommRead(long vaddr, long elr) {
case 0x90: {
Operand operand = op[0];
OpValue value = operand.getValue();
reg_write(value.getUnicornReg(), 0x0);
reg_write(insn.mapToUnicornReg(value.getReg()), 0x0);
hypervisor.reg_set_elr_el1(elr + 4);
return true;
}
Expand All @@ -388,7 +421,7 @@ private boolean handleCommRead(long vaddr, long elr) {
case 0x36: { // uint8_t number of logical CPUs (hw.logicalcpu_max)
Operand operand = op[0];
OpValue value = operand.getValue();
reg_write(value.getUnicornReg(), 1);
reg_write(insn.mapToUnicornReg(value.getReg()), 1);
hypervisor.reg_set_elr_el1(elr + 4);
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ private boolean handleCommRead(long vaddr, long elr) {
case 0x58: {
Operand operand = op[0];
OpValue value = operand.getValue();
reg_write(value.getUnicornReg(), 0x0L);
reg_write(insn.mapToUnicornReg(value.getReg()), 0x0L);
kvm.reg_set_elr_el1(elr + 4);
return true;
}
Expand All @@ -107,7 +107,7 @@ private boolean handleCommRead(long vaddr, long elr) {
case 0x90: {
Operand operand = op[0];
OpValue value = operand.getValue();
reg_write(value.getUnicornReg(), 0x0);
reg_write(insn.mapToUnicornReg(value.getReg()), 0x0);
kvm.reg_set_elr_el1(elr + 4);
return true;
}
Expand All @@ -117,7 +117,7 @@ private boolean handleCommRead(long vaddr, long elr) {
case 0x36: { // uint8_t number of logical CPUs (hw.logicalcpu_max)
Operand operand = op[0];
OpValue value = operand.getValue();
reg_write(value.getUnicornReg(), 1);
reg_write(insn.mapToUnicornReg(value.getReg()), 1);
kvm.reg_set_elr_el1(elr + 4);
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions unidbg-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<dependency>
<groupId>com.github.zhkl0228</groupId>
<artifactId>capstone</artifactId>
<version>3.1.7</version>
<version>3.1.8</version>
</dependency>
<dependency>
<groupId>com.github.zhkl0228</groupId>
Expand Down Expand Up @@ -55,7 +55,7 @@
<dependency>
<groupId>com.github.zhkl0228</groupId>
<artifactId>demumble</artifactId>
<version>1.0.3</version>
<version>1.0.4</version>
</dependency>
</dependencies>
</project>
27 changes: 14 additions & 13 deletions unidbg-api/src/main/java/com/github/unidbg/RegAccessPrinter.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.github.unidbg;

import capstone.Arm64_const;
import capstone.Arm_const;
import capstone.api.Instruction;
import com.github.unidbg.arm.Cpsr;
import com.github.unidbg.arm.backend.Backend;
import unicorn.Arm64Const;
import unicorn.ArmConst;

import java.util.Locale;

Expand All @@ -27,34 +27,35 @@ public void print(Emulator<?> emulator, Backend backend, StringBuilder builder,
return;
}
for (short reg : accessRegs) {
int regId = instruction.mapToUnicornReg(reg);
if (emulator.is32Bit()) {
if ((reg >= Arm_const.ARM_REG_R0 && reg <= Arm_const.ARM_REG_R12) ||
reg == Arm_const.ARM_REG_LR || reg == Arm_const.ARM_REG_SP ||
reg == Arm_const.ARM_REG_CPSR) {
if ((regId >= ArmConst.UC_ARM_REG_R0 && regId <= ArmConst.UC_ARM_REG_R12) ||
regId == ArmConst.UC_ARM_REG_LR || regId == ArmConst.UC_ARM_REG_SP ||
regId == ArmConst.UC_ARM_REG_CPSR) {
if (forWriteRegs) {
builder.append(" =>");
forWriteRegs = false;
}
if (reg == Arm_const.ARM_REG_CPSR) {
if (regId == ArmConst.UC_ARM_REG_CPSR) {
Cpsr cpsr = Cpsr.getArm(backend);
builder.append(String.format(Locale.US, " cpsr: N=%d, Z=%d, C=%d, V=%d",
cpsr.isNegative() ? 1 : 0,
cpsr.isZero() ? 1 : 0,
cpsr.hasCarry() ? 1 : 0,
cpsr.isOverflow() ? 1 : 0));
} else {
int value = backend.reg_read(reg).intValue();
int value = backend.reg_read(regId).intValue();
builder.append(' ').append(instruction.regName(reg)).append("=0x").append(Long.toHexString(value & 0xffffffffL));
}
}
} else {
if ((reg >= Arm64_const.ARM64_REG_X0 && reg <= Arm64_const.ARM64_REG_X28) ||
(reg >= Arm64_const.ARM64_REG_X29 && reg <= Arm64_const.ARM64_REG_SP)) {
if ((regId >= Arm64Const.UC_ARM64_REG_X0 && regId <= Arm64Const.UC_ARM64_REG_X28) ||
(regId >= Arm64Const.UC_ARM64_REG_X29 && regId <= Arm64Const.UC_ARM64_REG_SP)) {
if (forWriteRegs) {
builder.append(" =>");
forWriteRegs = false;
}
if (reg == Arm64_const.ARM64_REG_NZCV) {
if (regId == Arm64Const.UC_ARM64_REG_NZCV) {
Cpsr cpsr = Cpsr.getArm64(backend);
if (cpsr.isA32()) {
builder.append(String.format(Locale.US, " cpsr: N=%d, Z=%d, C=%d, V=%d",
Expand All @@ -70,15 +71,15 @@ public void print(Emulator<?> emulator, Backend backend, StringBuilder builder,
cpsr.isOverflow() ? 1 : 0));
}
} else {
long value = backend.reg_read(reg).longValue();
long value = backend.reg_read(regId).longValue();
builder.append(' ').append(instruction.regName(reg)).append("=0x").append(Long.toHexString(value));
}
} else if (reg >= Arm64_const.ARM64_REG_W0 && reg <= Arm64_const.ARM64_REG_W30) {
} else if (regId >= Arm64Const.UC_ARM64_REG_W0 && regId <= Arm64Const.UC_ARM64_REG_W30) {
if (forWriteRegs) {
builder.append(" =>");
forWriteRegs = false;
}
int value = backend.reg_read(reg).intValue();
int value = backend.reg_read(regId).intValue();
builder.append(' ').append(instruction.regName(reg)).append("=0x").append(Long.toHexString(value & 0xffffffffL));
}
}
Expand Down
Loading

0 comments on commit 9506c0d

Please sign in to comment.