com.github.unidbg.ios.ARM32SyscallHandler Maven / Gradle / Ivy
The newest version!
package com.github.unidbg.ios;
import com.github.unidbg.AbstractEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.LongJumpException;
import com.github.unidbg.StopEmulatorException;
import com.github.unidbg.Svc;
import com.github.unidbg.arm.ARM;
import com.github.unidbg.arm.ARMEmulator;
import com.github.unidbg.arm.ArmSvc;
import com.github.unidbg.arm.Cpsr;
import com.github.unidbg.arm.ThumbSvc;
import com.github.unidbg.arm.backend.Backend;
import com.github.unidbg.arm.backend.BackendException;
import com.github.unidbg.arm.context.Arm32RegisterContext;
import com.github.unidbg.arm.context.EditableArm32RegisterContext;
import com.github.unidbg.arm.context.RegisterContext;
import com.github.unidbg.file.FileIO;
import com.github.unidbg.file.FileResult;
import com.github.unidbg.file.ios.DarwinFileIO;
import com.github.unidbg.file.ios.IOConstants;
import com.github.unidbg.ios.file.ByteArrayFileIO;
import com.github.unidbg.ios.file.DriverFileIO;
import com.github.unidbg.ios.file.LocalDarwinUdpSocket;
import com.github.unidbg.ios.file.SocketIO;
import com.github.unidbg.ios.file.TcpSocket;
import com.github.unidbg.ios.file.UdpSocket;
import com.github.unidbg.ios.struct.attr.AttrList;
import com.github.unidbg.ios.struct.kernel.AslServerMessageRequest;
import com.github.unidbg.ios.struct.kernel.ClockGetTimeReply;
import com.github.unidbg.ios.struct.kernel.HostGetClockServiceReply;
import com.github.unidbg.ios.struct.kernel.HostGetClockServiceRequest;
import com.github.unidbg.ios.struct.kernel.HostInfoReply;
import com.github.unidbg.ios.struct.kernel.HostInfoRequest;
import com.github.unidbg.ios.struct.kernel.HostRequestNotificationReply;
import com.github.unidbg.ios.struct.kernel.HostRequestNotificationRequest;
import com.github.unidbg.ios.struct.kernel.IOServiceGetMatchingServiceRequest;
import com.github.unidbg.ios.struct.kernel.MachMsgHeader;
import com.github.unidbg.ios.struct.kernel.MachPortOptions;
import com.github.unidbg.ios.struct.kernel.MachPortReply;
import com.github.unidbg.ios.struct.kernel.MachPortSetAttributesReply;
import com.github.unidbg.ios.struct.kernel.MachPortSetAttributesRequest;
import com.github.unidbg.ios.struct.kernel.MachPortsLookupReply32;
import com.github.unidbg.ios.struct.kernel.MachTimebaseInfo;
import com.github.unidbg.ios.struct.kernel.NotifyServerCancelReply;
import com.github.unidbg.ios.struct.kernel.NotifyServerCancelRequest;
import com.github.unidbg.ios.struct.kernel.NotifyServerGetStateReply;
import com.github.unidbg.ios.struct.kernel.NotifyServerGetStateRequest;
import com.github.unidbg.ios.struct.kernel.NotifyServerRegisterCheckReply;
import com.github.unidbg.ios.struct.kernel.NotifyServerRegisterCheckRequest;
import com.github.unidbg.ios.struct.kernel.NotifyServerRegisterMachPortReply;
import com.github.unidbg.ios.struct.kernel.NotifyServerRegisterMachPortRequest;
import com.github.unidbg.ios.struct.kernel.NotifyServerRegisterPlainReply;
import com.github.unidbg.ios.struct.kernel.NotifyServerRegisterPlainRequest;
import com.github.unidbg.ios.struct.kernel.ProcBsdShortInfo;
import com.github.unidbg.ios.struct.kernel.Pthread;
import com.github.unidbg.ios.struct.kernel.Pthread32;
import com.github.unidbg.ios.struct.kernel.RLimit;
import com.github.unidbg.ios.struct.kernel.SemaphoreCreateReply;
import com.github.unidbg.ios.struct.kernel.SemaphoreCreateRequest;
import com.github.unidbg.ios.struct.kernel.Stat;
import com.github.unidbg.ios.struct.kernel.StatFS;
import com.github.unidbg.ios.struct.kernel.TaskDyldInfoReply;
import com.github.unidbg.ios.struct.kernel.TaskGetExceptionPortsReply;
import com.github.unidbg.ios.struct.kernel.TaskGetExceptionPortsRequest;
import com.github.unidbg.ios.struct.kernel.TaskGetSpecialPortReply;
import com.github.unidbg.ios.struct.kernel.TaskGetSpecialPortRequest;
import com.github.unidbg.ios.struct.kernel.TaskInfoRequest;
import com.github.unidbg.ios.struct.kernel.TaskSetExceptionPortsReply;
import com.github.unidbg.ios.struct.kernel.TaskSetExceptionPortsRequest;
import com.github.unidbg.ios.struct.kernel.ThreadBasicInfoReply;
import com.github.unidbg.ios.struct.kernel.ThreadInfoRequest;
import com.github.unidbg.ios.struct.kernel.ThreadStateReply32;
import com.github.unidbg.ios.struct.kernel.ThreadStateRequest;
import com.github.unidbg.ios.struct.kernel.VmCopyReply;
import com.github.unidbg.ios.struct.kernel.VmCopyRequest;
import com.github.unidbg.ios.struct.kernel.VmRegionRecurse32Reply;
import com.github.unidbg.ios.struct.kernel.VmRegionRecurse32Request;
import com.github.unidbg.ios.struct.kernel.VmRegionReply;
import com.github.unidbg.ios.struct.kernel.VmRegionRequest;
import com.github.unidbg.ios.struct.kernel.VmRemapReply;
import com.github.unidbg.ios.struct.kernel.VmRemapRequest;
import com.github.unidbg.ios.struct.sysctl.IfMsgHeader;
import com.github.unidbg.ios.struct.sysctl.KInfoProc32;
import com.github.unidbg.ios.struct.sysctl.SockAddrDL;
import com.github.unidbg.ios.struct.sysctl.TaskDyldInfo;
import com.github.unidbg.memory.MemoryMap;
import com.github.unidbg.memory.SvcMemory;
import com.github.unidbg.pointer.UnidbgPointer;
import com.github.unidbg.pointer.UnidbgStructure;
import com.github.unidbg.thread.PopContextException;
import com.github.unidbg.thread.RunnableTask;
import com.github.unidbg.thread.Task;
import com.github.unidbg.thread.ThreadContextSwitchException;
import com.github.unidbg.unix.UnixEmulator;
import com.github.unidbg.unix.struct.TimeSpec;
import com.github.unidbg.unix.struct.TimeVal32;
import com.github.unidbg.utils.Inspector;
import com.sun.jna.Pointer;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import unicorn.ArmConst;
import unicorn.UnicornConst;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import static com.github.unidbg.ios.MachO.MAP_MY_FIXED;
import static com.github.unidbg.ios.file.SocketIO.AF_LINK;
import static com.github.unidbg.ios.file.SocketIO.AF_ROUTE;
/**
* http://androidxref.com/4.4.4_r1/xref/external/kernel-headers/original/asm-arm/unistd.h
*/
public class ARM32SyscallHandler extends DarwinSyscallHandler {
private static final Log log = LogFactory.getLog(ARM32SyscallHandler.class);
private final SvcMemory svcMemory;
protected ARM32SyscallHandler(SvcMemory svcMemory) {
super();
this.svcMemory = svcMemory;
}
@SuppressWarnings("unchecked")
@Override
public void hook(Backend backend, int intno, int swi, Object user) {
Emulator emulator = (Emulator) user;
UnidbgPointer pc = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_PC);
final int bkpt;
if (ARM.isThumb(backend)) {
bkpt = pc.getShort(0) & 0xff;
} else {
int instruction = pc.getInt(0);
bkpt = (instruction & 0xf) | ((instruction >> 8) & 0xfff) << 4;
}
if (intno == ARMEmulator.EXCP_BKPT) { // bkpt
createBreaker(emulator).brk(pc, bkpt);
return;
}
if (intno == ARMEmulator.EXCP_UDEF) {
createBreaker(emulator).debug();
return;
}
if (intno != ARMEmulator.EXCP_SWI) {
throw new BackendException("intno=" + intno);
}
int NR = backend.reg_read(ArmConst.UC_ARM_REG_R12).intValue();
String syscall = null;
Throwable exception = null;
try {
if (swi == 0 && (backend.reg_read(ArmConst.UC_ARM_REG_R5).intValue()) == Svc.POST_CALLBACK_SYSCALL_NUMBER && (backend.reg_read(ArmConst.UC_ARM_REG_R7).intValue()) == 0) { // postCallback
int number = backend.reg_read(ArmConst.UC_ARM_REG_R4).intValue();
Svc svc = svcMemory.getSvc(number);
if (svc != null) {
svc.handlePostCallback(emulator);
return;
}
backend.emu_stop();
throw new IllegalStateException("svc number: " + swi);
}
if (swi == 0 && (backend.reg_read(ArmConst.UC_ARM_REG_R5).intValue()) == Svc.PRE_CALLBACK_SYSCALL_NUMBER && (backend.reg_read(ArmConst.UC_ARM_REG_R7).intValue()) == 0) { // preCallback
int number = backend.reg_read(ArmConst.UC_ARM_REG_R4).intValue();
Svc svc = svcMemory.getSvc(number);
if (svc != null) {
svc.handlePreCallback(emulator);
return;
}
backend.emu_stop();
throw new IllegalStateException("svc number: " + swi);
}
if (swi != DARWIN_SWI_SYSCALL) {
if (swi == (ARM.isThumb(backend) ? ThumbSvc.SVC_MAX : ArmSvc.SVC_MAX)) {
throw new PopContextException();
}
if (swi == (ARM.isThumb(backend) ? ThumbSvc.SVC_MAX : ArmSvc.SVC_MAX) - 1) {
throw new ThreadContextSwitchException();
}
Svc svc = svcMemory.getSvc(swi);
if (svc != null) {
backend.reg_write(ArmConst.UC_ARM_REG_R0, (int) svc.handle(emulator));
return;
}
backend.emu_stop();
throw new IllegalStateException("svc number: " + swi + ", NR=" + NR);
}
if (log.isTraceEnabled()) {
ARM.showThumbRegs(emulator);
}
Cpsr.getArm(backend).setCarry(false);
if (handleSyscall(emulator, NR)) {
return;
}
switch (NR) {
case -3:
backend.reg_write(ArmConst.UC_ARM_REG_R0, mach_absolute_time(emulator));
return;
case -10:
backend.reg_write(ArmConst.UC_ARM_REG_R0, _kernelrpc_mach_vm_allocate_trap(emulator));
return;
case -12:
backend.reg_write(ArmConst.UC_ARM_REG_R0, _kernelrpc_mach_vm_deallocate_trap(emulator));
return;
case -15:
backend.reg_write(ArmConst.UC_ARM_REG_R0, _kernelrpc_mach_vm_map_trap(emulator));
return;
case -16:
backend.reg_write(ArmConst.UC_ARM_REG_R0, _kernelrpc_mach_port_allocate_trap(emulator));
return;
case -18:
backend.reg_write(ArmConst.UC_ARM_REG_R0, _kernelrpc_mach_port_deallocate_trap(emulator));
return;
case -19:
backend.reg_write(ArmConst.UC_ARM_REG_R0, _kernelrpc_mach_port_mod_refs_trap(emulator));
return;
case -20:
backend.reg_write(ArmConst.UC_ARM_REG_R0, _kernelrpc_mach_port_move_member_trap(emulator));
return;
case -21:
backend.reg_write(ArmConst.UC_ARM_REG_R0, _kernelrpc_mach_port_insert_right_trap(emulator));
return;
case -22: // _mach_port_insert_member
backend.reg_write(ArmConst.UC_ARM_REG_R0, _mach_port_insert_member(emulator));
return;
case -24:
backend.reg_write(ArmConst.UC_ARM_REG_R0, _kernelrpc_mach_port_construct_trap(emulator));
return;
case -26: // mach_port_t mach_reply_port(...)
backend.reg_write(ArmConst.UC_ARM_REG_R0, mach_reply_port());
return;
case -27:
backend.reg_write(ArmConst.UC_ARM_REG_R0, thread_self_trap());
return;
case -28: // mach_port_name_t task_self_trap(void)
backend.reg_write(ArmConst.UC_ARM_REG_R0, task_self_trap());
return;
case -29:
backend.reg_write(ArmConst.UC_ARM_REG_R0, host_self_trap());
return;
case -31:
backend.reg_write(ArmConst.UC_ARM_REG_R0, mach_msg_trap(emulator));
return;
case -33: // _semaphore_signal_trap
backend.reg_write(ArmConst.UC_ARM_REG_R0, _semaphore_signal_trap(emulator));
return;
case -36: // _semaphore_wait_trap
backend.reg_write(ArmConst.UC_ARM_REG_R0, _semaphore_wait_trap(emulator));
return;
case -41: // _xpc_mach_port_guard
backend.reg_write(ArmConst.UC_ARM_REG_R0, _kernelrpc_mach_port_guard_trap(emulator));
return;
case -59: // swtch_pri
backend.reg_write(ArmConst.UC_ARM_REG_R0, swtch_pri(emulator));
return;
case -61:
backend.reg_write(ArmConst.UC_ARM_REG_R0, thread_switch(emulator));
return;
case -89:
backend.reg_write(ArmConst.UC_ARM_REG_R0, _mach_timebase_info(emulator));
return;
case -91: // mk_timer_create
backend.reg_write(ArmConst.UC_ARM_REG_R0, _mk_timer_create());
return;
case -93: // mk_timer_arm
backend.reg_write(ArmConst.UC_ARM_REG_R0, _mk_timer_arm(emulator));
return;
case 1:
exit(emulator);
return;
case 4:
backend.reg_write(ArmConst.UC_ARM_REG_R0, write(emulator));
return;
case 6:
backend.reg_write(ArmConst.UC_ARM_REG_R0, close(emulator));
return;
case 10:
backend.reg_write(ArmConst.UC_ARM_REG_R0, unlink(emulator));
return;
case 15:
backend.reg_write(ArmConst.UC_ARM_REG_R0, chmod(emulator));
return;
case 16:
backend.reg_write(ArmConst.UC_ARM_REG_R0, chown(emulator));
return;
case 20:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getpid(emulator));
return;
case 24: // getuid
case 25: // geteuid
case 43: // getegid
case 47: // getgid
if (log.isDebugEnabled()) {
log.debug("NR=" + NR);
}
backend.reg_write(ArmConst.UC_ARM_REG_R0, 0);
return;
case 33:
backend.reg_write(ArmConst.UC_ARM_REG_R0, access(emulator));
return;
case 34:
backend.reg_write(ArmConst.UC_ARM_REG_R0, chflags(emulator));
return;
case 37:
backend.reg_write(ArmConst.UC_ARM_REG_R0, kill(emulator));
return;
case 39:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getppid(emulator));
return;
case 46:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sigaction(emulator));
return;
case 48:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sigprocmask(emulator));
return;
case 52:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sigpending(emulator));
return;
case 53:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sigaltstack(emulator));
return;
case 54:
backend.reg_write(ArmConst.UC_ARM_REG_R0, ioctl(emulator));
return;
case 58:
backend.reg_write(ArmConst.UC_ARM_REG_R0, readlink(emulator));
return;
case 73:
backend.reg_write(ArmConst.UC_ARM_REG_R0, munmap(emulator));
return;
case 74:
backend.reg_write(ArmConst.UC_ARM_REG_R0, mprotect(emulator));
return;
case 75:
syscall = "posix_madvise";
backend.reg_write(ArmConst.UC_ARM_REG_R0, 0);
return;
case 92:
case 406: // fcntl_NOCANCEL
backend.reg_write(ArmConst.UC_ARM_REG_R0, fcntl(emulator));
return;
case 95:
backend.reg_write(ArmConst.UC_ARM_REG_R0, fsync(emulator));
return;
case 97:
backend.reg_write(ArmConst.UC_ARM_REG_R0, socket(emulator));
return;
case 98:
backend.reg_write(ArmConst.UC_ARM_REG_R0, connect(emulator));
return;
case 116:
backend.reg_write(ArmConst.UC_ARM_REG_R0, gettimeofday(emulator));
return;
case 121:
backend.reg_write(ArmConst.UC_ARM_REG_R0, writev(emulator));
return;
case 128:
backend.reg_write(ArmConst.UC_ARM_REG_R0, rename(emulator));
return;
case 133:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sendto(emulator));
return;
case 136:
backend.reg_write(ArmConst.UC_ARM_REG_R0, mkdir(emulator));
return;
case 137:
backend.reg_write(ArmConst.UC_ARM_REG_R0, rmdir(emulator));
return;
case 194:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getrlimit(emulator));
return;
case 197:
backend.reg_write(ArmConst.UC_ARM_REG_R0, mmap(emulator));
return;
case 199:
backend.reg_write(ArmConst.UC_ARM_REG_R0, lseek(emulator));
return;
case 201:
backend.reg_write(ArmConst.UC_ARM_REG_R0, ftruncate(emulator));
return;
case 202:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sysctl(emulator));
return;
case 216:
backend.reg_write(ArmConst.UC_ARM_REG_R0, open_dprotected_np(emulator));
return;
case 220:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getattrlist(emulator));
return;
case 221:
backend.reg_write(ArmConst.UC_ARM_REG_R0, setattrlist(emulator));
return;
case 240:
backend.reg_write(ArmConst.UC_ARM_REG_R0, listxattr(emulator));
return;
case 236:
backend.reg_write(ArmConst.UC_ARM_REG_R0, setxattr(emulator));
return;
case 237:
backend.reg_write(ArmConst.UC_ARM_REG_R0, fsetxattr(emulator));
return;
case 286:
backend.reg_write(ArmConst.UC_ARM_REG_R0, pthread_getugid_np(emulator));
return;
case 301:
backend.reg_write(ArmConst.UC_ARM_REG_R0, psynch_mutexwait(emulator));
return;
case 302:
backend.reg_write(ArmConst.UC_ARM_REG_R0, psynch_mutexdrop(emulator));
return;
case 303:
backend.reg_write(ArmConst.UC_ARM_REG_R0, psynch_cvbroad(emulator));
return;
case 305:
backend.reg_write(ArmConst.UC_ARM_REG_R0, psynch_cvwait(emulator));
return;
case 327:
backend.reg_write(ArmConst.UC_ARM_REG_R0, issetugid());
return;
case 328:
backend.reg_write(ArmConst.UC_ARM_REG_R0, pthread_kill(emulator));
return;
case 329:
backend.reg_write(ArmConst.UC_ARM_REG_R0, pthread_sigmask(emulator));
return;
case 330:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sigwait(emulator));
return;
case 331:
backend.reg_write(ArmConst.UC_ARM_REG_R0, disable_threadsignal(emulator));
return;
case 334:
backend.reg_write(ArmConst.UC_ARM_REG_R0, semwait_signal(emulator));
return;
case 336:
backend.reg_write(ArmConst.UC_ARM_REG_R0, proc_info(emulator));
return;
case 338:
backend.reg_write(ArmConst.UC_ARM_REG_R0, stat64(emulator));
return;
case 339:
backend.reg_write(ArmConst.UC_ARM_REG_R0, fstat(emulator));
return;
case 340:
backend.reg_write(ArmConst.UC_ARM_REG_R0, lstat(emulator));
return;
case 344:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getdirentries64(emulator));
return;
case 345:
backend.reg_write(ArmConst.UC_ARM_REG_R0, statfs64(emulator));
return;
case 346:
backend.reg_write(ArmConst.UC_ARM_REG_R0, fstatfs64(emulator));
return;
case 347:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getfsstat64(emulator, 0));
return;
case 357:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getaudit_addr(emulator));
return;
case 360:
backend.reg_write(ArmConst.UC_ARM_REG_R0, bsdthread_create(emulator));
return;
case 361:
backend.reg_write(ArmConst.UC_ARM_REG_R0, bsdthread_terminate(emulator));
return;
case 362:
backend.reg_write(ArmConst.UC_ARM_REG_R0, kqueue());
return;
case 366:
backend.reg_write(ArmConst.UC_ARM_REG_R0, bsdthread_register(emulator));
return;
case 367:
backend.reg_write(ArmConst.UC_ARM_REG_R0, _workq_open());
return;
case 368:
backend.reg_write(ArmConst.UC_ARM_REG_R0, _workq_kernreturn());
return;
case 369:
backend.reg_write(ArmConst.UC_ARM_REG_R0, kevent64(emulator));
return;
case 372:
backend.reg_write(ArmConst.UC_ARM_REG_R0, thread_selfid(emulator));
backend.reg_write(ArmConst.UC_ARM_REG_R1, 0);
return;
case 381:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sandbox_ms(emulator));
return;
case 3:
case 396:
backend.reg_write(ArmConst.UC_ARM_REG_R0, read_NOCANCEL(emulator));
return;
case 397:
backend.reg_write(ArmConst.UC_ARM_REG_R0, write_NOCANCEL(emulator));
return;
case 5: // unix open
case 398:
backend.reg_write(ArmConst.UC_ARM_REG_R0, open_NOCANCEL(emulator, 0));
return;
case 266:
backend.reg_write(ArmConst.UC_ARM_REG_R0, shm_open(emulator));
return;
case 399:
backend.reg_write(ArmConst.UC_ARM_REG_R0, close_NOCANCEL(emulator));
return;
case 423:
backend.reg_write(ArmConst.UC_ARM_REG_R0, semwait_signal(emulator));
return;
case 428:
backend.reg_write(ArmConst.UC_ARM_REG_R0, audit_session_self());
return;
case 443:
backend.reg_write(ArmConst.UC_ARM_REG_R0, guarded_kqueue_np(emulator));
return;
case 0x80000000:
NR = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
if(handleMachineDependentSyscall(emulator, NR)) {
return;
}
default:
break;
}
} catch (StopEmulatorException e) {
backend.emu_stop();
return;
} catch (LongJumpException e) {
backend.emu_stop();
throw e;
} catch (Throwable e) {
backend.emu_stop();
exception = e;
}
log.warn("handleInterrupt intno=" + intno + ", NR=" + NR + ", svcNumber=0x" + Integer.toHexString(swi) + ", PC=" + pc + ", syscall=" + syscall, exception);
if (log.isDebugEnabled() || LogFactory.getLog(AbstractEmulator.class).isDebugEnabled()) {
createBreaker(emulator).debug();
}
if (exception instanceof RuntimeException) {
throw (RuntimeException) exception;
}
}
private int _kernelrpc_mach_port_move_member_trap(Emulator emulator) {
RegisterContext context = emulator.getContext();
int task = context.getIntArg(0);
int member = context.getIntArg(1);
int after = context.getIntArg(2);
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_port_move_member_trap task=" + task + ", member=" + member + ", after=" + after);
}
return 0;
}
private int chflags(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer path = context.getPointerArg(0);
int flags = context.getIntArg(1);
String pathname = path.getString(0);
log.info("chflags paht=" + pathname + ", flags=0x" + Integer.toHexString(flags));
return -1;
}
private int open_dprotected_np(Emulator emulator) {
RegisterContext context = emulator.getContext();
Pointer path = context.getPointerArg(0);
int flags = context.getIntArg(1);
int _class = context.getIntArg(2);
int dpflags = context.getIntArg(3);
String pathname = path.getString(0);
log.info("open_dprotected_np path=" + pathname + ", flags=0x" + Integer.toHexString(flags) + ", class=" + _class + ", dpflags=0x" + Integer.toHexString(dpflags));
return -1;
}
private int fsetxattr(Emulator emulator) {
Arm32RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
Pointer name = context.getPointerArg(1);
Pointer value = context.getPointerArg(2);
int size = context.getIntArg(3);
int position = context.getR4Int();
int options = context.getR5Int();
log.info("fsetxattr fd=" + fd + ", name=" + name.getString(0) + ", value=" + value + ", size=" + size + ", position=" + position + ", options=0x" + Integer.toHexString(options));
return -1;
}
private int setxattr(Emulator emulator) {
Arm32RegisterContext context = emulator.getContext();
Pointer path = context.getPointerArg(0);
Pointer name = context.getPointerArg(1);
Pointer value = context.getPointerArg(2);
int size = context.getIntArg(3);
int position = context.getR4Int();
int options = context.getR5Int();
log.info("setxattr pat=" + path.getString(0) + ", name=" + name.getString(0) + ", value=" + value + ", size=" + size + ", position=" + position + ", options=0x" + Integer.toHexString(options));
return -1;
}
private int getattrlist(Emulator emulator) {
Arm32RegisterContext context = emulator.getContext();
Pointer path = context.getPointerArg(0);
Pointer attrListPointer = context.getPointerArg(1);
UnidbgPointer attrBuf = context.getPointerArg(2);
int attrBufSize = context.getIntArg(3);
int options = context.getR4Int();
String pathname = path.getString(0);
AttrList attrList = new AttrList(attrListPointer);
attrBuf.setSize(attrBufSize);
String msg = "getattrlist path=" + pathname + ", attrList=" + attrList + ", attrBuf=" + attrBuf + ", attrBufSize=" + attrBufSize + ", options=0x" + Integer.toHexString(options);
FileResult result = resolve(emulator, pathname, IOConstants.O_RDONLY);
if (result != null && result.isSuccess()) {
int ret = result.io.getattrlist(attrList, attrBuf, attrBufSize);
if (ret != 0) {
log.info(msg + ", ret=" + ret);
} else {
if (log.isDebugEnabled()) {
log.debug(msg + ", ret=" + ret);
}
}
return ret;
}
emulator.getMemory().setErrno(result != null ? result.errno : UnixEmulator.EACCES);
log.info(msg);
return -1;
}
private int setattrlist(Emulator emulator) {
Arm32RegisterContext context = emulator.getContext();
Pointer path = context.getPointerArg(0);
Pointer attrListPointer = context.getPointerArg(1);
UnidbgPointer attrBuf = context.getPointerArg(2);
int attrBufSize = context.getIntArg(3);
int options = context.getR4Int();
String pathname = path.getString(0);
AttrList attrList = new AttrList(attrListPointer);
attrBuf.setSize(attrBufSize);
String msg = "setattrlist path=" + pathname + ", attrList=" + attrList + ", attrBuf=" + attrBuf + ", attrBufSize=" + attrBufSize + ", options=0x" + Integer.toHexString(options);
FileResult result = resolve(emulator, pathname, IOConstants.O_RDONLY);
if (result != null && result.isSuccess()) {
int ret = result.io.setattrlist(attrList, attrBuf, attrBufSize);
if (ret != 0) {
log.info(msg + ", ret=" + ret);
} else {
if (log.isDebugEnabled()) {
log.debug(msg + ", ret=" + ret);
}
}
return ret;
}
emulator.getMemory().setErrno(result != null ? result.errno : UnixEmulator.EACCES);
log.info(msg);
return -1;
}
private int fsync(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
if (log.isDebugEnabled()) {
log.debug("fsync fd=" + fd);
}
return 0;
}
private int sigaltstack(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer nstack = context.getPointerArg(0);
Pointer ostack = context.getPointerArg(1);
log.info("sigaltstack nstack=" + nstack + ", ostack=" + ostack);
return 0;
}
private int ioctl(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
long request = context.getLongArg(1);
long argp = context.getLongArg(2);
if (log.isDebugEnabled()) {
log.debug("ioctl fd=" + fd + ", request=0x" + Long.toHexString(request) + ", argp=0x" + Long.toHexString(argp));
}
FileIO file = fdMap.get(fd);
if (file == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
int ret = file.ioctl(emulator, request, argp);
if (ret == -1) {
emulator.getMemory().setErrno(UnixEmulator.ENOTTY);
}
return ret;
}
private boolean handleMachineDependentSyscall(Emulator> emulator, int NR) {
Backend backend = emulator.getBackend();
switch (NR) {
case 0:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sys_icache_invalidate(emulator));
return true;
case 1:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sys_dcache_flush(emulator));
return true;
case 2:
backend.reg_write(ArmConst.UC_ARM_REG_R0, pthread_set_self(emulator));
return true;
}
return false;
}
private int pthread_set_self(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer self = context.getPointerArg(0);
Pthread pthread = new Pthread32(self.getPointer(0));
pthread.unpack();
UnidbgPointer tsd = pthread.getTSD();
emulator.getBackend().reg_write(ArmConst.UC_ARM_REG_C13_C0_3, tsd.peer);
Task task = emulator.get(Task.TASK_KEY);
if (task != null && task.isMainThread()) {
MachOLoader loader = (MachOLoader) emulator.getMemory();
loader.setErrnoPointer(pthread.getErrno());
}
if (log.isDebugEnabled()) {
String threadName = pthread.getName();
log.debug("pthread_set_self=" + self + ", pthread=" + pthread + ", threadName=" + threadName + ", LR=" + emulator.getContext().getLRPointer());
}
return 0;
}
private int sys_dcache_flush(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer address = context.getPointerArg(0);
long size = context.getLongArg(1);
if (log.isDebugEnabled()) {
log.debug("sys_dcache_flush address=" + address + ", size=" + size);
}
return 0;
}
private int sys_icache_invalidate(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer address = context.getPointerArg(0);
long size = context.getLongArg(1);
if (log.isDebugEnabled()) {
log.debug("sys_icache_invalidate address=" + address + ", size=" + size);
}
return 0;
}
private int pthread_getugid_np(Emulator> emulator) {
Pointer uid = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
Pointer gid = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
if (log.isDebugEnabled()) {
log.debug("pthread_getugid_np uid=" + uid + ", gid=" + gid);
}
uid.setInt(0, 0);
gid.setInt(0, 0);
return 0;
}
private int _mach_timebase_info(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer pointer = context.getPointerArg(0);
MachTimebaseInfo info = new MachTimebaseInfo(pointer);
info.denom = 1;
info.numer = 1;
info.pack();
if (log.isDebugEnabled()) {
log.debug("_mach_timebase_info info=" + info + ", LR=" + context.getLRPointer());
}
return 0;
}
private int _mk_timer_create() {
if (log.isDebugEnabled()) {
log.debug("_mk_timer_create");
}
return STATIC_PORT;
}
private int _mk_timer_arm(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int port = context.getIntArg(0);
long time = context.getLongArg(1);
if (log.isDebugEnabled()) {
log.debug("_mk_timer_arm port=" + port + ", time=" + time);
}
return 0;
}
private int readlink(Emulator> emulator) {
Backend emulatorBackend = emulator.getBackend();
Pointer pathname = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
Pointer buf = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int bufSize = emulatorBackend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
String path = pathname.getString(0);
if (log.isDebugEnabled()) {
log.debug("readlink path=" + path + ", buf=" + buf + ", bufSize=" + bufSize);
}
if ("/var/db/timezone/localtime".equals(path)) { // 设置时区
path = "/var/db/timezone/zoneinfo/Asia/Shanghai";
}
buf.setString(0, path);
return path.length() + 1;
}
private int psynch_mutexdrop(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
Pointer mutex = context.getPointerArg(0);
int mgen = context.getIntArg(1);
int ugen = context.getIntArg(2);
long tid = context.getR3Int();
int flags = context.getR5Int();
if (log.isDebugEnabled()) {
log.debug("psynch_mutexdrop mutex=" + mutex + ", mgen=" + mgen + ", ugen=" + ugen + ", tid=" + tid + ", flags=0x" + Integer.toHexString(flags) + ", LR=" + context.getLRPointer());
}
return 0;
}
private int psynch_mutexwait(Emulator> emulator) {
// TODO: implement
Arm32RegisterContext context = emulator.getContext();
Pointer mutex = context.getPointerArg(0);
int mgen = context.getIntArg(1);
int ugen = context.getIntArg(2);
long tid = context.getR3Int();
int flags = context.getR5Int();
if (log.isDebugEnabled()) {
log.debug("psynch_mutexwait mutex=" + mutex + ", mgen=" + mgen + ", ugen=" + ugen + ", tid=" + tid + ", flags=0x" + Integer.toHexString(flags) + ", LR=" + context.getLRPointer());
}
return 0;
}
private int bsdthread_create(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
UnidbgPointer start_routine = context.getPointerArg(0);
UnidbgPointer arg = context.getPointerArg(1);
UnidbgPointer stack = context.getPointerArg(2);
UnidbgPointer thread = context.getPointerArg(3);
int flags = context.getR4Int();
return (int) bsdthread_create(emulator, start_routine, arg, stack, thread, flags);
}
private int _workq_open() {
// TODO: implement
log.info("_workq_open");
return 0;
}
private int _workq_kernreturn() {
// TODO: implement
log.info("_workq_kernreturn");
return 0;
}
private int kevent64(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
int kq = context.getR0Int();
Pointer changelist = context.getR1Pointer();
int nchanges = context.getR2Int();
Pointer eventlist = context.getR3Pointer();
int nevents = context.getR4Int();
int flags = context.getR5Int();
Pointer timeout = context.getR6Pointer();
return kevent64(emulator, kq, changelist, nchanges, eventlist, nevents, flags, TimeSpec.createTimeSpec(emulator, timeout));
}
private int _kernelrpc_mach_port_allocate_trap(Emulator> emulator) {
Backend backend = emulator.getBackend();
int task = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int right = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
Pointer name = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_port_allocate_trap task=" + task + ", right=" + right + ", name=" + name);
}
name.setInt(0, STATIC_PORT);
return 0;
}
private int _kernelrpc_mach_port_insert_right_trap(Emulator> emulator) {
Backend backend = emulator.getBackend();
int task = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int name = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int poly = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
int polyPoly = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_port_insert_right_trap task=" + task + ", name=" + name + ", poly=" + poly + ", polyPoly=" + polyPoly);
}
return 0;
}
private int _mach_port_insert_member(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int task = context.getIntArg(0);
int name = context.getIntArg(1);
int pset = context.getIntArg(2);
if (log.isDebugEnabled()) {
log.debug("_mach_port_insert_member task=" + task + ", name=" + name + ", pset=" + pset);
}
return 0;
}
private int _semaphore_signal_trap(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int port = context.getIntArg(0);
log.info("_semaphore_signal_trap port=" + port);
if (log.isDebugEnabled() || LogFactory.getLog(AbstractEmulator.class).isDebugEnabled()) {
createBreaker(emulator).debug();
}
return 0;
}
private long _kernelrpc_mach_port_guard_trap(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int task = context.getIntArg(0);
int name = context.getIntArg(1);
Pointer guard = context.getPointerArg(2);
int strict = context.getIntArg(3);
log.info("_kernelrpc_mach_port_guard_trap task=" + task + ", name=" + name + ", guard=" + guard + ", strict=" + strict);
return 0;
}
private int thread_switch(Emulator> emulator) {
// TODO: implement
RegisterContext context = emulator.getContext();
int thread_name = context.getIntArg(0);
int option = context.getIntArg(1);
int option_time = context.getIntArg(2);
log.info("thread_switch thread_name=" + thread_name + ", option=" + option + ", option_time=" + option_time);
return 0;
}
private int psynch_cvwait(Emulator> emulator) {
if (threadDispatcherEnabled) {
throw new ThreadContextSwitchException();
}
log.info("psynch_cvwait LR=" + emulator.getContext().getLRPointer());
emulator.attach().debug();
emulator.getMemory().setErrno(UnixEmulator.EINTR);
return -1;
}
private int close(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
if (log.isDebugEnabled()) {
log.debug("close fd=" + fd);
}
return close(emulator, fd);
}
private int lseek(Emulator> emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int r1 = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
long r2 = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
long offset = r1 | (r2 << 32);
int whence = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
FileIO file = fdMap.get(fd);
if (file == null) {
if (log.isDebugEnabled()) {
log.debug("lseek fd=" + fd + ", offset=" + offset + ", whence=" + whence);
}
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
int pos = file.lseek((int) offset, whence);
if (log.isDebugEnabled()) {
log.debug("lseek fd=" + fd + ", offset=" + offset + ", whence=" + whence + ", pos=" + pos);
}
return pos;
}
private int ftruncate(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
int length = context.getIntArg(1);
if (log.isDebugEnabled()) {
log.debug("ftruncate fd=" + fd + ", length=" + length);
}
FileIO file = fdMap.get(fd);
if (file == null) {
throw new UnsupportedOperationException();
}
return file.ftruncate(length);
}
private int unlink(Emulator> emulator) {
Pointer pathname = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
String path = FilenameUtils.normalize(pathname.getString(0), true);
emulator.getFileSystem().unlink(path);
return 0;
}
private int chown(Emulator emulator) {
RegisterContext context = emulator.getContext();
Pointer path = context.getPointerArg(0);
int uid = context.getIntArg(1);
int gid = context.getIntArg(2);
String pathname = path.getString(0);
log.info("chown path=" + pathname + ", uid=" + uid + ", gid=" + gid);
return 0;
}
private int getdirentries64(Emulator emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
UnidbgPointer buf = context.getPointerArg(1);
int bufSize = context.getIntArg(2);
Pointer basep = context.getPointerArg(3);
if (log.isDebugEnabled()) {
log.debug("getdirentries64 fd=" + fd + ", buf=" + buf + ", bufSize=" + bufSize + ", basep=" + basep + ", LR=" + context.getLRPointer());
}
DarwinFileIO io = fdMap.get(fd);
if (io == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
} else {
buf.setSize(bufSize);
return io.getdirentries64(buf, bufSize);
}
}
protected int statfs64(Emulator emulator) {
RegisterContext context = emulator.getContext();
Pointer pathPointer = context.getPointerArg(0);
Pointer buf = context.getPointerArg(1);
String path = pathPointer.getString(0);
FileResult result = resolve(emulator, path, IOConstants.O_RDONLY);
if (log.isDebugEnabled()) {
log.debug("statfs64 pathPointer=" + pathPointer + ", buf=" + buf + ", path=" + path);
}
if (result != null && result.isSuccess()) {
return result.io.fstatfs(new StatFS(buf));
}
log.info("statfs64 pathPointer=" + pathPointer + ", buf=" + buf + ", path=" + path);
throw new BackendException("statfs64 path=" + path + ", buf=" + buf);
}
private int fstatfs64(Emulator> emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer buf = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
if (log.isDebugEnabled()) {
log.debug("fstatfs64 fd=" + fd + ", buf=" + buf);
}
DarwinFileIO io = fdMap.get(fd);
if (io != null) {
return io.fstatfs(new StatFS(buf));
}
emulator.getMemory().setErrno(UnixEmulator.EACCES);
return -1;
}
private int stat64(Emulator emulator) {
RegisterContext context = emulator.getContext();
Pointer pathname = context.getPointerArg(0);
Pointer statbuf = context.getPointerArg(1);
String path = pathname.getString(0);
if (log.isDebugEnabled()) {
log.debug("stat64 pathname=" + path + ", statbuf=" + statbuf + ", LR=" + context.getLRPointer());
}
return stat64(emulator, FilenameUtils.normalize(path, true), statbuf);
}
protected int fstat(Emulator emulator, int fd, Pointer stat) {
if (log.isDebugEnabled()) {
log.debug("fstat fd=" + fd + ", stat=" + stat);
}
DarwinFileIO file = fdMap.get(fd);
if (file == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
if (log.isDebugEnabled()) {
log.debug("fstat file=" + file + ", stat=" + stat);
}
return file.fstat(emulator, new Stat(stat));
}
protected int stat64(Emulator emulator, String pathname, Pointer statbuf) {
FileResult result = resolve(emulator, pathname, IOConstants.O_RDONLY);
if (result != null && result.isSuccess()) {
return result.io.fstat(emulator, new Stat(statbuf));
}
emulator.getMemory().setErrno(result != null ? result.errno : UnixEmulator.ENOENT);
return -1;
}
private int write_NOCANCEL(Emulator> emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer buffer = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int count = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
return write(emulator, fd, buffer, count);
}
private int fstat(Emulator emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer stat = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
return fstat(emulator, fd, stat);
}
/**
* lstat() is identical to stat(), except that if pathname is a symbolic link, then it returns information about the link itself, not the file that it refers to.
*/
private int lstat(Emulator emulator) {
Arm32RegisterContext context = emulator.getContext();
Pointer pathname = context.getR0Pointer();
Pointer stat = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
String pathStr = pathname.getString(0);
String path = FilenameUtils.normalize(pathStr, true);
if (log.isDebugEnabled()) {
log.debug("lstat path=" + path + ", pathStr=" + pathStr + ", stat=" + stat);
}
return stat64(emulator, path, stat);
}
private static final int RLIMIT_NOFILE = 8; /* number of open files */
private static final int RLIMIT_POSIX_FLAG = 0x1000; /* Set bit for strict POSIX */
private int getrlimit(Emulator> emulator) {
Backend backend = emulator.getBackend();
int resource = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer rlp = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
boolean posix = (resource & RLIMIT_POSIX_FLAG) != 0;
int type = resource & (RLIMIT_POSIX_FLAG - 1);
String msg = "getrlimit resource=0x" + Integer.toHexString(resource) + ", rlp=" + rlp + ", posix=" + posix + ", type=" + type;
if (type == RLIMIT_NOFILE) {
if (log.isDebugEnabled()) {
log.debug(msg);
}
RLimit rLimit = new RLimit(rlp);
rLimit.rlim_cur = 128;
rLimit.rlim_max = 256;
rLimit.pack();
return 0;
} else {
log.info(msg);
}
return 1;
}
private int _kernelrpc_mach_port_mod_refs_trap(Emulator> emulator) {
Backend backend = emulator.getBackend();
int task = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int name = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int right = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
int delta = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_port_mod_refs_trap task=" + task + ", name=" + name + ", right=" + right + ", delta=" + delta);
}
return 0;
}
private int _kernelrpc_mach_port_construct_trap(Emulator> emulator) {
Backend backend = emulator.getBackend();
int task = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer options = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int r2 = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
long r3 = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
long context = r2 | (r3 << 32);
Pointer name = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R4);
if (log.isDebugEnabled()) {
MachPortOptions portOptions = new MachPortOptions(options);
portOptions.unpack();
log.debug("_kernelrpc_mach_port_construct_trap task=" + task + ", options=" + options + ", context=0x" + Long.toHexString(context) + ", name=" + name + ", portOptions=" + portOptions);
}
name.setInt(0, 0x88);
return 0;
}
private int getaudit_addr(Emulator> emulator) {
Backend backend = emulator.getBackend();
Pointer addr = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
int size = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
if (log.isDebugEnabled()) {
log.debug("getaudit_addr=" + addr + ", size=" + size);
}
return 0;
}
private int semwait_signal(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
int cond_sem = context.getR0Int();
int mutex_sem = context.getR1Int();
int timeout = context.getR2Int();
int relative = context.getR3Int();
long tv_sec = context.getR4Int() | (long) context.getR5Int() << 32;
int tv_nsec = context.getR6Int();
RunnableTask runningTask = emulator.getThreadDispatcher().getRunningTask();
String msg = "semwait_signal cond_sem=" + cond_sem + ", mutex_sem=" + mutex_sem + ", timeout=" + timeout + ", relative=" + relative + ", tv_sec=" + tv_sec + ", tv_nsec=" + tv_nsec;
if (threadDispatcherEnabled && runningTask != null) {
if (log.isDebugEnabled()) {
log.debug(msg);
}
return semwait_signal(emulator, runningTask, cond_sem, mutex_sem, timeout, relative, tv_sec, tv_nsec);
}
log.info(msg);
try {
Thread.sleep(tv_sec * 1000L + tv_nsec / 1000L, tv_nsec % 1000);
emulator.getMemory().setErrno(ETIMEDOUT);
return -1;
} catch (InterruptedException e) {
emulator.getMemory().setErrno(UnixEmulator.EINVAL);
return -1;
}
}
private static final int PROC_INFO_CALL_SETCONTROL = 0x5;
private static final int PROC_SELFSET_THREADNAME = 2;
private static final int PROC_INFO_CALL_PIDINFO = 0x2;
private static final int PROC_PIDT_SHORTBSDINFO = 13;
private int proc_info(Emulator> emulator) {
Backend backend = emulator.getBackend();
int callNum = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int pid = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int flavor = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
int r3 = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
long r4 = backend.reg_read(ArmConst.UC_ARM_REG_R4).intValue();
long arg = r3 | (r4 << 32);
Pointer buffer = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R5);
int bufferSize = backend.reg_read(ArmConst.UC_ARM_REG_R6).intValue();
String msg = "proc_info callNum=" + callNum + ", pid=" + pid + ", flavor=" + flavor + ", arg=" + arg + ", buffer=" + buffer + ", bufferSize=" + bufferSize;
if (PROC_INFO_CALL_SETCONTROL == callNum && PROC_SELFSET_THREADNAME == flavor) {
String threadName = buffer.getString(0);
if (log.isDebugEnabled()) {
log.debug(msg + ", threadName=" + threadName);
}
return 0;
} else if (PROC_INFO_CALL_PIDINFO == callNum && PROC_PIDT_SHORTBSDINFO == flavor) {
ProcBsdShortInfo info = new ProcBsdShortInfo(buffer);
info.unpack();
String processName = emulator.getProcessName();
if (processName == null) {
processName = "unidbg";
}
info.pbsi_pid = pid;
info.pbsi_status = ProcBsdShortInfo.SRUN;
info.pbsi_comm = Arrays.copyOf(Arrays.copyOf(processName.getBytes(), DarwinSyscall.MAXCOMLEN-1), DarwinSyscall.MAXCOMLEN);
info.pbsi_flags = 0x24090;
info.pbsi_uid = 0;
info.pbsi_ruid = 0;
info.pbsi_svuid = 0;
info.pbsi_gid = 0;
info.pbsi_rgid = 0;
info.pbsi_svgid = 0;
info.pbsi_pgid = 0;
info.pbsi_ppid = pid - 1;
info.pack();
if (log.isDebugEnabled()) {
log.debug(msg + ", info=" + info);
}
return info.size();
} else {
log.info(msg);
return 1;
}
}
private int sandbox_ms(Emulator> emulator) {
Backend backend = emulator.getBackend();
Pointer policyName = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
int call = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
Pointer args = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
if (log.isDebugEnabled()) {
log.debug("sandbox_ms policyName=" + policyName.getString(0) + ", call=" + call + ", args=" + args);
}
return 0;
}
private int issetugid() {
log.debug("issetugid");
return 0;
}
private int bsdthread_register(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
UnidbgPointer thread_start = context.getR0Pointer();
UnidbgPointer start_wqthread = context.getR1Pointer();
int pthreadSize = context.getR2Int();
UnidbgPointer data = context.getR3Pointer();
int dataSize = context.getR4Int();
int r5 = context.getR5Int();
long r6 = context.getR6Int();
long offset = r5 | (r6 << 32);
if (log.isDebugEnabled()) {
log.debug("bsdthread_register thread_start=" + thread_start + ", start_wqthread=" + start_wqthread + ", pthreadSize=" + pthreadSize + ", data=" + data + ", dataSize=" + dataSize + ", offset=0x" + Long.toHexString(offset));
}
return bsdthread_register(thread_start, pthreadSize);
}
private int munmap(Emulator> emulator) {
Backend backend = emulator.getBackend();
long timeInMillis = System.currentTimeMillis();
long start = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue() & 0xffffffffL;
int length = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
emulator.getMemory().munmap(start, length);
if (log.isDebugEnabled()) {
log.debug("munmap start=0x" + Long.toHexString(start) + ", length=" + length + ", offset=" + (System.currentTimeMillis() - timeInMillis));
}
return 0;
}
private int sysctl(Emulator> emulator) {
Backend backend = emulator.getBackend();
Pointer name = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
int namelen = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
Pointer buffer = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
Pointer bufferSize = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R3);
Pointer set0 = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R4);
int set1 = backend.reg_read(ArmConst.UC_ARM_REG_R5).intValue();
int top = name.getInt(0);
switch (top) {
case CTL_UNSPEC:
int action = name.getInt(4);
if (action == 3) {
byte[] bytes = set0.getByteArray(0, set1);
String sub = new String(bytes, StandardCharsets.UTF_8);
if (log.isDebugEnabled()) {
log.debug("sysctl CTL_UNSPEC action=" + action + ", namelen=" + namelen + ", buffer=" + buffer + ", bufferSize=" + bufferSize + ", sub=" + sub);
}
if ("unidbg.debug".equals(sub)) {
return LogFactory.getLog("com.github.unidbg.ios.debug").isDebugEnabled() ? 1 : 0;
}
if ("kern.ostype".equals(sub)) {
buffer.setInt(0, CTL_KERN);
buffer.setInt(4, KERN_OSTYPE);
bufferSize.setInt(0, 8);
return 0;
}
if ("kern.osrelease".equals(sub)) {
buffer.setInt(0, CTL_KERN);
buffer.setInt(4, KERN_OSRELEASE);
bufferSize.setInt(0, 8);
return 0;
}
if ("kern.version".equals(sub)) {
buffer.setInt(0, CTL_KERN);
buffer.setInt(4, KERN_VERSION);
bufferSize.setInt(0, 8);
return 0;
}
if ("kern.osversion".equals(sub)) {
buffer.setInt(0, CTL_KERN);
buffer.setInt(4, KERN_OSVERSION);
bufferSize.setInt(0, 8);
return 0;
}
if ("kern.boottime".equals(sub)) {
buffer.setInt(0, CTL_KERN);
buffer.setInt(4, KERN_BOOTTIME);
bufferSize.setInt(0, 8);
return 0;
}
if ("hw.machine".equals(sub)) {
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_MACHINE);
bufferSize.setInt(0, 8);
return 0;
}
if ("hw.model".equals(sub)) {
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_MODEL);
bufferSize.setInt(0, 8);
return 0;
}
if ("hw.cputype".equals(sub)) {
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_CPU_TYPE);
bufferSize.setInt(0, 8);
return 0;
}
if ("hw.cpusubtype".equals(sub)) {
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_CPU_SUBTYPE);
bufferSize.setInt(0, 8);
return 0;
}
if ("hw.cpufamily".equals(sub)) {
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_CPU_FAMILY);
bufferSize.setLong(0, 8);
return 0;
}
if ("hw.ncpu".equals(sub)) {
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_NCPU);
bufferSize.setInt(0, 8);
return 0;
}
if ("hw.memsize".equals(sub)) {
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_MEMSIZE);
bufferSize.setInt(0, 8);
return 0;
}
if (log.isDebugEnabled()) {
createBreaker(emulator).debug();
}
return -1;
}
log.info("sysctl CTL_UNSPEC action=" + action + ", namelen=" + namelen + ", buffer=" + buffer + ", bufferSize=" + bufferSize + ", set0=" + set0 + ", set1=" + set1);
break;
case CTL_KERN:
action = name.getInt(4);
String msg = "sysctl CTL_KERN action=" + action + ", namelen=" + namelen + ", buffer=" + buffer + ", bufferSize=" + bufferSize + ", set0=" + set0 + ", set1=" + set1;
switch (action) {
case KERN_PROCARGS2:
log.info(msg);
return 1;
case KERN_OSTYPE:
log.debug(msg);
String osType = "Darwin";
if (bufferSize != null) {
bufferSize.setInt(0, osType.length() + 1);
}
if (buffer != null) {
buffer.setString(0, osType);
}
return 0;
case KERN_OSRELEASE:
log.debug(msg);
String osRelease = "7.1.2";
if (bufferSize != null) {
bufferSize.setInt(0, osRelease.length() + 1);
}
if (buffer != null) {
buffer.setString(0, osRelease);
}
return 0;
case KERN_VERSION:
log.debug(msg);
String version = "Darwin Kernel Version 14.0.0: Sun Mar 29 19:47:37 PDT 2015; root:xnu-2784.20.34~2/RELEASE_ARM64_S5L8960X";
if (bufferSize != null) {
bufferSize.setInt(0, version.length() + 1);
}
if (buffer != null) {
buffer.setString(0, version);
}
return 0;
case KERN_ARGMAX:
bufferSize.setInt(0, 4);
buffer.setInt(0, 128);
return 0;
case KERN_HOSTNAME:
log.debug(msg);
String host = "localhost";
if (bufferSize != null) {
bufferSize.setInt(0, host.length() + 1);
}
if (buffer != null) {
buffer.setString(0, host);
}
return 0;
case KERN_PROC:
int subType = name.getInt(8);
if (subType == KERN_PROC_PID) {
int pid = name.getInt(0xc);
KInfoProc32 kInfoProc = new KInfoProc32(buffer);
kInfoProc.unpack();
kInfoProc.kp_proc.p_flag = 0; // P_TRACED
kInfoProc.kp_eproc.e_ucred.cr_uid = 0;
kInfoProc.pack();
if (log.isDebugEnabled()) {
log.debug(msg + ", subType=" + subType + ", pid=" + pid + ", kInfoProc=" + kInfoProc);
}
return 0;
}
log.info(msg + ", subType=" + subType);
break;
case KERN_OSVERSION:
log.debug(msg);
String osVersion = "9A127";
if (bufferSize != null) {
bufferSize.setInt(0, osVersion.length() + 1);
}
if (buffer != null) {
buffer.setString(0, osVersion);
}
return 0;
case KERN_USRSTACK32:
if (bufferSize != null) {
bufferSize.setInt(0, 4);
}
if (buffer != null) {
buffer.setInt(0, (int) emulator.getMemory().getStackBase());
}
return 0;
case KERN_BOOTTIME:
if (bufferSize != null) {
bufferSize.setInt(0, UnidbgStructure.calculateSize(TimeVal32.class));
}
if (buffer != null) {
fillKernelBootTime(buffer);
}
return 0;
default:
log.info(msg);
break;
}
break;
case CTL_HW:
action = name.getInt(4);
msg = "sysctl CTL_HW action=" + action + ", namelen=" + namelen + ", buffer=" + buffer + ", bufferSize=" + bufferSize + ", set0=" + set0 + ", set1=" + set1;
switch (action) {
case HW_CPU_FREQ:
if (bufferSize != null) {
bufferSize.setLong(0, 4);
}
if (buffer != null) {
buffer.setInt(0, 1800000000);
}
return 0;
case HW_PAGESIZE:
log.debug(msg);
if (bufferSize != null) {
bufferSize.setInt(0, 4);
}
if (buffer != null) {
buffer.setInt(0, emulator.getPageAlign());
}
return 0;
case HW_CPU_TYPE:
log.debug(msg);
if (bufferSize != null) {
bufferSize.setInt(0, 4);
}
if (buffer != null) {
buffer.setInt(0, CPU_TYPE_ARM);
}
return 0;
case HW_CPU_SUBTYPE:
log.debug(msg);
if (bufferSize != null) {
bufferSize.setInt(0, 4);
}
if (buffer != null) {
buffer.setInt(0, CPU_SUBTYPE_ARM_V7);
}
return 0;
case HW_CPU_FAMILY:
log.debug(msg);
if (bufferSize != null) {
bufferSize.setInt(0, 4);
}
if (buffer != null) {
buffer.setInt(0, 933271106);
}
return 0;
case HW_MACHINE:
log.debug(msg);
String machine = getHwMachine();
if (bufferSize != null) {
bufferSize.setInt(0, machine.length() + 1);
}
if (buffer != null) {
buffer.setString(0, machine);
}
return 0;
case HW_MODEL:
log.debug(msg);
String model = "N53AP";
if (bufferSize != null) {
bufferSize.setInt(0, model.length() + 1);
}
if (buffer != null) {
buffer.setString(0, model);
}
return 0;
case HW_NCPU:
log.debug(msg);
if (bufferSize != null) {
bufferSize.setInt(0, 4);
}
if (buffer != null) {
buffer.setInt(0, getHwNcpu()); // 2 cpus
}
return 0;
case HW_MEMSIZE:
if (bufferSize != null) {
bufferSize.setInt(0, 8);
}
if (buffer != null) {
long memSize = 2L * 1024 * 1024 * 1024; // 2G
buffer.setLong(0, memSize);
}
return 0;
}
log.info(msg);
break;
case CTL_NET:
action = name.getInt(4); // AF_ROUTE
msg = "sysctl CTL_NET action=" + action + ", namelen=" + namelen + ", buffer=" + buffer + ", bufferSize=" + bufferSize + ", set0=" + set0 + ", set1=" + set1;
int family = name.getInt(0xc); // AF_INET
int rt = name.getInt(0x10);
if(action == AF_ROUTE && rt == NET_RT_IFLIST) {
try {
List networkIFList = DarwinUtils.getNetworkIFs(isVerbose());
int sizeOfSDL = UnidbgStructure.calculateSize(SockAddrDL.class);
int entrySize = UnidbgStructure.calculateSize(IfMsgHeader.class) + sizeOfSDL;
if (bufferSize != null) {
bufferSize.setInt(0, entrySize * networkIFList.size());
}
if (buffer != null) {
Pointer pointer = buffer;
short index = 0;
for (DarwinUtils.NetworkIF networkIF : networkIFList) {
IfMsgHeader header = new IfMsgHeader(pointer);
SockAddrDL sockAddr = new SockAddrDL(pointer.share(header.size()));
header.ifm_msglen = (short) entrySize;
header.ifm_version = 5;
header.ifm_type = RTM_IFINFO;
header.ifm_addrs = 0x10;
header.ifm_index = ++index;
header.ifm_data.ifi_type = 6; // ethernet
header.pack();
byte[] networkInterfaceName = networkIF.networkInterface.getName().getBytes();
sockAddr.sdl_len = (byte) sizeOfSDL;
sockAddr.sdl_family = AF_LINK;
sockAddr.sdl_index = index;
sockAddr.sdl_type = 6; // ethernet
sockAddr.sdl_nlen = (byte) networkInterfaceName.length;
System.arraycopy(networkInterfaceName, 0, sockAddr.sdl_data, 0, networkInterfaceName.length);
byte[] macAddress = networkIF.networkInterface.getHardwareAddress();
sockAddr.sdl_alen = (byte) macAddress.length;
System.arraycopy(macAddress, 0, sockAddr.sdl_data, networkInterfaceName.length, macAddress.length);
sockAddr.pack();
pointer = pointer.share(entrySize);
}
}
return 0;
} catch (SocketException e) {
throw new IllegalStateException(e);
}
}
log.info(msg + ", family=" + family + ", rt=" + rt);
if (log.isDebugEnabled()) {
createBreaker(emulator).debug();
}
default:
log.info("sysctl top=" + name.getInt(0) + ", namelen=" + namelen + ", buffer=" + buffer + ", bufferSize=" + bufferSize + ", set0=" + set0 + ", set1=" + set1);
break;
}
return -1;
}
private int _kernelrpc_mach_vm_deallocate_trap(Emulator> emulator) {
Backend backend = emulator.getBackend();
int target = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
long r1 = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
long r2 = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
long address = r1 | (r2 << 32);
long r3 = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
long r4 = backend.reg_read(ArmConst.UC_ARM_REG_R4).intValue();
long size = r3 | (r4 << 32);
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_vm_deallocate_trap target=" + target + ", address=0x" + Long.toHexString(address) + ", size=0x" + Long.toHexString(size));
} else {
Log log = LogFactory.getLog("com.github.unidbg.ios.malloc");
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_vm_deallocate_trap target=" + target + ", address=0x" + Long.toHexString(address) + ", size=0x" + Long.toHexString(size) + ", lr=" + UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_LR));
}
}
if (size > 0) {
emulator.getMemory().munmap(address, (int) size);
}
return 0;
}
@Override
protected void fillKernelBootTime(Pointer buffer) {
long currentTimeMillis = bootTime;
long tv_sec = currentTimeMillis / 1000;
long tv_usec = (currentTimeMillis % 1000) * 1000 + (bootTime / 7 % 1000);
TimeVal32 timeVal = new TimeVal32(buffer);
timeVal.tv_sec = (int) tv_sec;
timeVal.tv_usec = (int) tv_usec;
timeVal.pack();
}
private int _kernelrpc_mach_vm_map_trap(Emulator> emulator) {
Backend backend = emulator.getBackend();
int target = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer address = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int r2 = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
long r3 = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
long size = (r3 << 32) | r2;
int r4 = backend.reg_read(ArmConst.UC_ARM_REG_R4).intValue();
long r5 = backend.reg_read(ArmConst.UC_ARM_REG_R5).intValue();
long mask = (r5 << 32) | r4;
int flags = backend.reg_read(ArmConst.UC_ARM_REG_R6).intValue();
int cur_protection = backend.reg_read(ArmConst.UC_ARM_REG_R8).intValue();
int tag = flags >> 24;
boolean anywhere = (flags & MachO.VM_FLAGS_ANYWHERE) != 0;
if (!anywhere) {
throw new BackendException("_kernelrpc_mach_vm_map_trap fixed");
}
Pointer value = address.getPointer(0);
UnidbgPointer pointer;
if (mask != 0) {
MachOLoader loader = (MachOLoader) emulator.getMemory();
pointer = UnidbgPointer.pointer(emulator, loader.allocate(size, mask));
} else {
pointer = emulator.getMemory().mmap((int) size, cur_protection);
}
String msg = "_kernelrpc_mach_vm_map_trap target=" + target + ", address=" + address + ", value=" + value + ", size=0x" + Long.toHexString(size) + ", mask=0x" + Long.toHexString(mask) + ", flags=0x" + Long.toHexString(flags) + ", cur_protection=" + cur_protection + ", pointer=" + pointer + ", anywhere=true, tag=0x" + Integer.toHexString(tag);
if (log.isDebugEnabled()) {
log.debug(msg);
} else {
Log log = LogFactory.getLog("com.github.unidbg.ios.malloc");
if (log.isDebugEnabled()) {
log.debug(msg);
}
}
address.setPointer(0, pointer);
return 0;
}
private int _kernelrpc_mach_vm_allocate_trap(Emulator> emulator) {
Backend backend = emulator.getBackend();
int target = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer address = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
long r2 = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
long r3 = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
long size = r2 | (r3 << 32);
int flags = backend.reg_read(ArmConst.UC_ARM_REG_R4).intValue();
int tag = flags >> 24;
boolean anywhere = (flags & MachO.VM_FLAGS_ANYWHERE) != 0;
if (!anywhere) {
long start = address.getInt(0) & 0xffffffffL;
long ret = emulator.getMemory().mmap2(start, (int) size, UnicornConst.UC_PROT_READ | UnicornConst.UC_PROT_WRITE, MAP_MY_FIXED, -1, 0);
if (ret == 0) {
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_vm_allocate_trap fixed, address=" + address.getPointer(0) + ", size=" + size + ", flags=0x" + Integer.toHexString(flags));
}
if (tag != MachO.VM_MEMORY_REALLOC) {
throw new IllegalStateException("_kernelrpc_mach_vm_allocate_trap fixed, address=" + address.getPointer(0) + ", size=" + size + ", flags=0x" + Integer.toHexString(flags) + ", tag=" + tag);
}
return -1;
}
Pointer pointer = address.getPointer(0);
pointer.write(0, new byte[(int) size], 0, (int) size);
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_vm_allocate_trap fixed, address=" + pointer + ", size=" + size + ", flags=0x" + Integer.toHexString(flags));
}
return 0;
}
Pointer value = address.getPointer(0);
UnidbgPointer pointer = emulator.getMemory().mmap((int) size, UnicornConst.UC_PROT_READ | UnicornConst.UC_PROT_WRITE);
pointer.write(0, new byte[(int) size], 0, (int) size);
address.setPointer(0, pointer);
String str = "_kernelrpc_mach_vm_allocate_trap target=" + target + ", address=" + address + ", value=" + value + ", size=0x" + Long.toHexString(size) + ", flags=0x" + Integer.toHexString(flags) + ", pointer=" + pointer + ", anywhere=true, tag=0x" + Integer.toHexString(tag);
if (log.isDebugEnabled()) {
log.debug(str);
} else {
Log log = LogFactory.getLog("com.github.unidbg.ios.malloc");
if (log.isDebugEnabled()) {
log.debug(str);
}
}
return 0;
}
private int _kernelrpc_mach_port_deallocate_trap(Emulator> emulator) {
Backend backend = emulator.getBackend();
int task = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int name = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_port_deallocate_trap task=" + task + ", name=" + name);
}
return 0;
}
// https://github.com/lunixbochs/usercorn/blob/master/go/kernel/mach/ports.go
private int mach_msg_trap(Emulator> emulator) {
Backend backend = emulator.getBackend();
Arm32RegisterContext context = emulator.getContext();
UnidbgPointer msg = context.getR0Pointer();
int option = context.getR1Int();
int send_size = context.getR2Int();
int rcv_size = context.getR3Int();
int rcv_name = context.getR4Int();
int timeout = context.getR5Int();
int notify = context.getR6Int();
msg.setSize(Math.max(send_size, rcv_size));
final MachMsgHeader header = new MachMsgHeader(msg);
header.unpack();
if (log.isDebugEnabled()) {
log.debug("mach_msg_trap msg=" + msg + ", option=0x" + Integer.toHexString(option) + ", send_size=" + send_size + ", rcv_size=" + rcv_size + ", rcv_name=" + rcv_name + ", timeout=" + timeout + ", notify=" + notify + ", header=" + header);
}
final Pointer request = msg.share(header.size());
switch (header.msgh_id) {
case 3409: // task_get_special_port
{
TaskGetSpecialPortRequest args = new TaskGetSpecialPortRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("task_get_special_port request=" + args);
}
if (args.which == TASK_BOOTSTRAP_PORT) {
TaskGetSpecialPortReply reply = new TaskGetSpecialPortReply(request);
reply.unpack();
header.msgh_bits = (header.msgh_bits & 0xff) | MACH_MSGH_BITS_COMPLEX;
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.body.msgh_descriptor_count = 1;
reply.port.name = BOOTSTRAP_PORT; // I just chose 11 randomly here
reply.port.pad1 = 0;
reply.port.pad2 = 0;
reply.port.disposition = 17; // meaning?
reply.port.type = MACH_MSG_PORT_DESCRIPTOR;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("task_get_special_port reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
}
case 200: // host_info
{
HostInfoRequest args = new HostInfoRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("host_info args=" + args);
}
if (args.flavor == HOST_PRIORITY_INFO) {
HostInfoReply reply = new HostInfoReply(request);
reply.unpack();
header.msgh_bits &= 0xff;
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.NDR = args.NDR;
reply.retCode = 0; // success
reply.host_info_outCnt = 8;
reply.host_info_out.kernel_priority = 0;
reply.host_info_out.system_priority = 0;
reply.host_info_out.server_priority = 0;
reply.host_info_out.user_priority = 0;
reply.host_info_out.depress_priority = 0;
reply.host_info_out.idle_priority = 0;
reply.host_info_out.minimum_priority = 10;
reply.host_info_out.maximum_priority = -10;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("host_info reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
}
case 3603: { // _thread_get_state
ThreadStateRequest args = new ThreadStateRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("_thread_get_state args=" + request);
}
ThreadStateReply32 reply = new ThreadStateReply32(request);
reply.unpack();
header.setMsgBits(false);
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
if (args.flavor != ThreadStateRequest.ARM_THREAD_STATE) {
reply.retCode = 4;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("_thread_get_state reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
reply.retCode = 0;
reply.outCnt = ThreadStateRequest.ARM_THREAD_STATE_COUNT;
for (int reg = ArmConst.UC_ARM_REG_R0; reg <= ArmConst.UC_ARM_REG_R12; reg++) {
reply.state.__r[reg - ArmConst.UC_ARM_REG_R0] = backend.reg_read(reg).intValue();
}
reply.state.__sp = backend.reg_read(ArmConst.UC_ARM_REG_SP).intValue();
reply.state.__lr = backend.reg_read(ArmConst.UC_ARM_REG_LR).intValue();
reply.state.__pc = backend.reg_read(ArmConst.UC_ARM_REG_PC).intValue();
reply.state.__cpsr = backend.reg_read(ArmConst.UC_ARM_REG_CPSR).intValue();
reply.pack();
if (log.isDebugEnabled()) {
log.debug("_thread_get_state reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 3612: { // _thread_info
ThreadInfoRequest args = new ThreadInfoRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("_thread_info args=" + args);
}
final int THREAD_BASIC_INFO = 3;
if (args.flavor != THREAD_BASIC_INFO) {
throw new UnsupportedOperationException();
}
ThreadBasicInfoReply reply = new ThreadBasicInfoReply(request);
reply.unpack();
header.setMsgBits(false);
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
final int THREAD_BASIC_INFO_COUNT = 10;
final int POLICY_TIMESHARE = 1;
final int TH_STATE_RUNNING = 1;
reply.retCode = 0;
reply.outCnt = THREAD_BASIC_INFO_COUNT;
reply.info.user_time.tv_sec = 0;
reply.info.user_time.tv_usec = 177546;
reply.info.system_time.tv_sec = 0;
reply.info.system_time.tv_usec = 0;
reply.info.cpu_usage = 343;
reply.info.policy = POLICY_TIMESHARE;
reply.info.run_state = TH_STATE_RUNNING;
reply.info.flags = 0;
reply.info.suspend_count = 0;
reply.info.sleep_time = 0;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("_thread_info reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 1000: { // clock_get_time
ClockGetTimeReply reply = new ClockGetTimeReply(request);
reply.unpack();
header.setMsgBits(false);
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
long currentTimeMillis = System.currentTimeMillis();
long nanoTime = System.nanoTime();
long tv_sec = currentTimeMillis / 1000;
long tv_usec = (currentTimeMillis % 1000) * 1000 + nanoTime % 1000;
reply.retCode = 0;
reply.tv_sec = (int) tv_sec;
reply.tv_nsec = (int) tv_usec;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("clock_get_time reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 206: // host_get_clock_service
{
HostGetClockServiceRequest args = new HostGetClockServiceRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("host_get_clock_service args=" + args);
}
HostGetClockServiceReply reply = new HostGetClockServiceReply(request);
reply.unpack();
header.msgh_bits = (header.msgh_bits & 0xff) | MACH_MSGH_BITS_COMPLEX;
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.body.msgh_descriptor_count = 1;
reply.clock_server.name = CLOCK_SERVER_PORT; // I just chose 13 randomly here
reply.clock_server.pad1 = 0;
reply.clock_server.pad2 = 0;
reply.clock_server.disposition = 17; // meaning?
reply.clock_server.type = MACH_MSG_PORT_DESCRIPTOR;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("host_get_clock_service reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 3418: // semaphore_create
{
SemaphoreCreateRequest args = new SemaphoreCreateRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("semaphore_create args=" + args);
}
SemaphoreCreateReply reply = new SemaphoreCreateReply(request);
reply.unpack();
header.setMsgBits(true);
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.body.msgh_descriptor_count = 1;
reply.semaphore.name = ThreadLocalRandom.current().nextInt() & 0x7fffffff;
reply.semaphore.pad1 = 0;
reply.semaphore.pad2 = 0;
reply.semaphore.disposition = 17; // meaning?
reply.semaphore.type = MACH_MSG_PORT_DESCRIPTOR;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("semaphore_create reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 3822: // vm_region_recurse_64
{
VmRegionRecurse32Request args = new VmRegionRecurse32Request(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("vm_region_recurse_64 args=" + args);
}
VmRegionRecurse32Reply reply = new VmRegionRecurse32Reply(request);
reply.unpack();
header.msgh_bits &= 0xff;
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
MemoryMap memoryMap = null;
for (MemoryMap mm : emulator.getMemory().getMemoryMap()) {
if (args.getAddress() >= mm.base && args.getAddress() < mm.base + mm.size) {
memoryMap = mm;
break;
}
}
if (log.isDebugEnabled()) {
log.debug("vm_region_recurse_64 header=" + header + ", memoryMap=" + memoryMap);
}
if (memoryMap == null) {
log.warn("vm_region_recurse_64 failed address=0x" + args.address + ", size=0x" + Integer.toHexString(args.size()));
return -1;
}
reply.NDR = args.NDR;
reply.retCode = 0; // success
reply.address = (int) memoryMap.base;
reply.size = (int) memoryMap.size;
reply.infoCnt = 7;
reply.nestingDepth = 0;
reply.info.protection = memoryMap.prot;
reply.info.max_protection = memoryMap.prot;
reply.info.inheritance = memoryMap.prot;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("vm_region_recurse_64 reply=" + reply + ", memoryMap=" + memoryMap);
}
return MACH_MSG_SUCCESS;
}
case 3413: { // task_set_exception_ports
TaskSetExceptionPortsRequest args = new TaskSetExceptionPortsRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("task_set_exception_ports args=" + args + ", lr=" + UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_LR));
}
TaskSetExceptionPortsReply reply = new TaskSetExceptionPortsReply(request);
reply.unpack();
header.setMsgBits(false);
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.NDR = args.NDR;
reply.retCode = 0;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("task_set_exception_ports reply=" + reply + ", header=" + header);
}
return MACH_MSG_SUCCESS;
}
case 3414: // task_get_exception_ports
{
TaskGetExceptionPortsRequest args = new TaskGetExceptionPortsRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("task_get_exception_ports args=" + args + ", lr=" + UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_LR));
}
TaskGetExceptionPortsReply reply = new TaskGetExceptionPortsReply(request);
reply.unpack();
header.msgh_bits = (header.msgh_bits & 0xff) | MACH_MSGH_BITS_COMPLEX;
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
args.NDR.mig_vers = 0x20;
reply.NDR = args.NDR;
reply.retCode = 0;
reply.header = new int[32];
reply.reserved = new byte[0x100];
reply.pack();
if (log.isDebugEnabled()) {
log.debug("task_get_exception_ports reply=" + reply + ", header=" + header);
}
return MACH_MSG_SUCCESS;
}
case 3404: // mach_ports_lookup
{
MachPortsLookupReply32 reply = new MachPortsLookupReply32(request);
reply.unpack();
header.msgh_bits = (header.msgh_bits & 0xff) | MACH_MSGH_BITS_COMPLEX;
header.msgh_size = 52;
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.retCode = 1;
reply.outPort = (int) UnidbgPointer.nativeValue(request);
reply.ret = 0;
reply.mask = 0x2110000;
reply.cnt = 0;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("mach_ports_lookup reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 3808: // vm_copy
{
VmCopyRequest args = new VmCopyRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("vm_copy args=" + args + ", lr=" + UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_LR));
}
byte[] data = backend.mem_read(args.source_address, args.size);
emulator.getMemory().pointer(args.dest_address).write(data);
VmCopyReply reply = new VmCopyReply(request);
reply.unpack();
header.msgh_bits &= 0xff;
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.retCode = 0;
reply.NDR = args.NDR;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("vm_copy reply=" + reply + ", header=" + header);
}
return MACH_MSG_SUCCESS;
}
case 4813: // _kernelrpc_mach_vm_remap
{
VmRemapRequest args = new VmRemapRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_vm_remap args=" + args + ", lr=" + UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_LR));
}
if ((args.anywhere != MachO.VM_FLAGS_OVERWRITE && args.anywhere != MachO.VM_FLAGS_FIXED) ||
args.mask != 0) {
throw new UnsupportedOperationException("_kernelrpc_mach_vm_remap anywhere=0x" + Integer.toHexString(args.anywhere) + ", mask=0x" + Long.toHexString(args.mask));
}
MachOLoader loader = (MachOLoader) emulator.getMemory();
loader.remap(args);
if (args.copy != 0) {
byte[] data = backend.mem_read(args.getSourceAddress(), args.size);
loader.pointer(args.target_address).write(data);
}
VmRemapReply reply = new VmRemapReply(request);
reply.unpack();
header.msgh_bits &= 0xff;
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.body.msgh_descriptor_count = 1;
reply.retCode = 0;
reply.target_address1 = (int) args.target_address;
reply.target_address2 = (int) (args.target_address >> 32);
reply.cur_protection = args.inheritance;
reply.max_protection = args.inheritance;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_vm_remap reply=" + reply + ", header=" + header);
}
return MACH_MSG_SUCCESS;
}
case 404: { // vproc_mig_look_up2
return vproc_mig_look_up2(request, header);
}
case 78945669: { // notify_server_register_plain
NotifyServerRegisterPlainRequest args = new NotifyServerRegisterPlainRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
Pointer pointer = UnidbgPointer.pointer(emulator, args.name);
log.debug("notify_server_register_plain args=" + args + ", name=" + (pointer == null ? null : new String(pointer.getByteArray(0, args.nameCnt), StandardCharsets.UTF_8)));
}
NotifyServerRegisterPlainReply reply = new NotifyServerRegisterPlainReply(request);
reply.unpack();
header.msgh_bits &= 0xff;
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.body.msgh_descriptor_count = 1;
reply.ret = 0;
reply.code = 0;
reply.clientId = STATIC_PORT;
reply.status = NOTIFY_STATUS_OK;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("notify_server_register_plain reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 78945681: { // notify_server_get_state
NotifyServerGetStateRequest args = new NotifyServerGetStateRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("notify_server_get_state args=" + args);
}
NotifyServerGetStateReply reply = new NotifyServerGetStateReply(request);
reply.unpack();
header.msgh_bits &= 0xff;
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.body.msgh_descriptor_count = 1;
reply.ret = 0;
reply.code = 0;
reply.version = 0;
reply.pid = emulator.getPid();
reply.status = NOTIFY_STATUS_OK;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("notify_server_get_state reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 78945679: { // notify_server_cancel
NotifyServerCancelRequest args = new NotifyServerCancelRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("notify_server_cancel args=" + args);
}
NotifyServerCancelReply reply = new NotifyServerCancelReply(request);
reply.unpack();
header.msgh_bits &= 0xff;
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.body.msgh_descriptor_count = 1;
reply.ret = 0;
reply.code = 0;
reply.status = NOTIFY_STATUS_OK;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("notify_server_cancel reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 78945670: { // notify_server_register_check
NotifyServerRegisterCheckRequest args = new NotifyServerRegisterCheckRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
Pointer pointer = UnidbgPointer.pointer(emulator, args.name & 0xffffffffL);
log.debug("notify_server_register_check args=" + args + ", name=" + (pointer == null ? null : new String(pointer.getByteArray(0, args.namelen), StandardCharsets.UTF_8)));
}
NotifyServerRegisterCheckReply reply = new NotifyServerRegisterCheckReply(request);
reply.unpack();
header.msgh_bits &= 0xff;
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.body.msgh_descriptor_count = 1;
reply.ret = 0;
reply.code = 0;
reply.shmsize = 0;
reply.slot = 0;
reply.clientId = STATIC_PORT;
reply.status = NOTIFY_STATUS_OK;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("notify_server_register_check reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 118: { // asl_server_message
AslServerMessageRequest args = new AslServerMessageRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("asl_server_message args=" + args);
}
return MACH_MSG_SUCCESS;
}
case 78945673: { // notify_server_register_mach_port
NotifyServerRegisterMachPortRequest args = new NotifyServerRegisterMachPortRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
Pointer pointer = UnidbgPointer.pointer(emulator, args.name);
log.debug("notify_server_register_mach_port args=" + args + ", name=" + (pointer == null ? null : new String(pointer.getByteArray(0, args.namelen), StandardCharsets.UTF_8)));
}
NotifyServerRegisterMachPortReply reply = new NotifyServerRegisterMachPortReply(request);
reply.unpack();
header.msgh_bits &= 0xff;
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.body.msgh_descriptor_count = 1;
reply.ret = 0;
reply.code = 0;
reply.clientId = STATIC_PORT;
reply.status = NOTIFY_STATUS_OK;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("notify_server_register_mach_port reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 205: { // host_get_io_master
MachPortReply reply = new MachPortReply(request);
reply.unpack();
header.setMsgBits(true);
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.body.msgh_descriptor_count = 1;
reply.port.name = STATIC_PORT;
reply.port.pad1 = 0;
reply.port.pad2 = 0;
reply.port.disposition = 17;
reply.port.type = MACH_MSG_PORT_DESCRIPTOR;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("host_get_io_master reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 2873: { // io_service_get_matching_service
IOServiceGetMatchingServiceRequest args = new IOServiceGetMatchingServiceRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("io_service_get_matching_service args=" + args + ", matching=" + args.getMatching());
}
MachPortReply reply = new MachPortReply(request);
reply.unpack();
header.setMsgBits(true);
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.body.msgh_descriptor_count = 1;
reply.port.name = STATIC_PORT;
reply.port.pad1 = 0;
reply.port.pad2 = 0;
reply.port.disposition = 17;
reply.port.type = MACH_MSG_PORT_DESCRIPTOR;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("io_service_get_matching_service reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 3218: { // _kernelrpc_mach_port_set_attributes
MachPortSetAttributesRequest args = new MachPortSetAttributesRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_port_set_attributes args=" + args);
}
MachPortSetAttributesReply reply = new MachPortSetAttributesReply(request);
reply.unpack();
header.setMsgBits(false);
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.retCode = 0;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_port_set_attributes reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 3800: { // vm_region
VmRegionRequest args = new VmRegionRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("vm_region args=" + args);
}
if (args.flavor != VmRegionRequest.VM_REGION_BASIC_INFO) {
throw new UnsupportedOperationException("flavor=" + args.flavor);
}
VmRegionReply reply = new VmRegionReply(request);
reply.unpack();
header.setMsgBits(true);
header.msgh_size = header.size() + reply.size() - 4;
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
MemoryMap memoryRegion = null;
for (MemoryMap memoryMap : emulator.getMemory().getMemoryMap()) {
if (memoryMap.base >= args.address) {
memoryRegion = memoryMap;
break;
}
}
if (memoryRegion == null) {
header.setMsgBits(false);
header.msgh_size = 0x24;
header.pack();
reply.pad1 = 1;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("vm_region reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
reply.NDR.mig_vers = 1;
reply.NDR.int_rep = 0;
reply.retCode = 0x110000;
reply.outCnt = VmRegionRequest.VM_REGION_BASIC_INFO_COUNT;
reply.address = (int) memoryRegion.base;
reply.size = (int) memoryRegion.size;
reply.info.protection = memoryRegion.prot;
reply.info.max_protection = memoryRegion.prot;
reply.info.inheritance = 0;
reply.info.shared = false;
reply.info.reserved = false;
reply.info.offset = 0;
reply.info.behavior = 0;
reply.info.user_wired_count = 0;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("vm_region reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
case 3405: { // task_info
TaskInfoRequest args = new TaskInfoRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("task_info args=" + args);
}
if (args.flavor == TaskInfoRequest.TASK_DYLD_INFO) {
TaskDyldInfoReply reply = new TaskDyldInfoReply(request);
reply.unpack();
header.setMsgBits(false);
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.retCode = 0;
reply.task_info_outCnt = UnidbgStructure.calculateSize(TaskDyldInfo.class) / 4;
reply.dyldInfo.allocateAllImage(emulator);
reply.pack();
if (log.isDebugEnabled()) {
log.debug("task_info TASK_DYLD_INFO reply=" + reply);
}
return MACH_MSG_SUCCESS;
}
throw new UnsupportedOperationException("flavor=" + args.flavor);
}
case 217: // host_request_notification
HostRequestNotificationRequest args = new HostRequestNotificationRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("host_request_notification args=" + args);
}
HostRequestNotificationReply reply = new HostRequestNotificationReply(request);
reply.unpack();
header.setMsgBits(false);
header.msgh_size = header.size() + reply.size();
header.msgh_remote_port = header.msgh_local_port;
header.msgh_local_port = 0;
header.msgh_id += 100; // reply Id always equals reqId+100
header.pack();
reply.retCode = 0;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("host_request_notification reply=" + reply);
}
return MACH_MSG_SUCCESS;
case 216: // host_statistics
if (host_statistics(request, header)) {
return MACH_MSG_SUCCESS;
}
default:
log.warn("mach_msg_trap header=" + header + ", size=" + header.size() + ", lr=" + UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_LR));
if (log.isDebugEnabled() || LogFactory.getLog(AbstractEmulator.class).isDebugEnabled()) {
createBreaker(emulator).debug();
}
break;
}
return -1;
}
private static final int BOOTSTRAP_PORT = 11;
private static final int CLOCK_SERVER_PORT = 13;
private int task_self_trap() {
log.debug("task_self_trap");
return 1;
}
private int host_self_trap() {
log.debug("host_self_trap");
return 2;
}
private int thread_self_trap() {
log.debug("thread_self_trap");
return 3;
}
private int mach_reply_port() {
log.debug("mach_reply_port");
return 4;
}
private int audit_session_self() {
log.debug("audit_session_self");
return 5;
}
private int sigprocmask(Emulator> emulator) {
Backend backend = emulator.getBackend();
int how = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer set = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
Pointer oldset = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
return sigprocmask(emulator, how, set, oldset);
}
protected int gettimeofday(Emulator> emulator) {
EditableArm32RegisterContext context = emulator.getContext();
long currentTimeMillis = System.currentTimeMillis();
long tv_sec = currentTimeMillis / 1000;
long tv_usec = (currentTimeMillis % 1000) * 1000;
context.setR1((int) tv_usec);
if (log.isDebugEnabled()) {
log.debug("gettimeofday tv_sec=" + tv_sec + ", tv_usec=" + tv_usec);
}
return (int) tv_sec;
}
private int writev(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
Pointer iov = context.getPointerArg(1);
int iovcnt = context.getIntArg(2);
if (log.isDebugEnabled()) {
for (int i = 0; i < iovcnt; i++) {
Pointer iov_base = iov.getPointer(i * 8L);
int iov_len = iov.getInt(i * 8L + 4);
byte[] data = iov_base.getByteArray(0, iov_len);
Inspector.inspect(data, "writev fd=" + fd + ", iov=" + iov + ", iov_base=" + iov_base);
}
}
FileIO file = fdMap.get(fd);
if (file == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
int count = 0;
for (int i = 0; i < iovcnt; i++) {
Pointer iov_base = iov.getPointer(i * 8L);
int iov_len = iov.getInt(i * 8L + 4);
byte[] data = iov_base.getByteArray(0, iov_len);
count += file.write(data);
}
return count;
}
private int rename(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
Pointer oldpath = context.getR0Pointer();
Pointer newpath = context.getR1Pointer();
String oldPath = oldpath.getString(0);
String newPath = newpath.getString(0);
int ret = emulator.getFileSystem().rename(oldPath, newPath);
if (ret != 0) {
log.info("rename oldPath=" + oldPath + ", newPath=" + newPath);
} else {
log.debug("rename oldPath=" + oldPath + ", newPath=" + newPath);
}
return 0;
}
private int mach_absolute_time(Emulator> emulator) {
long nanoTime = System.nanoTime();
if (log.isDebugEnabled()) {
log.debug("mach_absolute_time nanoTime=" + nanoTime);
}
emulator.getBackend().reg_write(ArmConst.UC_ARM_REG_R1, (int) (nanoTime >> 32));
return (int) (nanoTime);
}
private int close_NOCANCEL(Emulator> emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
if (log.isDebugEnabled()) {
log.debug("close_NOCANCEL fd=" + fd);
}
return close(emulator, fd);
}
private int read_NOCANCEL(Emulator> emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer buffer = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int count = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
if (log.isDebugEnabled()) {
log.debug("read_NOCANCEL fd=" + fd + ", buffer=" + buffer + ", count=" + count);
}
return read(emulator, fd, buffer, count);
}
private int shm_open(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer pointer = context.getPointerArg(0);
int oflags = context.getIntArg(1);
int mode = context.getIntArg(2);
String name = pointer.getString(0);
if (log.isDebugEnabled()) {
log.debug("shm_open name=" + name + ", oflags=0x" + Integer.toHexString(oflags) + ", mode=" + Integer.toHexString(mode));
}
emulator.getMemory().setErrno(UnixEmulator.EACCES);
return -1;
}
private int getppid(Emulator> emulator) {
if (log.isDebugEnabled()) {
log.debug("getppid");
}
return emulator.getPid();
}
private int getpid(Emulator> emulator) {
int pid = emulator.getPid();
log.debug("getpid pid=" + pid);
return pid;
}
private int mkdir(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer pathname = context.getPointerArg(0);
int mode = context.getIntArg(1);
String path = pathname.getString(0);
if (emulator.getFileSystem().mkdir(path, mode)) {
if (log.isDebugEnabled()) {
log.debug("mkdir pathname=" + path + ", mode=" + mode);
}
return 0;
} else {
log.info("mkdir pathname=" + path + ", mode=" + mode);
emulator.getMemory().setErrno(UnixEmulator.EACCES);
return -1;
}
}
private int rmdir(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer pathname = context.getPointerArg(0);
String path = pathname.getString(0);
emulator.getFileSystem().rmdir(path);
if (log.isDebugEnabled()) {
log.debug("rmdir pathname=" + path);
}
return 0;
}
private int sendto(Emulator> emulator) {
Backend backend = emulator.getBackend();
int sockfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer buf = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int len = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
int flags = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
Pointer dest_addr = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R4);
int addrlen = backend.reg_read(ArmConst.UC_ARM_REG_R5).intValue();
return sendto(emulator, sockfd, buf, len, flags, dest_addr, addrlen);
}
private int connect(Emulator> emulator) {
Backend backend = emulator.getBackend();
int sockfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer addr = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int addrlen = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
return connect(emulator, sockfd, addr, addrlen);
}
private int sigaction(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int signum = context.getIntArg(0);
Pointer act = context.getPointerArg(1);
Pointer oldact = context.getPointerArg(2);
return sigaction(emulator, signum, act, oldact);
}
private int fcntl(Emulator> emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int cmd = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int arg = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
return fcntl(emulator, fd, cmd, arg);
}
@Override
protected int fcntl(Emulator> emulator, int fd, int cmd, long arg) {
FileIO file = fdMap.get(fd);
if (file != null && cmd == MachO.F_GETPATH) {
Pointer pointer = UnidbgPointer.pointer(emulator, arg & 0xffffffffL);
assert pointer != null;
pointer.setString(0, file.getPath());
return 0;
}
return super.fcntl(emulator, fd, cmd, arg);
}
private int mmap(Emulator> emulator) {
Backend backend = emulator.getBackend();
UnidbgPointer addr = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
int length = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int prot = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
int flags = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R4).intValue();
int r5 = backend.reg_read(ArmConst.UC_ARM_REG_R5).intValue();
long r6 = backend.reg_read(ArmConst.UC_ARM_REG_R6).intValue();
long offset = r5 | (r6 << 32);
int tag = fd >>> 24;
if (tag != 0) {
fd = -1;
}
boolean warning = length >= 0x10000000;
long base = emulator.getMemory().mmap2(addr == null ? 0 : addr.peer, length, prot, flags, fd, (int) offset);
String msg = "mmap addr=" + addr + ", length=" + length + ", prot=0x" + Integer.toHexString(prot) + ", flags=0x" + Integer.toHexString(flags) + ", fd=" + fd + ", offset=" + offset + ", tag=" + tag;
if (log.isDebugEnabled() || warning) {
if (warning) {
log.warn(msg);
} else {
log.debug(msg);
}
} else {
Log log = LogFactory.getLog("com.github.unidbg.ios.malloc");
if (log.isDebugEnabled()) {
log.debug(msg + ", base=0x" + Long.toHexString(base));
}
}
return (int) base;
}
private int socket(Emulator> emulator) {
Backend backend = emulator.getBackend();
int domain = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int type = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue() & 0x7ffff;
int protocol = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
if (log.isDebugEnabled()) {
log.debug("socket domain=" + domain + ", type=" + type + ", protocol=" + protocol);
}
if (protocol == SocketIO.IPPROTO_ICMP) {
throw new UnsupportedOperationException();
}
int fd;
switch (domain) {
case SocketIO.AF_UNSPEC:
throw new UnsupportedOperationException();
case SocketIO.AF_LOCAL:
if (type == SocketIO.SOCK_DGRAM) {
fd = getMinFd();
fdMap.put(fd, new LocalDarwinUdpSocket(emulator));
return fd;
}
emulator.getMemory().setErrno(UnixEmulator.EACCES);
return -1;
case SocketIO.AF_INET:
case SocketIO.AF_INET6:
switch (type) {
case SocketIO.SOCK_STREAM:
fd = getMinFd();
fdMap.put(fd, new TcpSocket(emulator));
return fd;
case SocketIO.SOCK_DGRAM:
fd = getMinFd();
fdMap.put(fd, new UdpSocket(emulator));
return fd;
case SocketIO.SOCK_RAW:
throw new UnsupportedOperationException();
}
break;
}
throw new UnsupportedOperationException("socket domain=" + domain + ", type=" + type + ", protocol=" + protocol);
}
private int write(Emulator> emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer buffer = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int count = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
byte[] data = buffer.getByteArray(0, count);
if (log.isDebugEnabled()) {
log.debug("write fd=" + fd + ", buffer=" + buffer + ", count=" + count);
}
FileIO file = fdMap.get(fd);
if (file == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
return file.write(data);
}
private int mprotect(Emulator> emulator) {
Backend backend = emulator.getBackend();
long address = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue() & 0xffffffffL;
long length = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int prot = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
long alignedAddress = address / ARMEmulator.PAGE_ALIGN * ARMEmulator.PAGE_ALIGN; // >> 12 << 12;
long offset = address - alignedAddress;
long alignedLength = ARM.alignSize(length + offset, emulator.getPageAlign());
if (log.isDebugEnabled()) {
log.debug("mprotect address=0x" + Long.toHexString(address) + ", alignedAddress=0x" + Long.toHexString(alignedAddress) + ", offset=" + offset + ", length=" + length + ", alignedLength=" + alignedLength + ", prot=0x" + Integer.toHexString(prot));
}
return emulator.getMemory().mprotect(alignedAddress, (int) alignedLength, prot);
}
@Override
protected DarwinFileIO createByteArrayFileIO(String pathname, int oflags, byte[] data) {
return new ByteArrayFileIO(oflags, pathname, data);
}
@Override
protected DarwinFileIO createDriverFileIO(Emulator> emulator, int oflags, String pathname) {
return DriverFileIO.create(emulator, oflags, pathname);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy