com.github.unidbg.ios.ARM64SyscallHandler 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.Arm64Svc;
import com.github.unidbg.arm.Cpsr;
import com.github.unidbg.arm.backend.Backend;
import com.github.unidbg.arm.backend.BackendException;
import com.github.unidbg.arm.context.Arm64RegisterContext;
import com.github.unidbg.arm.context.EditableArm64RegisterContext;
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.DyldCacheHeader;
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.IOServiceAddNotificationRequest;
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.MachPortTypeReply;
import com.github.unidbg.ios.struct.kernel.MachPortTypeRequest;
import com.github.unidbg.ios.struct.kernel.MachPortsLookupReply64;
import com.github.unidbg.ios.struct.kernel.MachTimebaseInfo;
import com.github.unidbg.ios.struct.kernel.MachVmMapReply;
import com.github.unidbg.ios.struct.kernel.MachVmMapRequest;
import com.github.unidbg.ios.struct.kernel.MakeMemoryEntryReply;
import com.github.unidbg.ios.struct.kernel.MakeMemoryEntryRequest;
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.NotifyServerRegisterCheck64Request;
import com.github.unidbg.ios.struct.kernel.NotifyServerRegisterCheckReply;
import com.github.unidbg.ios.struct.kernel.NotifyServerRegisterMachPort64Request;
import com.github.unidbg.ios.struct.kernel.NotifyServerRegisterMachPortReply;
import com.github.unidbg.ios.struct.kernel.NotifyServerRegisterPlain64Request;
import com.github.unidbg.ios.struct.kernel.NotifyServerRegisterPlainReply;
import com.github.unidbg.ios.struct.kernel.ProcBsdShortInfo;
import com.github.unidbg.ios.struct.kernel.Pthread;
import com.github.unidbg.ios.struct.kernel.Pthread64;
import com.github.unidbg.ios.struct.kernel.PurgableControlReply;
import com.github.unidbg.ios.struct.kernel.PurgableControlRequest;
import com.github.unidbg.ios.struct.kernel.RLimit;
import com.github.unidbg.ios.struct.kernel.RUsage64;
import com.github.unidbg.ios.struct.kernel.SemaphoreCreateReply;
import com.github.unidbg.ios.struct.kernel.SemaphoreCreateRequest;
import com.github.unidbg.ios.struct.kernel.Stat64;
import com.github.unidbg.ios.struct.kernel.StatFS;
import com.github.unidbg.ios.struct.kernel.TaskBasicInfoReply64V2;
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.TaskThreadsReply64;
import com.github.unidbg.ios.struct.kernel.TaskVmInfoReply64;
import com.github.unidbg.ios.struct.kernel.ThreadBasicInfoReply;
import com.github.unidbg.ios.struct.kernel.ThreadInfoRequest;
import com.github.unidbg.ios.struct.kernel.ThreadStateReply64;
import com.github.unidbg.ios.struct.kernel.ThreadStateRequest;
import com.github.unidbg.ios.struct.kernel.VmCopy64Request;
import com.github.unidbg.ios.struct.kernel.VmCopyReply;
import com.github.unidbg.ios.struct.kernel.VmReadOverwriteReply;
import com.github.unidbg.ios.struct.kernel.VmReadOverwriteRequest;
import com.github.unidbg.ios.struct.kernel.VmRegion64Reply;
import com.github.unidbg.ios.struct.kernel.VmRegion64Request;
import com.github.unidbg.ios.struct.kernel.VmRegionRecurse64Reply;
import com.github.unidbg.ios.struct.kernel.VmRegionRecurse64Request;
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.KInfoProc64;
import com.github.unidbg.ios.struct.sysctl.SockAddrDL;
import com.github.unidbg.ios.struct.sysctl.TaskDyldInfo;
import com.github.unidbg.ios.struct.sysctl.TaskVmInfo64;
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.ThreadContextSwitchException;
import com.github.unidbg.unix.UnixEmulator;
import com.github.unidbg.unix.struct.TimeSpec;
import com.github.unidbg.unix.struct.TimeVal64;
import com.github.unidbg.utils.Inspector;
import com.sun.jna.Pointer;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import unicorn.Arm64Const;
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 java.util.concurrent.TimeUnit;
import static com.github.unidbg.file.ios.DarwinFileIO.XATTR_CREATE;
import static com.github.unidbg.file.ios.DarwinFileIO.XATTR_REPLACE;
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;
public class ARM64SyscallHandler extends DarwinSyscallHandler {
private static final Logger log = LoggerFactory.getLogger(ARM64SyscallHandler.class);
private final SvcMemory svcMemory;
protected ARM64SyscallHandler(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, Arm64Const.UC_ARM64_REG_PC);
if (intno == ARMEmulator.EXCP_BKPT) { // brk
createBreaker(emulator).brk(pc, pc == null ? swi : (pc.getInt(0) >> 5) & 0xffff);
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(Arm64Const.UC_ARM64_REG_X16).intValue();
String syscall = null;
Throwable exception = null;
try {
if (swi == 0 && NR == Svc.POST_CALLBACK_SYSCALL_NUMBER && backend.reg_read(Arm64Const.UC_ARM64_REG_X8).intValue() == 0) { // postCallback
int number = backend.reg_read(Arm64Const.UC_ARM64_REG_X12).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 && NR == Svc.PRE_CALLBACK_SYSCALL_NUMBER && backend.reg_read(Arm64Const.UC_ARM64_REG_X8).intValue() == 0) { // preCallback
int number = backend.reg_read(Arm64Const.UC_ARM64_REG_X12).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 == Arm64Svc.SVC_MAX) {
throw new PopContextException();
}
if (swi == Arm64Svc.SVC_MAX - 1) {
throw new ThreadContextSwitchException();
}
Svc svc = svcMemory.getSvc(swi);
if (svc != null) {
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, svc.handle(emulator));
return;
}
backend.emu_stop();
throw new BackendException("svc number: " + swi + ", NR=" + NR + ", intno=" + intno);
}
if (log.isTraceEnabled()) {
log.debug("handle syscall NR={}", NR);
ARM.showRegs64(emulator, null);
}
Cpsr.getArm64(backend).setCarry(false);
boolean isIndirect = NR == 0;
if (isIndirect) {
int indirectNR = backend.reg_read(Arm64Const.UC_ARM64_REG_X0).intValue();
if (!handleIndirect(emulator, indirectNR)) {
log.warn("handleInterrupt intno={}, indirectNR={}, svcNumber=0x{}, PC={}", intno, indirectNR, Integer.toHexString(swi), pc);
if (log.isDebugEnabled() || LoggerFactory.getLogger(AbstractEmulator.class).isDebugEnabled()) {
createBreaker(emulator).debug();
}
}
return;
}
if (handleSyscall(emulator, NR)) {
return;
}
switch (NR) {
case -3:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, mach_absolute_time());
return;
case -10:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _kernelrpc_mach_vm_allocate_trap(emulator));
return;
case -12:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _kernelrpc_mach_vm_deallocate_trap(emulator));
return;
case -14:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _kernelrpc_mach_vm_protect_trap(emulator));
return;
case -15:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _kernelrpc_mach_vm_map_trap(emulator));
return;
case -16:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _kernelrpc_mach_port_allocate_trap(emulator));
return;
case -18:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _kernelrpc_mach_port_deallocate_trap(emulator));
return;
case -19:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _kernelrpc_mach_port_mod_refs_trap(emulator));
return;
case -21:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _kernelrpc_mach_port_insert_right_trap(emulator));
return;
case -22: // _mach_port_insert_member
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _mach_port_insert_member(emulator));
return;
case -24:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _kernelrpc_mach_port_construct_trap(emulator));
return;
case -26: // mach_port_t mach_reply_port(...)
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, mach_reply_port());
return;
case -27:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, thread_self_trap());
return;
case -28: // mach_port_name_t task_self_trap(void)
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, task_self_trap());
return;
case -29:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, host_self_trap());
return;
case -31:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, mach_msg_trap(emulator));
return;
case -33: // _semaphore_signal_trap
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _os_semaphore_signal(emulator));
return;
case -36: // _semaphore_wait_trap
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _semaphore_wait_trap(emulator));
return;
case -38: // semaphore_timedwait_trap
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, semaphore_timedwait_trap(emulator));
return;
case -41: // _xpc_mach_port_guard
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _kernelrpc_mach_port_guard_trap(emulator));
return;
case -47:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, kern_invalid());
return;
case -59: // swtch_pri
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, swtch_pri(emulator));
return;
case -61:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, thread_switch(emulator));
return;
case -89:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _mach_timebase_info(emulator));
return;
case -91: // mk_timer_create
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _mk_timer_create());
return;
case -93: // mk_timer_arm
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _mk_timer_arm(emulator));
return;
case -94: // mk_timer_cancel
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _mk_timer_cancel(emulator));
return;
case 1:
exit(emulator);
return;
case 2:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, fork(emulator));
return;
case 4:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, write(emulator, 0));
return;
case 6:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, closeWithOffset(emulator, 0));
return;
case 10:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, unlink(emulator));
return;
case 15:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, chmod(emulator));
return;
case 16:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, chown(emulator));
return;
case 20:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getpid(emulator));
return;
case 24: // getuid
case 25: // geteuid
case 43: // getegid
case 47: // getgid
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, 0);
return;
case 33:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, access(emulator));
return;
case 34:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, chflags(emulator));
return;
case 35:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, fchflags(emulator));
return;
case 37:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, kill(emulator));
return;
case 39:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getppid(emulator));
return;
case 42:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, pipe(emulator));
return;
case 46:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, sigaction(emulator));
return;
case 48:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, sigprocmask(emulator));
return;
case 52:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, sigpending(emulator));
return;
case 53:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, sigaltstack(emulator));
return;
case 54:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, ioctl(emulator));
return;
case 58:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, readlink(emulator));
return;
case 65:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, msync(emulator));
return;
case 73:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, munmap(emulator));
return;
case 74:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, mprotect(emulator));
return;
case 75:
syscall = "posix_madvise";
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, 0);
return;
case 89:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getdtablesize());
return;
case 90:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, dup2(emulator));
return;
case 92:
case 406: // fcntl_NOCANCEL
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, fcntl(emulator));
return;
case 93:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, newselect(emulator));
return;
case 95:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, fsync(emulator));
return;
case 97:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, socket(emulator, 0));
return;
case 98:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, connect(emulator, 0));
return;
case 116:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, gettimeofday(emulator));
return;
case 117:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getrusage(emulator));
return;
case 121:
case 412: // __writev_nocancel
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, writev(emulator));
return;
case 123:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, fchown(emulator));
return;
case 124:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, fchmod(emulator));
return;
case 128:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, rename(emulator));
return;
case 131:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, flock(emulator));
return;
case 133:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, sendto(emulator));
return;
case 136:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, mkdir(emulator));
return;
case 137:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, rmdir(emulator));
return;
case 138:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, utimes(emulator, 0));
return;
case 139:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, futimes(emulator));
return;
case 159:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, unmount(emulator));
return;
case 169:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, csops(emulator));
return;
case 194:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getrlimit(emulator));
return;
case 195:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, setrlimit(emulator));
return;
case 197:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, mmap(emulator));
return;
case 199:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, lseek(emulator));
return;
case 201:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, ftruncate(emulator));
return;
case 202:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, sysctl(emulator, 0));
return;
case 216:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, open_dprotected_np(emulator));
return;
case 220:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getattrlist(emulator));
return;
case 221:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, setattrlist(emulator));
return;
case 234:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getxattr(emulator));
return;
case 236:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, setxattr(emulator));
return;
case 237:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, fsetxattr(emulator));
return;
case 238:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, removexattr(emulator));
return;
case 240:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, listxattr(emulator));
return;
case 241:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, flistxattr(emulator));
return;
case 266:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, shm_open(emulator));
return;
case 282:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, chmodx_np(emulator));
return;
case 283:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, fchmodx_np(emulator));
return;
case 286:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, pthread_getugid_np(emulator));
return;
case 294:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, shared_region_check_np(emulator));
return;
case 301:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, psynch_mutexwait(emulator));
return;
case 302:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, psynch_mutexdrop(emulator));
return;
case 303:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, psynch_cvbroad(emulator));
return;
case 305:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, psynch_cvwait(emulator));
return;
case 307:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, psynch_rw_wrlock(emulator));
return;
case 308:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, psynch_rw_unlock(emulator));
return;
case 327:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, issetugid());
return;
case 328:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, pthread_kill(emulator));
return;
case 329:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, pthread_sigmask(emulator));
return;
case 330:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, sigwait(emulator));
return;
case 331:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, disable_threadsignal(emulator));
return;
case 334:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, semwait_signal(emulator));
return;
case 336:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, proc_info(emulator, 0));
return;
case 338:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, stat64(emulator, 0));
return;
case 339:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, fstat(emulator));
return;
case 340:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, lstat(emulator, 0));
return;
case 341:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, statx_np(emulator));
return;
case 342:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, lstatx_np(emulator));
return;
case 343:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, fstatx_np(emulator));
return;
case 344:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getdirentries64(emulator, 0));
return;
case 345:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, statfs64(emulator));
return;
case 346:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, fstatfs64(emulator));
return;
case 347:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getfsstat64(emulator, 0));
return;
case 357:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getaudit_addr(emulator));
return;
case 360:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, bsdthread_create(emulator));
return;
case 361:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, bsdthread_terminate(emulator));
return;
case 366:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, bsdthread_register(emulator));
return;
case 367:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _workq_open(emulator));
return;
case 368:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, _workq_kernreturn(emulator));
return;
case 369:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, kevent64(emulator));
return;
case 372:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, thread_selfid(emulator));
return;
case 381:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, sandbox_ms(emulator));
return;
case 3:
case 396:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, read_NOCANCEL(emulator, 0));
return;
case 397:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, write_NOCANCEL(emulator));
return;
case 5:
case 398:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, open_NOCANCEL(emulator, 0));
return;
case 399:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, close_NOCANCEL(emulator));
return;
case 423:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, semwait_signal(emulator));
return;
case 428:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, audit_session_self());
return;
case 443:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, guarded_kqueue_np(emulator));
return;
case 0x80000000:
NR = backend.reg_read(Arm64Const.UC_ARM64_REG_X3).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={}, NR={}, svcNumber=0x{}, PC={}, syscall={}", intno, NR, Integer.toHexString(swi), pc, syscall, exception);
if (log.isDebugEnabled() || LoggerFactory.getLogger(AbstractEmulator.class).isDebugEnabled()) {
createBreaker(emulator).debug();
}
if (exception instanceof RuntimeException) {
throw (RuntimeException) exception;
}
}
private long newselect(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int nfds = context.getIntArg(0);
Pointer readfds = context.getPointerArg(1);
Pointer writefds = context.getPointerArg(2);
Pointer exceptfds = context.getPointerArg(3);
Pointer timeout = context.getPointerArg(4);
int size = (nfds - 1) / 8 + 1;
if (log.isDebugEnabled()) {
log.debug("newselect nfds={}, readfds={}, writefds={}, exceptfds={}, timeout={}", nfds, readfds, writefds, exceptfds, timeout);
if (readfds != null) {
byte[] data = readfds.getByteArray(0, size);
Inspector.inspect(data, "readfds");
}
if (writefds != null) {
byte[] data = writefds.getByteArray(0, size);
Inspector.inspect(data, "writefds");
}
}
if (exceptfds != null) {
emulator.getMemory().setErrno(UnixEmulator.ENOMEM);
return -1;
}
if (writefds != null) {
int count = select(nfds, writefds, readfds, false);
if (count > 0) {
return count;
}
}
if (readfds != null) {
int count = select(nfds, readfds, writefds, true);
if (count == 0) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
return count;
}
throw new AbstractMethodError("newselect nfds=" + nfds + ", readfds=null, writefds=" + writefds + ", exceptfds=null, timeout=" + timeout);
}
private long fstatx_np(Emulator emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
Pointer sb = context.getPointerArg(1);
Pointer fsacl = context.getPointerArg(2);
Pointer fsacl_size = context.getPointerArg(3);
DarwinFileIO io = fdMap.get(fd);
if (io != null) {
fsacl_size.setLong(0, 0);
io.fstat(emulator, new Stat64(sb));
log.debug("fstatx_np fd={}, sb={}, fsacl={}, fsacl_size={}, io={}", fd, sb, fsacl, fsacl_size, io);
return 0;
}
int errno = UnixEmulator.ENOENT;
if (verbose) {
System.out.printf("File fstatx_np '%s' errno is %d from %s%n", fd, errno, emulator.getContext().getLRPointer());
}
Cpsr.getArm64(emulator.getBackend()).setCarry(true);
return errno;
}
private long lstatx_np(Emulator emulator) {
RegisterContext context = emulator.getContext();
Pointer obj = context.getPointerArg(0);
Pointer sb = context.getPointerArg(1);
Pointer fsacl = context.getPointerArg(2);
Pointer fsacl_size = context.getPointerArg(3);
String path = obj.getString(0);
FileResult result = resolve(emulator, path, IOConstants.O_RDONLY);
if (result != null && result.isSuccess()) {
fsacl_size.setLong(0, 0);
result.io.fstat(emulator, new Stat64(sb));
log.debug("lstatx_np path={}, sb={}, fsacl={}, fsacl_size={}, result={}", path, sb, fsacl, fsacl_size, result.io);
return 0;
}
int errno = result != null ? result.errno : UnixEmulator.ENOENT;
if (verbose) {
System.out.printf("File lstatx_np '%s' errno is %d from %s%n", path, errno, emulator.getContext().getLRPointer());
}
Cpsr.getArm64(emulator.getBackend()).setCarry(true);
return errno;
}
private long statx_np(Emulator emulator) {
RegisterContext context = emulator.getContext();
Pointer obj = context.getPointerArg(0);
Pointer sb = context.getPointerArg(1);
Pointer fsacl = context.getPointerArg(2);
Pointer fsacl_size = context.getPointerArg(3);
String path = obj.getString(0);
FileResult result = resolve(emulator, path, IOConstants.O_RDONLY);
if (result != null && result.isSuccess()) {
fsacl_size.setLong(0, 0);
result.io.fstat(emulator, new Stat64(sb));
log.debug("statx_np path={}, sb={}, fsacl={}, fsacl_size={}, result={}", path, sb, fsacl, fsacl_size, result.io);
return 0;
}
int errno = result != null ? result.errno : UnixEmulator.ENOENT;
if (verbose) {
System.out.printf("File statx '%s' errno is %d from %s%n", path, errno, emulator.getContext().getLRPointer());
}
Cpsr.getArm64(emulator.getBackend()).setCarry(true);
return errno;
}
private long kern_invalid() {
return 0x4; // KERN_INVALID_ARGUMENT
}
private long getrusage(Emulator emulator) {
RegisterContext context = emulator.getContext();
int who = context.getIntArg(0);
Pointer r_usage = context.getPointerArg(1);
RUsage64 usage64 = new RUsage64(r_usage);
usage64.unpack();
if (log.isDebugEnabled()) {
log.debug("getrusage who={}, r_usage={}, usage64={}", who, r_usage, usage64);
}
usage64.fillDefault();
usage64.pack();
return 0;
}
private int unmount(Emulator emulator) {
RegisterContext context = emulator.getContext();
Pointer target = context.getPointerArg(0);
int flags = context.getIntArg(1);
if (log.isDebugEnabled()) {
log.debug("unmount target={}, flags=0x{}", target.getString(0), Integer.toHexString(flags));
}
return 0;
}
private UnidbgPointer shared_region;
private int shared_region_check_np(Emulator emulator) {
RegisterContext context = emulator.getContext();
Pointer start_address = context.getPointerArg(0);
if (shared_region == null) {
shared_region = emulator.getMemory().mmap(emulator.getPageAlign(), UnicornConst.UC_PROT_READ);
DyldCacheHeader dyldCacheHeader = new DyldCacheHeader(shared_region);
dyldCacheHeader.pack();
}
if (log.isDebugEnabled()) {
log.debug("shared_region_check_np start_address={}, LR={}", start_address, context.getLRPointer());
}
start_address.setPointer(0, shared_region);
return 0;
}
private int getdtablesize() {
return 0x1000;
}
// see https://fergofrog.com/code/cbowser/xnu/BUILD/obj/EXPORT_HDRS/osfmk/kern/cs_blobs.h.html#_M/CS_VALID
private static final int CS_OPS_STATUS = 0; /* return status */
private static final int CS_GET_TASK_ALLOW = 0x00000004; /* has get-task-allow entitlement */
private static final int CS_INSTALLER = 0x00000008; /* has installer entitlement */
private static final int CS_HARD = 0x0000100; /* don't load invalid pages */
private static final int CS_RESTRICT = 0x0000800; /* tell dyld to treat restricted */
private static final int CS_ENFORCEMENT = 0x0001000; /* require enforcement */
private static final int CS_REQUIRE_LV = 0x0002000; /* require library validation */
private static final int CS_ENTITLEMENTS_VALIDATED = 0x0004000; /* code signature permits restricted entitlements */
private static final int CS_DYLD_PLATFORM = 0x2000000; /* dyld used to load this is a platform binary */
private static final int CS_PLATFORM_BINARY = 0x4000000; /* this is a platform binary */
private static final int CS_DEBUGGED = 0x10000000; /* process is currently or has previously been debugged and allowed to run with invalid pages */
private static final int CS_SIGNED = 0x20000000; /* process has a signature (may have gone invalid) */
private static final int CS_OPS_CDHASH = 5; /* get code directory hash */
private long csops(Emulator emulator) {
RegisterContext context = emulator.getContext();
int pid = context.getIntArg(0);
int op = context.getIntArg(1);
Pointer addr = context.getPointerArg(2);
int length = context.getIntArg(3);
if (log.isDebugEnabled()) {
log.debug("csops pid={}, op={}, addr={}, length={}", pid, op, addr, length);
}
if (op == CS_OPS_STATUS) {
addr.setInt(0, CS_HARD | CS_RESTRICT | CS_ENFORCEMENT | CS_REQUIRE_LV | CS_ENTITLEMENTS_VALIDATED | CS_DYLD_PLATFORM | CS_PLATFORM_BINARY | CS_SIGNED);
return 0;
} else if (op == CS_OPS_CDHASH) {
byte[] cdhash = new byte[length];
for (int i = 0; i < length; i++) {
cdhash[i] = (byte) (i + 0x10);
}
addr.write(0, cdhash, 0, length);
return 0;
} else {
log.info("csops pid={}, op={}, addr={}, length={}", pid, op, addr, length);
Logger log = LoggerFactory.getLogger(AbstractEmulator.class);
if (log.isDebugEnabled()) {
emulator.attach().debug();
}
return -1;
}
}
private long msync(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer addr = context.getPointerArg(0);
int len = context.getIntArg(1);
int flags = context.getIntArg(2);
if (log.isDebugEnabled()) {
log.debug("msync addr={}, len={}, flags=0x{}", addr, len, Integer.toHexString(flags));
}
return 0;
}
private long fchown(Emulator emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
int uid = context.getIntArg(1);
int gid = context.getIntArg(2);
DarwinFileIO io = fdMap.get(fd);
if (io != null) {
int ret = io.chown(uid, gid);
if (ret == -1) {
log.info("fchown fd={}, uid={}, gid={}", fd, uid, gid);
} else {
if (log.isDebugEnabled()) {
log.debug("fchown fd={}, uid={}, gid={}", fd, uid, gid);
}
}
return ret;
} else {
log.info("fchown fd={}, uid={}, gid={}", fd, uid, gid);
Cpsr.getArm64(emulator.getBackend()).setCarry(true);
return UnixEmulator.ENOENT;
}
}
private long 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);
FileResult result = resolve(emulator, pathname, IOConstants.O_RDONLY);
if (result != null && result.isSuccess()) {
int ret = result.io.chown(uid, gid);
if (ret == -1) {
log.info("chown path={}, uid={}, gid={}", pathname, uid, gid);
} else {
log.debug("chown path={}, uid={}, gid={}", pathname, uid, gid);
}
return ret;
} else {
log.info("chown path={}, uid={}, gid={}, result={}", pathname, uid, gid, result);
Cpsr.getArm64(emulator.getBackend()).setCarry(true);
return UnixEmulator.ENOENT;
}
}
private boolean handleMachineDependentSyscall(Emulator> emulator, int NR) {
Backend backend = emulator.getBackend();
switch (NR) {
case 0:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, sys_icache_invalidate(emulator));
return true;
case 1:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, sys_dcache_flush(emulator));
return true;
case 2:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, pthread_set_self(emulator));
return true;
}
return false;
}
private long 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={}, size={}", address, size);
}
return 0;
}
private long 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={}, size={}", address, size);
}
return 0;
}
private long _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={}, name={}, pset={}", task, name, pset);
}
if (verbose) {
System.out.printf("mach_port_insert_member %d with pset=0x%x from %s%n", name, pset, emulator.getContext().getLRPointer());
}
return 0;
}
private long _mk_timer_create() {
if (log.isDebugEnabled()) {
log.debug("_mk_timer_create");
}
return STATIC_PORT;
}
private long _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={}, time={}", port, time);
}
return 0;
}
private long _mk_timer_cancel(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int name = context.getIntArg(0);
Pointer result_time = context.getPointerArg(1);
if (log.isDebugEnabled()) {
log.debug("_mk_timer_cancel name={}, result_time={}", name, result_time);
}
return 0;
}
private long 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={}, mode={}", path, mode);
}
return 0;
} else {
log.info("mkdir pathname={}, mode={}", path, mode);
emulator.getMemory().setErrno(UnixEmulator.EACCES);
return -1;
}
}
private int rmdir(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer path = context.getPointerArg(0);
String pathname = path.getString(0);
emulator.getFileSystem().rmdir(pathname);
if (log.isDebugEnabled()) {
log.debug("rmdir pathname={}", path);
}
return 0;
}
/**
* set file access and modification times
* int utimes(const char *path, const struct timeval times[2]);
*/
private long utimes(Emulator> emulator, int offset) {
RegisterContext context = emulator.getContext();
Pointer path = context.getPointerArg(offset);
Pointer times = context.getPointerArg(offset + 1);
String pathname = path.getString(0);
if (log.isDebugEnabled()) {
log.debug("utimes pathname={}, times={}", pathname, times);
}
return 0;
}
private long futimes(Emulator emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
Pointer times = context.getPointerArg(1);
if (log.isDebugEnabled()) {
log.debug("futimes fd={}, times={}", fd, times);
}
return 0;
}
protected boolean handleIndirect(Emulator emulator, int indirectNR) {
Backend backend = emulator.getBackend();
switch (indirectNR) {
case 3:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, read_NOCANCEL(emulator, 1));
return true;
case 4:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, write(emulator, 1));
return true;
case 5:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, open_NOCANCEL(emulator, 1));
return true;
case 6:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, closeWithOffset(emulator, 1));
return true;
case 20:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getpid(emulator));
return true;
case 39:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getppid(emulator));
return true;
case 97:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, socket(emulator, 1));
return true;
case 98:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, connect(emulator, 1));
return true;
case 138:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, utimes(emulator, 1));
return true;
case 190:
case 340:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, lstat(emulator, 1));
return true;
case 202:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, sysctl(emulator, 1));
return true;
case 336:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, proc_info(emulator, 1));
return true;
case 338:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, stat64(emulator, 1));
return true;
case 344:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getdirentries64(emulator, 1));
return true;
case 347:
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, getfsstat64(emulator, 1));
return true;
}
return false;
}
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={}, name={}, guard={}, strict={}", task, name, guard, strict);
return 0;
}
private long semaphore_timedwait_trap(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int port = context.getIntArg(0);
log.info("semaphore_timedwait_trap port={}", port);
Logger log = ARM64SyscallHandler.log;
if (!log.isDebugEnabled()) {
log = LoggerFactory.getLogger(AbstractEmulator.class);
}
if (log.isDebugEnabled()) {
createBreaker(emulator).debug();
}
return 0;
}
private long _os_semaphore_signal(Emulator> emulator) {
int semaphore = emulator.getContext().getIntArg(0);
if (log.isDebugEnabled()) {
log.debug("_os_semaphore_signal semaphore={}", semaphore);
}
if (semaphore != 0) {
semaphoreMap.put(semaphore, Boolean.TRUE);
}
Logger log = ARM64SyscallHandler.log;
if (!log.isDebugEnabled()) {
log = LoggerFactory.getLogger(AbstractEmulator.class);
}
if (log.isDebugEnabled()) {
createBreaker(emulator).debug();
}
return 0;
}
private int _kernelrpc_mach_port_allocate_trap(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int task = context.getIntArg(0);
int right = context.getIntArg(1);
Pointer name = context.getPointerArg(2);
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_port_allocate_trap task={}, right={}, name={}", task, right, name);
}
name.setInt(0, STATIC_PORT);
if (verbose) {
System.out.printf("mach_port_allocate %d with right=0x%x from %s%n", STATIC_PORT, right, emulator.getContext().getLRPointer());
}
return 0;
}
private int pthread_set_self(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer self = context.getPointerArg(0);
Pthread pthread = new Pthread64(self.getPointer(0));
pthread.unpack();
UnidbgPointer tsd = pthread.getTSD();
emulator.getBackend().reg_write(Arm64Const.UC_ARM64_REG_TPIDRRO_EL0, tsd.peer);
MachOLoader loader = (MachOLoader) emulator.getMemory();
loader.setErrnoPointer(pthread.getErrno());
if (log.isDebugEnabled()) {
String threadName = pthread.getName();
log.debug("pthread_set_self={}, pthread={}, threadName={}, LR={}", self, pthread, threadName, emulator.getContext().getLRPointer());
}
return 0;
}
private int thread_switch(Emulator> emulator) {
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={}, option={}, option_time={}", thread_name, option, option_time);
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={}, LR={}", info, context.getLRPointer());
}
return 0;
}
private long psynch_rw_unlock(Emulator> emulator) {
// TODO: implement
log.info("psynch_rw_unlock LR={}", emulator.getContext().getLRPointer());
return 0;
}
private long psynch_rw_wrlock(Emulator> emulator) {
// TODO: implement
log.info("psynch_rw_wrlock LR={}", emulator.getContext().getLRPointer());
return 0;
}
/**
* psynch_mutexwait: This system call is used for contended psynch mutexes to block.
*/
private int psynch_mutexwait(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer mutex = context.getPointerArg(0);
int mgen = context.getIntArg(1);
int ugen = context.getIntArg(2);
long tid = context.getLongArg(3);
int flags = context.getIntArg(4);
if (log.isDebugEnabled()) {
log.debug("psynch_mutexwait mutex={}, mgen={}, ugen={}, tid={}, flags=0x{}, LR={}", mutex, mgen, ugen, tid, Integer.toHexString(flags), context.getLRPointer());
}
return 0;
}
private int psynch_mutexdrop(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer mutex = context.getPointerArg(0);
int mgen = context.getIntArg(1);
int ugen = context.getIntArg(2);
long tid = context.getLongArg(3);
int flags = context.getIntArg(4);
if (log.isDebugEnabled()) {
log.debug("psynch_mutexdrop mutex={}, mgen={}, ugen={}, tid={}, flags=0x{}, LR={}", mutex, mgen, ugen, tid, Integer.toHexString(flags), context.getLRPointer());
}
return 0;
}
private int psynch_cvwait(Emulator> emulator) {
Logger log = LoggerFactory.getLogger(AbstractEmulator.class);
if (threadDispatcherEnabled) {
if (log.isTraceEnabled()) {
emulator.attach().debug();
}
throw new ThreadContextSwitchException();
}
log.info("psynch_cvwait LR=" + emulator.getContext().getLRPointer());
if (log.isDebugEnabled()) {
emulator.attach().debug();
}
emulator.getMemory().setErrno(UnixEmulator.EINTR);
return -1;
}
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={}, oflags=0x{}, mode={}", name, Integer.toHexString(oflags), Integer.toHexString(mode));
}
emulator.getMemory().setErrno(UnixEmulator.EACCES);
return -1;
}
private int pthread_getugid_np(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer uid = context.getPointerArg(0);
Pointer gid = context.getPointerArg(1);
if (log.isDebugEnabled()) {
log.debug("pthread_getugid_np uid={}, gid={}", uid, gid);
}
uid.setInt(0, 0);
gid.setInt(0, 0);
return 0;
}
private int closeWithOffset(Emulator> emulator, int offset) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(offset);
if (log.isDebugEnabled()) {
log.debug("close fd={}, LR={}", fd, context.getLRPointer());
}
return close(emulator, fd);
}
private int lseek(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
long offset = context.getLongArg(1);
int whence = context.getIntArg(2);
FileIO file = fdMap.get(fd);
if (file == null) {
if (log.isDebugEnabled()) {
log.debug("lseek fd={}, offset={}, whence={}", fd, offset, whence);
}
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
int pos = file.lseek((int) offset, whence);
if (log.isDebugEnabled()) {
log.debug("lseek fd={}, offset={}, whence={}, pos={}", fd, offset, whence, pos);
}
return pos;
}
private long ftruncate(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
int length = context.getIntArg(1);
if (log.isDebugEnabled()) {
log.debug("ftruncate fd={}, length={}, LR={}", fd, length, context.getLRPointer());
}
FileIO file = fdMap.get(fd);
if (file == null) {
throw new UnsupportedOperationException("fd=" + fd + ", map=" + fdMap);
}
return file.ftruncate(length);
}
private int unlink(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer pathname = context.getPointerArg(0);
String path = FilenameUtils.normalize(pathname.getString(0), true);
emulator.getFileSystem().unlink(path);
return 0;
}
private int getdirentries64(Emulator> emulator, int index) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(index);
UnidbgPointer buf = context.getPointerArg(index + 1);
int bufSize = context.getIntArg(index + 2);
Pointer basep = context.getPointerArg(index + 3);
DarwinFileIO io = fdMap.get(fd);
if (log.isDebugEnabled()) {
log.debug("getdirentries64 fd={}, buf={}, bufSize={}, basep={}, io={}, LR={}", fd, buf, bufSize, basep, io, context.getLRPointer());
}
if (io == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
} else {
buf.setSize(bufSize);
return io.getdirentries64(buf, bufSize);
}
}
private long flock(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
int operation = context.getIntArg(1);
if (log.isDebugEnabled()) {
log.debug("flock fd={}, operation={}", fd, operation);
}
return 0;
}
private int fstatfs64(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
Pointer buf = context.getPointerArg(1);
if (log.isDebugEnabled()) {
log.debug("fstatfs64 fd={}, buf={}, LR={}", fd, buf, context.getLRPointer());
}
DarwinFileIO io = fdMap.get(fd);
if (io != null) {
if (verbose) {
System.out.printf("File fstatfs '%s' from %s%n", io, emulator.getContext().getLRPointer());
}
return io.fstatfs(new StatFS(buf));
}
emulator.getMemory().setErrno(UnixEmulator.EACCES);
return -1;
}
private long fchflags(Emulator emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
int flags = context.getIntArg(1);
DarwinFileIO io = fdMap.get(fd);
if (io != null) {
int ret = io.chflags(flags);
if (ret == -1) {
log.info("fchflags fd={}, flags=0x{}", io, Integer.toHexString(flags));
} else {
if (log.isDebugEnabled()) {
log.debug("fchflags fd={}, flags=0x{}", io, Integer.toHexString(flags));
}
}
return ret;
} else {
log.info("fchflags fd={}, flags=0x{}", io, Integer.toHexString(flags));
Cpsr.getArm64(emulator.getBackend()).setCarry(true);
return UnixEmulator.ENOENT;
}
}
private long chflags(Emulator emulator) {
RegisterContext context = emulator.getContext();
Pointer path = context.getPointerArg(0);
int flags = context.getIntArg(1);
String pathname = path.getString(0);
FileResult result = resolve(emulator, pathname, IOConstants.O_RDONLY);
if (result != null && result.isSuccess()) {
int ret = result.io.chflags(flags);
if (ret == -1) {
log.info("chflags pathname={}, flags=0x{}", pathname, Integer.toHexString(flags));
} else {
if (log.isDebugEnabled()) {
log.debug("chflags pathname={}, flags=0x{}", pathname, Integer.toHexString(flags));
}
}
return ret;
} else {
log.info("chflags pathname={}, flags=0x{}", pathname, Integer.toHexString(flags));
Cpsr.getArm64(emulator.getBackend()).setCarry(true);
return UnixEmulator.ENOENT;
}
}
private int getppid(Emulator> emulator) {
if (log.isDebugEnabled()) {
log.debug("getppid");
}
return emulator.getPid();
}
private long pipe(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer pipefd = context.getPointerArg(0);
if (log.isDebugEnabled()) {
int readfd = pipefd.getInt(0);
int writefd = pipefd.getInt(4);
log.debug("pipe readfd={}, writefd={}", readfd, writefd);
}
emulator.getMemory().setErrno(UnixEmulator.EFAULT);
return -1;
}
private int stat64(Emulator emulator, int offset) {
RegisterContext context = emulator.getContext();
Pointer pathname = context.getPointerArg(offset);
Pointer statbuf = context.getPointerArg(offset + 1);
String path = FilenameUtils.normalize(pathname.getString(0), true);
if (log.isDebugEnabled()) {
log.debug("stat64 pathname={}, statbuf={}", path, statbuf);
}
return stat64(emulator, path, statbuf);
}
protected int stat64(Emulator emulator, String pathname, Pointer statbuf) {
FileResult result = resolve(emulator, pathname, IOConstants.O_RDONLY);
if (result != null && result.isSuccess()) {
if (verbose) {
System.out.printf("File stat '%s' from %s%n", pathname, emulator.getContext().getLRPointer());
}
return result.io.fstat(emulator, new Stat64(statbuf));
}
int errno = result != null ? result.errno : UnixEmulator.ENOENT;
if (verbose) {
System.out.printf("File stat '%s' errno is %d from %s%n", pathname, errno, emulator.getContext().getLRPointer());
}
Cpsr.getArm64(emulator.getBackend()).setCarry(true);
return errno;
}
private int write_NOCANCEL(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
Pointer buffer = context.getPointerArg(1);
int count = context.getIntArg(2);
return write(emulator, fd, buffer, count);
}
/**
* 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, int offset) {
RegisterContext context = emulator.getContext();
Pointer pathname = context.getPointerArg(offset);
Pointer stat = context.getPointerArg(offset + 1);
String pathStr = pathname.getString(0);
String path = FilenameUtils.normalize(pathStr, true);
int ret = stat64(emulator, path, stat);
if (log.isDebugEnabled()) {
log.debug("lstat path={}, pathStr={}, stat={}, ret={}, LR={}", path, pathStr, stat, ret, context.getLRPointer());
}
return ret;
}
private int fstat(Emulator emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
Pointer stat = context.getPointerArg(1);
return fstat(emulator, fd, stat);
}
protected int fstat(Emulator emulator, int fd, Pointer stat) {
if (log.isDebugEnabled()) {
log.debug("fstat fd={}, stat={}", fd, stat);
}
DarwinFileIO file = fdMap.get(fd);
if (file == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
if (log.isDebugEnabled()) {
log.debug("fstat file={}, stat={}", file, stat);
}
if (verbose) {
System.out.printf("File fstat '%s' from %s%n", file, emulator.getContext().getLRPointer());
}
return file.fstat(emulator, new Stat64(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 long rlim_cur = 128;
private long rlim_max = 256;
private int getrlimit(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int resource = context.getIntArg(0);
Pointer rlp = context.getPointerArg(1);
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) {
RLimit rLimit = new RLimit(rlp);
rLimit.rlim_cur = rlim_cur;
rLimit.rlim_max = rlim_max;
rLimit.pack();
if (log.isDebugEnabled()) {
msg += (", rLimit=" + rLimit);
log.debug(msg);
}
return 0;
} else {
log.info(msg);
}
return 1;
}
private int setrlimit(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int resource = context.getIntArg(0);
Pointer rlp = context.getPointerArg(1);
boolean posix = (resource & RLIMIT_POSIX_FLAG) != 0;
int type = resource & (RLIMIT_POSIX_FLAG - 1);
String msg = "setrlimit resource=0x" + Integer.toHexString(resource) + ", rlp=" + rlp + ", posix=" + posix + ", type=" + type;
if (type == RLIMIT_NOFILE) {
RLimit rLimit = new RLimit(rlp);
rLimit.unpack();
rlim_cur = rLimit.rlim_cur;
rlim_max = rLimit.rlim_max;
if (log.isDebugEnabled()) {
msg += (", rLimit=" + rLimit);
log.debug(msg);
}
return 0;
} else {
log.info(msg);
}
return 1;
}
private long _kernelrpc_mach_port_mod_refs_trap(Emulator> emulator) {
Arm64RegisterContext context = emulator.getContext();
int task = context.getXInt(0);
int name = context.getXInt(1);
int right = context.getXInt(2);
int delta = context.getXInt(3);
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_port_mod_refs_trap task={}, name={}, right={}, delta={}", task, name, right, delta);
}
if (verbose) {
System.out.printf("mach_port_mod_refs %d with right=0x%x from %s%n", name, right, emulator.getContext().getLRPointer());
}
return 0;
}
private int _kernelrpc_mach_port_insert_right_trap(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int task = context.getIntArg(0);
int name = context.getIntArg(1);
int poly = context.getIntArg(2);
int polyPoly = context.getIntArg(3);
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_port_insert_right_trap task={}, name={}, poly={}, polyPoly={}", task, name, poly, polyPoly);
}
if (verbose) {
System.out.printf("mach_port_insert_right %d with poly=0x%x from %s%n", name, poly, emulator.getContext().getLRPointer());
}
return 0;
}
private int _kernelrpc_mach_port_construct_trap(Emulator> emulator) {
Arm64RegisterContext context = emulator.getContext();
int task = context.getXInt(0);
Pointer options = context.getXPointer(1);
long ctx = context.getXInt(2);
Pointer name = context.getXPointer(3);
if (log.isDebugEnabled()) {
MachPortOptions portOptions = new MachPortOptions(options);
portOptions.unpack();
log.debug("_kernelrpc_mach_port_construct_trap task={}, options={}, context=0x{}, name={}, portOptions={}", task, options, Long.toHexString(ctx), name, portOptions);
}
name.setInt(0, 0x88);
if (verbose) {
System.out.printf("mach_port_construct %d from %s%n", 0x88, emulator.getContext().getLRPointer());
}
return 0;
}
private long getaudit_addr(Emulator> emulator) {
Arm64RegisterContext context = emulator.getContext();
Pointer addr = context.getXPointer(0);
int size = context.getXInt(1);
if (log.isDebugEnabled()) {
log.debug("getaudit_addr={}, size={}", addr, size);
}
return 0;
}
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_PIDPATHINFO = 11;
private static final int PROC_PIDT_SHORTBSDINFO = 13;
private int proc_info(Emulator> emulator, int index) {
RegisterContext context = emulator.getContext();
int callNum = context.getIntArg(index);
int pid = context.getIntArg(index + 1);
int flavor = context.getIntArg(index + 2);
long arg = context.getLongArg(index + 3);
Pointer buffer = context.getPointerArg(index + 4);
int bufferSize = context.getIntArg(index + 5);
String executable = executableBundlePath;
if (executable == null) {
executable = emulator.getProcessName();
}
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("{}, newName={}", msg, 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("{}, info={}", msg, info);
}
return info.size();
} else if (PROC_INFO_CALL_PIDINFO == callNum && PROC_PIDPATHINFO == flavor && executable != null) {
byte[] data = executable.getBytes(StandardCharsets.UTF_8);
if (bufferSize < data.length + 1) {
throw new UnsupportedOperationException();
}
buffer.write(0, Arrays.copyOf(data, data.length + 1), 0, data.length + 1);
return 0;
} else {
log.info(msg);
Logger log = LoggerFactory.getLogger(AbstractEmulator.class);
if (log.isDebugEnabled()) {
emulator.attach().debug();
}
return -1;
}
}
protected int semwait_signal(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int cond_sem = context.getIntArg(0);
int mutex_sem = context.getIntArg(1);
int timeout = context.getIntArg(2);
int relative = context.getIntArg(3);
long tv_sec = context.getLongArg(4);
int tv_nsec = context.getIntArg(5);
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 int sandbox_ms(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer policyName = context.getPointerArg(0);
int call = context.getIntArg(1);
Pointer args = context.getPointerArg(2);
if (log.isDebugEnabled()) {
log.debug("sandbox_ms policyName={}, call={}, args={}", policyName.getString(0), call, args);
}
return 0;
}
private int issetugid() {
log.debug("issetugid");
return 0;
}
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={}, buf={}, path={}", pathPointer, buf, path);
}
if (result != null && result.isSuccess()) {
return result.io.fstatfs(new StatFS(buf));
}
log.info("statfs64 pathPointer={}, buf={}, path={}", pathPointer, buf, path);
throw new BackendException("statfs64 path=" + path + ", buf=" + buf);
}
private long bsdthread_create(Emulator> emulator) {
RegisterContext 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.getIntArg(4);
return bsdthread_create(emulator, start_routine, arg, stack, thread, flags);
}
private int bsdthread_register(Emulator> emulator) {
RegisterContext context = emulator.getContext();
UnidbgPointer thread_start = context.getPointerArg(0);
UnidbgPointer start_wqthread = context.getPointerArg(1);
int pthreadSize = context.getIntArg(2);
UnidbgPointer data = context.getPointerArg(3);
int dataSize = context.getIntArg(4);
long offset = context.getLongArg(5);
if (log.isDebugEnabled()) {
log.debug("bsdthread_register thread_start={}, start_wqthread={}, pthreadSize={}, data={}, dataSize={}, offset=0x{}", thread_start, start_wqthread, pthreadSize, data, dataSize, Long.toHexString(offset));
}
return bsdthread_register(thread_start, pthreadSize);
}
private int readlink(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer pathname = context.getPointerArg(0);
Pointer buf = context.getPointerArg(1);
int bufSize = context.getIntArg(2);
String path = pathname.getString(0);
if (log.isDebugEnabled()) {
log.debug("readlink path={}, buf={}, bufSize={}", path, buf, 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 munmap(Emulator> emulator) {
RegisterContext context = emulator.getContext();
long timeInMillis = System.currentTimeMillis();
long start = context.getLongArg(0);
int length = context.getIntArg(1);
emulator.getMemory().munmap(start, length);
if (log.isDebugEnabled()) {
log.debug("munmap start=0x{}, length={}, offset={}", Long.toHexString(start), length, System.currentTimeMillis() - timeInMillis);
}
return 0;
}
private int sysctl(Emulator> emulator, int offset) {
RegisterContext context = emulator.getContext();
Pointer name = context.getPointerArg(offset);
int namelen = context.getIntArg(offset + 1);
Pointer buffer = context.getPointerArg(offset + 2);
Pointer bufferSize = context.getPointerArg(offset + 3);
Pointer set0 = context.getPointerArg(offset + 4);
int set1 = context.getIntArg(offset + 5);
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={}, namelen={}, buffer={}, bufferSize={}, sub={}, set1={}", action, namelen, buffer, bufferSize, sub, set1);
}
switch (sub) {
case "unidbg.debug":
return verbose || LoggerFactory.getLogger("com.github.unidbg.ios.debug").isDebugEnabled() ? 1 : 0;
case "kern.ostype":
buffer.setInt(0, CTL_KERN);
buffer.setInt(4, KERN_OSTYPE);
bufferSize.setLong(0, 8);
return 0;
case "kern.osrelease":
buffer.setInt(0, CTL_KERN);
buffer.setInt(4, KERN_OSRELEASE);
bufferSize.setLong(0, 8);
return 0;
case "kern.version":
buffer.setInt(0, CTL_KERN);
buffer.setInt(4, KERN_VERSION);
bufferSize.setLong(0, 8);
return 0;
case "kern.osversion":
buffer.setInt(0, CTL_KERN);
buffer.setInt(4, KERN_OSVERSION);
bufferSize.setLong(0, 8);
return 0;
case "kern.boottime":
buffer.setInt(0, CTL_KERN);
buffer.setInt(4, KERN_BOOTTIME);
bufferSize.setLong(0, 8);
return 0;
case "hw.machine":
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_MACHINE);
bufferSize.setLong(0, 8);
return 0;
case "hw.model":
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_MODEL);
bufferSize.setLong(0, 8);
return 0;
case "hw.cputype":
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_CPU_TYPE);
bufferSize.setLong(0, 8);
return 0;
case "hw.cpusubtype":
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_CPU_SUBTYPE);
bufferSize.setLong(0, 8);
return 0;
case "hw.cpufamily":
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_CPU_FAMILY);
bufferSize.setLong(0, 8);
return 0;
case "hw.ncpu":
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_NCPU);
bufferSize.setLong(0, 8);
return 0;
case "hw.memsize":
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_MEMSIZE);
bufferSize.setLong(0, 8);
return 0;
case "hw.physicalcpu_max":
case "hw.logicalcpu_max":
buffer.setInt(0, CTL_HW);
buffer.setInt(4, HW_CPU_MAX);
bufferSize.setLong(0, 8);
return 0;
case "sysctl.proc_native":
return -1;
}
if (log.isDebugEnabled()) {
createBreaker(emulator).debug();
}
log.info("sysctl CTL_UNSPEC action={}, namelen={}, buffer={}, bufferSize={}, sub={}", action, namelen, buffer, bufferSize, sub);
return -1;
}
log.info("sysctl CTL_UNSPEC action={}, namelen={}, buffer={}, bufferSize={}, set0={}, set1={}", action, namelen, buffer, bufferSize, set0, 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_USRSTACK32:
case KERN_PROCARGS2:
log.info(msg);
return 1;
case KERN_OSTYPE:
log.debug(msg);
String osType = "Darwin";
if (bufferSize != null) {
bufferSize.setLong(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.setLong(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.setLong(0, version.length() + 1);
}
if (buffer != null) {
buffer.setString(0, version);
}
return 0;
case KERN_ARGMAX:
bufferSize.setLong(0, 4);
buffer.setInt(0, 128);
return 0;
case KERN_PROC:
int subType = name.getInt(8);
if (subType == KERN_PROC_PID) {
if (bufferSize != null) {
bufferSize.setLong(0, UnidbgStructure.calculateSize(KInfoProc64.class));
}
KInfoProc64 kInfoProc = null;
if (buffer != null) {
kInfoProc = new KInfoProc64(buffer);
kInfoProc.unpack();
kInfoProc.kp_proc.p_flag = 0; // P_TRACED
kInfoProc.kp_eproc.e_ucred.cr_uid = 0;
kInfoProc.pack();
}
int pid = name.getInt(0xc);
log.debug("{}, subType={}, pid={}, kInfoProc={}", msg, subType, pid, kInfoProc);
return 0;
}
log.info("{}, subType={}", msg, subType);
break;
case KERN_OSVERSION:
log.debug(msg);
String osVersion = "9A127";
if (bufferSize != null) {
bufferSize.setLong(0, osVersion.length() + 1);
}
if (buffer != null) {
buffer.setString(0, osVersion);
}
return 0;
case KERN_HOSTNAME:
log.debug(msg);
String hostName = "unidbg.local";
if (bufferSize != null) {
bufferSize.setLong(0, hostName.length() + 1);
}
if (buffer != null) {
buffer.setString(0, hostName);
}
return 0;
case KERN_USRSTACK64:
if (bufferSize != null) {
bufferSize.setLong(0, 8);
}
if (buffer != null) {
buffer.setLong(0, emulator.getMemory().getStackBase());
}
return 0;
case KERN_BOOTTIME:
if (bufferSize != null) {
bufferSize.setLong(0, UnidbgStructure.calculateSize(TimeVal64.class));
}
if (buffer != null) {
fillKernelBootTime(buffer);
}
return 0;
case KERN_MAXFILESPERPROC:
if (bufferSize != null) {
bufferSize.setLong(0, 4);
}
if (buffer != null) {
buffer.setInt(0, 256);
}
return 0;
default:
log.info(msg);
if (log.isDebugEnabled()) {
createBreaker(emulator).debug();
}
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_MACHINE:
log.debug(msg);
String machine = getHwMachine();
if (bufferSize != null) {
bufferSize.setLong(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.setLong(0, model.length() + 1);
}
if (buffer != null) {
buffer.setString(0, model);
}
return 0;
case HW_NCPU:
log.debug(msg);
if (bufferSize != null) {
bufferSize.setLong(0, 4);
}
if (buffer != null) {
buffer.setInt(0, getHwNcpu()); // 2 cpus
}
return 0;
case HW_PAGESIZE:
log.debug(msg);
if (bufferSize != null) {
bufferSize.setLong(0, 4);
}
if (buffer != null) {
buffer.setInt(0, emulator.getPageAlign());
}
return 0;
case HW_CPU_TYPE:
log.debug(msg);
if (bufferSize != null) {
bufferSize.setLong(0, 4);
}
if (buffer != null) {
buffer.setInt(0, CPU_TYPE_ARM);
}
return 0;
case HW_CPU_SUBTYPE:
log.debug(msg);
if (bufferSize != null) {
bufferSize.setLong(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.setLong(0, 4);
}
if (buffer != null) {
buffer.setInt(0, 933271106);
}
return 0;
case HW_MEMSIZE:
if (bufferSize != null) {
bufferSize.setLong(0, 8);
}
if (buffer != null) {
long memSize = 2L * 1024 * 1024 * 1024; // 2G
buffer.setLong(0, memSize);
}
return 0;
case HW_CPU_FREQ:
if (bufferSize != null) {
bufferSize.setLong(0, 4);
}
if (buffer != null) {
buffer.setInt(0, 1800000000);
}
return 0;
case HW_CPU_MAX:
case HW_AVAILCPU:
if (bufferSize != null) {
bufferSize.setLong(0, 4);
}
if (buffer != null) {
buffer.setInt(0, getHwNcpu());
}
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) {
log.debug(msg);
try {
List networkIFList = DarwinUtils.getNetworkIFs(isVerbose());
int sizeOfSDL = UnidbgStructure.calculateSize(SockAddrDL.class);
int entrySize = UnidbgStructure.calculateSize(IfMsgHeader.class) + sizeOfSDL;
if (bufferSize != null) {
bufferSize.setLong(0, (long) 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("{}, family={}, rt={}", msg, family, rt);
if (log.isDebugEnabled()) {
createBreaker(emulator).debug();
}
default:
log.info("sysctl top={}, namelen={}, buffer={}, bufferSize={}, set0={}, set1={}", name.getInt(0), namelen, buffer, bufferSize, set0, set1);
break;
}
return 1;
}
@Override
protected void fillKernelBootTime(Pointer buffer) {
long currentTimeMillis = bootTime;
long tv_sec = currentTimeMillis / 1000;
long tv_usec = (currentTimeMillis % 1000) * 1000 + (bootTime / 7 % 1000);
TimeVal64 timeVal = new TimeVal64(buffer);
timeVal.tv_sec = tv_sec;
timeVal.tv_usec = tv_usec;
timeVal.pack();
}
private long 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);
int mode = context.getIntArg(4);
String pathname = path.getString(0);
int fd = open(emulator, pathname, flags);
if (log.isDebugEnabled()) {
log.debug("open_dprotected_np path={}, flags=0x{}, class={}, dpflags=0x{}, mode=0x{}", pathname, Integer.toHexString(flags), _class, Integer.toHexString(dpflags), Integer.toHexString(mode));
}
return fd;
}
private long getattrlist(Emulator emulator) {
RegisterContext 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.getIntArg(4);
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("{}, ret={}", msg, ret);
if (log.isDebugEnabled() || LoggerFactory.getLogger(AbstractEmulator.class).isDebugEnabled()) {
createBreaker(emulator).debug();
}
} else {
if (log.isDebugEnabled()) {
log.debug("{}, ret={}", msg, ret);
}
}
return ret;
}
emulator.getMemory().setErrno(result != null ? result.errno : UnixEmulator.EEXIST);
return -1;
}
private long setattrlist(Emulator emulator) {
RegisterContext 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.getIntArg(4);
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("{}, ret={}", msg, ret);
} else {
if (log.isDebugEnabled()) {
log.debug("{}, ret={}, result={}", msg, ret, result);
}
}
return ret;
}
emulator.getMemory().setErrno(result != null ? result.errno : UnixEmulator.EACCES);
log.info(msg);
return -1;
}
private long getxattr(Emulator emulator) {
RegisterContext context = emulator.getContext();
Pointer path = context.getPointerArg(0);
Pointer name = context.getPointerArg(1);
UnidbgPointer value = context.getPointerArg(2);
int size = context.getIntArg(3);
int position = context.getIntArg(4);
int options = context.getIntArg(5);
String pathname = path.getString(0);
if (position != 0 || (options & XATTR_CREATE) != 0 || (options & XATTR_REPLACE) != 0) {
log.info("getxattr path={}, name={}, value={}, size={}, position={}, options=0x{}", pathname, name.getString(0), value, size, position, Integer.toHexString(options));
return -1;
}
if (value != null) {
value.setSize(size);
}
FileResult result = resolve(emulator, pathname, IOConstants.O_RDONLY);
if (result != null && result.isSuccess()) {
int ret = result.io.getxattr(emulator, name.getString(0), value, size);
if (ret == -1) {
log.info("getxattr path={}, name={}, value={}, size={}, position={}, options=0x{}", pathname, name.getString(0), value, size, position, Integer.toHexString(options));
} else {
if (log.isDebugEnabled()) {
log.debug("getxattr path={}, name={}, value={}, size={}, position={}, options=0x{}", pathname, name.getString(0), value, size, position, Integer.toHexString(options));
}
}
return ret;
} else {
log.info("getxattr path={}, name={}, value={}, size={}, position={}, options=0x{}", pathname, name.getString(0), value, size, position, Integer.toHexString(options));
emulator.getMemory().setErrno(UnixEmulator.ENOENT);
return -1;
}
}
private long removexattr(Emulator emulator) {
RegisterContext context = emulator.getContext();
Pointer path = context.getPointerArg(0);
Pointer name = context.getPointerArg(1);
int options = context.getIntArg(2);
String pathname = path.getString(0);
FileResult result = resolve(emulator, pathname, IOConstants.O_RDONLY);
if (result != null && result.isSuccess()) {
int ret = result.io.removexattr(name.getString(0));
if (ret == -1) {
log.info("removexattr path={}, name={}, options=0x{}", pathname, name.getString(0), Integer.toHexString(options));
} else {
if (log.isDebugEnabled()) {
log.debug("removexattr path={}, name={}, options=0x{}", pathname, name.getString(0), Integer.toHexString(options));
}
}
return ret;
} else {
log.info("removexattr path={}, name={}, options=0x{}, result={}", pathname, name.getString(0), Integer.toHexString(options), result);
emulator.getMemory().setErrno(UnixEmulator.ENOENT);
return -1;
}
}
private long setxattr(Emulator emulator) {
RegisterContext 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.getIntArg(4);
int options = context.getIntArg(5);
String pathname = path.getString(0);
if (position != 0 || (options & XATTR_CREATE) != 0 || (options & XATTR_REPLACE) != 0) {
log.info("setxattr path={}, name={}, value={}, size={}, position={}, options=0x{}", pathname, name.getString(0), value, size, position, Integer.toHexString(options));
return -1;
}
FileResult result = resolve(emulator, pathname, IOConstants.O_RDONLY);
if (result != null && result.isSuccess()) {
int ret = result.io.setxattr(name.getString(0), value.getByteArray(0, size));
if (ret == -1) {
log.info("setxattr path={}, name={}, value={}, size={}, position={}, options=0x{}", pathname, name.getString(0), value, size, position, Integer.toHexString(options));
} else {
if (log.isDebugEnabled()) {
log.debug("setxattr path={}, name={}, value={}, size={}, position={}, options=0x{}", pathname, name.getString(0), value, size, position, Integer.toHexString(options));
}
}
return ret;
} else {
log.info("setxattr path={}, name={}, value={}, size={}, position={}, options=0x{}", pathname, name.getString(0), value, size, position, Integer.toHexString(options));
Cpsr.getArm64(emulator.getBackend()).setCarry(true);
return UnixEmulator.ENOENT;
}
}
private long fsetxattr(Emulator emulator) {
RegisterContext 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.getIntArg(4);
int options = context.getIntArg(5);
DarwinFileIO io = fdMap.get(fd);
if (position != 0 || (options & XATTR_CREATE) != 0 || (options & XATTR_REPLACE) != 0) {
log.info("fsetxattr fd={}, name={}, value={}, size={}, position={}, options=0x{}", fd, name.getString(0), value, size, position, Integer.toHexString(options));
return -1;
}
if (io != null) {
int ret = io.setxattr(name.getString(0), value.getByteArray(0, size));
if (ret == -1) {
log.info("fsetxattr fd={}, name={}, value={}, size={}, position={}, options=0x{}", fd, name.getString(0), value, size, position, Integer.toHexString(options));
} else {
if (log.isDebugEnabled()) {
log.debug("fsetxattr fd={}, name={}, value={}, size={}, position={}, options=0x{}", fd, name.getString(0), value, size, position, Integer.toHexString(options));
}
}
return ret;
}
log.info("fsetxattr fd={}, name={}, value={}, size={}, position={}, options=0x{}", fd, name.getString(0), value, size, position, Integer.toHexString(options));
return 0;
}
private int _kernelrpc_mach_vm_deallocate_trap(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int target = context.getIntArg(0);
long address = context.getLongArg(1);
long size = context.getLongArg(2);
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_vm_deallocate_trap target={}, address=0x{}, size=0x{}", target, Long.toHexString(address), Long.toHexString(size));
} else {
Logger log = LoggerFactory.getLogger("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=" + context.getLRPointer());
}
}
if (size > 0) {
emulator.getMemory().munmap(address, (int) size);
}
return 0;
}
private int _kernelrpc_mach_vm_protect_trap(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int target = context.getIntArg(0);
long address = context.getLongArg(1);
long size = context.getLongArg(2);
int set_maximum = context.getIntArg(3);
int new_protection = context.getIntArg(4);
long alignedLength = ARM.alignSize(size, emulator.getPageAlign());
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_vm_protect_trap target={}, address=0x{}, size=0x{}, set_maximum={}, new_protection=0x{}", target, Long.toHexString(address), Long.toHexString(size), set_maximum, Integer.toHexString(new_protection));
}
if (address % emulator.getPageAlign() != 0) {
throw new UnsupportedOperationException("address=0x" + Long.toHexString(address) + ", size=0x" + Long.toHexString(size));
}
return emulator.getMemory().mprotect(address, (int) alignedLength, new_protection);
}
private int _kernelrpc_mach_vm_map_trap(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int target = context.getIntArg(0);
Pointer address = context.getPointerArg(1);
long size = context.getLongArg(2);
long mask = context.getLongArg(3);
int flags = context.getIntArg(4);
int cur_protection = context.getIntArg(5);
int tag = flags >> 24;
boolean anywhere = (flags & MachO.VM_FLAGS_ANYWHERE) != 0;
if (!anywhere) {
throw new BackendException("_kernelrpc_mach_vm_map_trap fixed");
}
MachOLoader loader = (MachOLoader) emulator.getMemory();
Pointer value = address.getPointer(0);
UnidbgPointer pointer;
if (mask != 0) {
pointer = UnidbgPointer.pointer(emulator, loader.allocate(size, mask));
} else {
pointer = loader.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 {
Logger log = LoggerFactory.getLogger("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) {
RegisterContext context = emulator.getContext();
int target = context.getIntArg(0);
Pointer address = context.getPointerArg(1);
long size = context.getLongArg(2);
int flags = context.getIntArg(3);
int tag = flags >> 24;
boolean anywhere = (flags & MachO.VM_FLAGS_ANYWHERE) != 0;
if (!anywhere) {
long start = address.getLong(0);
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={}, size={}, flags=0x{}", address.getPointer(0), size, 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={}, size={}, flags=0x{}, anywhere=false", pointer, size, 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 msg = "_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(msg);
} else {
Logger log = LoggerFactory.getLogger("com.github.unidbg.ios.malloc");
if (log.isDebugEnabled()) {
log.debug(msg);
}
}
return 0;
}
private int _kernelrpc_mach_port_deallocate_trap(Emulator> emulator) {
Backend backend = emulator.getBackend();
int task = backend.reg_read(Arm64Const.UC_ARM64_REG_X0).intValue();
int name = backend.reg_read(Arm64Const.UC_ARM64_REG_X1).intValue();
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_port_deallocate_trap task={}, name={}", task, name);
}
if (verbose) {
System.out.printf("mach_port_deallocate %d from %s%n", name, emulator.getContext().getLRPointer());
}
return 0;
}
private int _workq_open(Emulator> emulator) {
RegisterContext context = emulator.getContext();
if (log.isDebugEnabled()) {
log.debug("_workq_open LR={}", context.getLRPointer());
}
if (LoggerFactory.getLogger(AbstractEmulator.class).isTraceEnabled()) {
createBreaker(emulator).debug();
}
return 0;
}
private int _workq_kernreturn(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int options = context.getIntArg(0);
Pointer item = context.getPointerArg(1);
int arg2 = context.getIntArg(2);
int arg3 = context.getIntArg(3);
if (log.isDebugEnabled()) {
log.debug("_workq_kernreturn options=0x{}, item={}, arg2={}, arg3=0x{}, LR={}", Integer.toHexString(options), item, arg2, Integer.toHexString(arg3), context.getLRPointer());
}
if (LoggerFactory.getLogger(AbstractEmulator.class).isTraceEnabled()) {
createBreaker(emulator).debug();
}
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();
RegisterContext context = emulator.getContext();
UnidbgPointer msg = context.getPointerArg(0);
int option = context.getIntArg(1);
int send_size = context.getIntArg(2);
int rcv_size = context.getIntArg(3);
int rcv_name = context.getIntArg(4);
int timeout = context.getIntArg(5);
int notify = context.getIntArg(6);
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={}, option=0x{}, send_size={}, rcv_size={}, rcv_name={}, timeout={}, notify={}, LR={}, header={}", msg, Integer.toHexString(option), send_size, rcv_size, rcv_name, timeout, notify, context.getLRPointer(), header);
}
final UnidbgPointer request = (UnidbgPointer) 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);
}
if (verbose) {
System.out.printf("task_get_special_port %d from %s%n", BOOTSTRAP_PORT, emulator.getContext().getLRPointer());
}
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 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 4807: // vm_copy
{
VmCopy64Request args = new VmCopy64Request(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("vm_copy args={}, lr={}", args, UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_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={}, header={}", reply, 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={}, lr={}", args, UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_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={}, header={}", reply, header);
}
return MACH_MSG_SUCCESS;
}
case 4815: // vm_region_recurse_64
{
VmRegionRecurse64Request args = new VmRegionRecurse64Request(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("vm_region_recurse_64 args={}", args);
}
VmRegionRecurse64Reply reply = new VmRegionRecurse64Reply(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 (memoryMap == null) {
break;
}
reply.NDR = args.NDR;
reply.retCode = 0; // success
reply.addressLow = (int) memoryMap.base;
reply.addressHigh = (int) (memoryMap.base >> 32L);
reply.sizeLow = (int) memoryMap.size;
reply.sizeHigh = (int) (memoryMap.size >> 32L);
reply.infoCnt = 7;
reply.nestingDepth = args.nestingDepth;
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={}, memoryMap={}", reply, 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={}, lr={}", args, UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_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={}, header={}", reply, 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={}, lr={}", args, UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_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);
}
return MACH_MSG_SUCCESS;
}
case 3404: // mach_ports_lookup
{
MachPortsLookupReply64 reply = new MachPortsLookupReply64(request);
reply.unpack();
header.msgh_bits = (header.msgh_bits & 0xff) | MACH_MSGH_BITS_COMPLEX;
header.msgh_size = 56;
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.outPortLow = (int) request.toUIntPeer();
reply.outPortHigh = (int) (request.peer >> 32L);
reply.mask = 0x2110000;
reply.cnt = 0;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("mach_ports_lookup reply={}", reply);
}
if (verbose) {
System.out.printf("mach_ports_lookup from %s%n", emulator.getContext().getLRPointer());
}
return MACH_MSG_SUCCESS;
}
case 404: { // vproc_mig_look_up2
return vproc_mig_look_up2(request, header);
}
case 78945669: { // notify_server_register_plain
NotifyServerRegisterPlain64Request args = new NotifyServerRegisterPlain64Request(request);
args.unpack();
if (log.isDebugEnabled()) {
Pointer pointer = UnidbgPointer.pointer(emulator, args.nameLow | (long) args.nameHigh << 32L);
log.debug("notify_server_register_plain args={}, name={}", args, 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
NotifyServerRegisterCheck64Request args = new NotifyServerRegisterCheck64Request(request);
args.unpack();
if (log.isDebugEnabled()) {
Pointer pointer = UnidbgPointer.pointer(emulator, (args.nameLow & 0xffffffffL) | (long) args.nameHigh << 32L);
log.debug("notify_server_register_check args={}, name={}", args, 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
NotifyServerRegisterMachPort64Request args = new NotifyServerRegisterMachPort64Request(request);
args.unpack();
if (log.isDebugEnabled()) {
Pointer pointer = UnidbgPointer.pointer(emulator, args.nameLow | (long) args.nameHigh << 32L);
log.debug("notify_server_register_mach_port args={}, name={}", args, pointer == null ? null : new String(pointer.getByteArray(0, args.namelen), StandardCharsets.UTF_8));
}
NotifyServerRegisterMachPortReply reply = new NotifyServerRegisterMachPortReply(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.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={}, matching={}", args, 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 3201: { // _kernelrpc_mach_port_type
MachPortTypeRequest args = new MachPortTypeRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_port_type args={}", args);
}
MachPortTypeReply reply = new MachPortTypeReply(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.ptype = 0x70000;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("_kernelrpc_mach_port_set_attributes reply={}", reply);
}
return MACH_MSG_SUCCESS;
}
case 2868: { // io_service_add_notification
IOServiceAddNotificationRequest args = new IOServiceAddNotificationRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("io_service_add_notification args={}, matching={}", args, 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_add_notification reply={}", reply);
}
return MACH_MSG_SUCCESS;
}
case 4816: { // vm_region_64
VmRegion64Request args = new VmRegion64Request(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("vm_region_64 args={}", args);
}
if (args.flavor != VmRegion64Request.VM_REGION_BASIC_INFO_64) {
throw new UnsupportedOperationException("flavor=" + args.flavor);
}
VmRegion64Reply reply = new VmRegion64Reply(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();
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.retCode1 = 1;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("vm_region_64 reply={}", reply);
}
return MACH_MSG_SUCCESS;
}
reply.NDR.mig_vers = 1;
reply.NDR.int_rep = 0;
reply.retCode2 = 0x110000;
reply.outCnt = VmRegion64Request.VM_REGION_BASIC_INFO_COUNT_64;
reply.address = memoryRegion.base;
reply.size = 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_64 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;
}
if (args.flavor == TaskInfoRequest.TASK_VM_INFO) {
TaskVmInfoReply64 reply = new TaskVmInfoReply64(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(TaskVmInfo64.class) / 4;
reply.vmInfo.virtual_size = 0x100000000L;
reply.vmInfo.region_count = emulator.getMemory().getMemoryMap().size();
reply.vmInfo.page_size = emulator.getPageAlign();
reply.pack();
if (log.isDebugEnabled()) {
log.debug("task_info TASK_VM_INFO reply={}", reply);
}
return MACH_MSG_SUCCESS;
}
if (args.flavor == TaskInfoRequest.TASK_BASIC_INFO_64_2) {
TaskBasicInfoReply64V2 reply = new TaskBasicInfoReply64V2(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(TaskBasicInfoReply64V2.class) / 4;
// get usage size;
reply.basicInfo.suspendCount = 0;
// 1gb
reply.basicInfo.virtualSize = 1024 * 1024 * 1024;
// 100m
reply.basicInfo.residentSize = 100 * 1024 * 1024;
//
reply.basicInfo.userTime = 0;
reply.basicInfo.systemTime = 0;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("task_info TASK_BASIC_INFO_64_2 reply={}", reply);
}
return MACH_MSG_SUCCESS;
}
log.warn("task_info flavor={}", args.flavor);
if (LoggerFactory.getLogger(AbstractEmulator.class).isDebugEnabled()) {
createBreaker(emulator).debug();
}
return -1;
}
case 78: { // _dispatch_send_wakeup_runloop_thread
if (log.isDebugEnabled()) {
log.debug("_dispatch_send_wakeup_runloop_thread");
}
return MACH_MSG_SUCCESS;
}
case 3402: { // task_threads
TaskThreadsReply64 reply = new TaskThreadsReply64(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.act_list = 0;
reply.mask = 0x2110000;
reply.act_listCnt = 0;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("task_threads 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 4808: // vm_read_overwrite
{
VmReadOverwriteRequest args = new VmReadOverwriteRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("vm_read_overwrite args={}, lr={}", args, UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_LR));
}
byte[] data = backend.mem_read(args.address, args.size);
emulator.getMemory().pointer(args.data).write(data);
VmReadOverwriteReply reply = new VmReadOverwriteReply(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.outSize = args.size;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("vm_read_overwrite reply={}, header={}", reply, header);
}
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);
}
ThreadStateReply64 reply = new ThreadStateReply64(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_STATE64) {
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_STATE64_COUNT;
for (int reg = Arm64Const.UC_ARM64_REG_X0; reg <= Arm64Const.UC_ARM64_REG_X28; reg++) {
reply.state.__x[reg - Arm64Const.UC_ARM64_REG_X0] = backend.reg_read(reg).longValue();
}
reply.state.__fp = backend.reg_read(Arm64Const.UC_ARM64_REG_FP).longValue();
reply.state.__lr = backend.reg_read(Arm64Const.UC_ARM64_REG_LR).longValue();
reply.state.__sp = backend.reg_read(Arm64Const.UC_ARM64_REG_SP).longValue();
reply.state.__pc = backend.reg_read(Arm64Const.UC_ARM64_REG_PC).longValue();
reply.state.__cpsr = backend.reg_read(Arm64Const.UC_ARM64_REG_NZCV).intValue();
reply.state.__pad = 0;
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 4811: { // _kernelrpc_mach_vm_map
MachVmMapRequest args = new MachVmMapRequest(request);
args.unpack();
log.debug("_kernelrpc_mach_vm_map args={}", args);
MachVmMapReply reply = new MachVmMapReply(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;
{
MachOLoader loader = (MachOLoader) emulator.getMemory();
UnidbgPointer pointer;
if (args.mask != 0) {
pointer = UnidbgPointer.pointer(emulator, loader.allocate(args.size, args.mask));
} else {
pointer = loader.mmap((int) args.size, args.cur_protection);
}
reply.address = UnidbgPointer.nativeValue(pointer);
}
reply.pack();
log.debug("_kernelrpc_mach_vm_map reply={}, header={}", reply, header);
return MACH_MSG_SUCCESS;
}
case 4817: { // mach_make_memory_entry_64
MakeMemoryEntryRequest args = new MakeMemoryEntryRequest(request);
args.unpack();
if (log.isDebugEnabled()) {
log.debug("mach_make_memory_entry_64 args={}", args);
}
MakeMemoryEntryReply reply = new MakeMemoryEntryReply(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.status = 1;
reply.object_handle = 0;
reply.retCode = 0;
reply.flags = 0x110000;
reply.NDR = args.NDR;
reply.outSize = args.size;
reply.pack();
if (log.isDebugEnabled()) {
log.debug("mach_make_memory_entry_64 reply={}, header={}", reply, header);
}
return MACH_MSG_SUCCESS;
}
case 4818: { // vm_purgable_control
PurgableControlRequest args = new PurgableControlRequest(request);
args.unpack();
log.debug("vm_purgable_control args={}", args);
PurgableControlReply reply = new PurgableControlReply(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 VM_PURGABLE_EMPTY = 2;
reply.NDR = args.NDR;
reply.retCode = 0;
reply.state = VM_PURGABLE_EMPTY;
reply.pack();
log.debug("vm_purgable_control reply={}, header={}", reply, header);
return MACH_MSG_SUCCESS;
}
case 216: // host_statistics
if (host_statistics(request, header)) {
return MACH_MSG_SUCCESS;
}
default:
log.warn("mach_msg_trap header={}, size={}, lr={}", header, header.size(), UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_LR));
if (log.isDebugEnabled() || LoggerFactory.getLogger(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 long audit_session_self() {
log.debug("audit_session_self");
return 5;
}
private int kevent64(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int kq = context.getIntArg(0);
Pointer changelist = context.getPointerArg(1);
int nchanges = context.getIntArg(2);
Pointer eventlist = context.getPointerArg(3);
int nevents = context.getIntArg(4);
int flags = context.getIntArg(5);
Pointer timeout = context.getPointerArg(6);
return kevent64(emulator, kq, changelist, nchanges, eventlist, nevents, flags, TimeSpec.createTimeSpec(emulator, timeout));
}
private int sigprocmask(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int how = context.getIntArg(0);
Pointer set = context.getPointerArg(1);
Pointer oldset = context.getPointerArg(2);
return sigprocmask(emulator, how, set, oldset);
}
private int sigaltstack(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer nstack = context.getPointerArg(0);
Pointer ostack = context.getPointerArg(1);
if (log.isDebugEnabled()) {
log.debug("sigaltstack nstack={}, ostack={}", nstack, ostack);
}
return 0;
}
private long 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={}, request=0x{}, argp=0x{}", fd, Long.toHexString(request), 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;
}
protected long gettimeofday(Emulator> emulator) {
EditableArm64RegisterContext context = emulator.getContext();
long currentTimeMillis = System.currentTimeMillis();
long nanoTime = System.nanoTime();
long tv_sec = currentTimeMillis / 1000;
long tv_usec = (currentTimeMillis % 1000) * 1000 + nanoTime % 1000;
context.setXLong(1, tv_usec);
Pointer tv = context.getPointerArg(0);
if (tv != null) {
TimeVal64 timeVal = new TimeVal64(tv);
timeVal.tv_sec = tv_sec;
timeVal.tv_usec = tv_usec;
timeVal.pack();
}
if (log.isDebugEnabled()) {
log.debug("gettimeofday tv_sec={}, tv_usec={}", tv_sec, tv_usec);
}
return tv_sec;
}
private long 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 * 16L);
long iov_len = iov.getLong(i * 16L + 8);
byte[] data = iov_base.getByteArray(0, (int) 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 * 16L);
long iov_len = iov.getLong(i * 16L + 8);
byte[] data = iov_base.getByteArray(0, (int) iov_len);
count += file.write(data);
}
return count;
}
private int rename(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer oldpath = context.getPointerArg(0);
Pointer newpath = context.getPointerArg(1);
String oldPath = oldpath.getString(0);
String newPath = newpath.getString(0);
int ret = emulator.getFileSystem().rename(oldPath, newPath);
if (ret != 0) {
log.info("rename oldPath={}, newPath={}", oldPath, newPath);
} else {
log.debug("rename oldPath={}, newPath={}", oldPath, newPath);
}
return 0;
}
private long mach_absolute_time() {
long nanoTime = System.nanoTime();
if (log.isDebugEnabled()) {
log.debug("mach_absolute_time nanoTime={}", nanoTime);
}
return nanoTime;
}
private int close_NOCANCEL(Emulator> emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(Arm64Const.UC_ARM64_REG_X0).intValue();
if (log.isDebugEnabled()) {
log.debug("close_NOCANCEL fd={}", fd);
}
return close(emulator, fd);
}
private int read_NOCANCEL(Emulator> emulator, int offset) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(offset);
Pointer buffer = context.getPointerArg(offset + 1);
int count = context.getIntArg(offset + 2);
if (log.isDebugEnabled()) {
log.debug("read_NOCANCEL fd={}, buffer={}, count={}, LR={}", fd, buffer, count, context.getLRPointer());
}
return read(emulator, fd, buffer, count);
}
private int getpid(Emulator> emulator) {
int pid = emulator.getPid();
log.debug("getpid pid={}", pid);
return pid;
}
private int sendto(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int sockfd = context.getIntArg(0);
Pointer buf = context.getPointerArg(1);
int len = context.getIntArg(2);
int flags = context.getIntArg(3);
Pointer dest_addr = context.getPointerArg(4);
int addrlen = context.getIntArg(5);
return sendto(emulator, sockfd, buf, len, flags, dest_addr, addrlen);
}
private int connect(Emulator> emulator, int offset) {
RegisterContext context = emulator.getContext();
int sockfd = context.getIntArg(offset);
Pointer addr = context.getPointerArg(offset + 1);
int addrlen = context.getIntArg(offset + 2);
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 dup2(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int oldfd = context.getIntArg(0);
int newfd = context.getIntArg(1);
if (log.isDebugEnabled()) {
log.debug("dup2 oldfd={}, newfd={}", oldfd, newfd);
}
FileIO old = fdMap.get(oldfd);
if (old == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
if (oldfd == newfd) {
return newfd;
}
DarwinFileIO _new = fdMap.remove(newfd);
if (_new != null) {
_new.close();
}
_new = (DarwinFileIO) old.dup2();
fdMap.put(newfd, _new);
return newfd;
}
private int fcntl(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
int cmd = context.getIntArg(1);
long arg = context.getLongArg(2);
return fcntl(emulator, fd, cmd, arg);
}
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 long mmap(Emulator> emulator) {
Arm64RegisterContext context = emulator.getContext();
UnidbgPointer addr = context.getXPointer(0);
int length = context.getXInt(1);
int prot = context.getXInt(2);
int flags = context.getXInt(3);
int fd = context.getXInt(4);
long offset = context.getXLong(5);
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 + ", base=0x" + Long.toHexString(base) + ", length=" + length + ", prot=0x" + Integer.toHexString(prot) + ", flags=0x" + Integer.toHexString(flags) + ", fd=" + fd + ", offset=" + offset + ", tag=" + tag + ", LR=" + context.getLRPointer();
if (log.isDebugEnabled() || warning) {
if (warning) {
log.warn(msg);
} else {
log.debug(msg);
}
} else if(LoggerFactory.getLogger("com.github.unidbg.ios.malloc").isDebugEnabled()) {
log.debug(msg);
}
return base;
}
private int socket(Emulator> emulator, int offset) {
RegisterContext context = emulator.getContext();
int domain = context.getIntArg(offset);
int type = context.getIntArg(offset + 1) & 0x7ffff;
int protocol = context.getIntArg(offset + 2);
if (log.isDebugEnabled()) {
log.debug("socket domain={}, type={}, protocol={}", domain, type, 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, int offset) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(offset);
Pointer buffer = context.getPointerArg(offset + 1);
int count = context.getIntArg(offset + 2);
byte[] data = buffer.getByteArray(0, count);
if (log.isDebugEnabled()) {
log.debug("write fd={}, buffer={}, count={}", fd, buffer, 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(Arm64Const.UC_ARM64_REG_X0).longValue();
long length = backend.reg_read(Arm64Const.UC_ARM64_REG_X1).longValue();
int prot = backend.reg_read(Arm64Const.UC_ARM64_REG_X2).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{}, alignedAddress=0x{}, offset={}, length={}, alignedLength={}, prot=0x{}", Long.toHexString(address), Long.toHexString(alignedAddress), offset, length, alignedLength, 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