com.github.unidbg.linux.ARM32SyscallHandler Maven / Gradle / Ivy
package com.github.unidbg.linux;
import com.github.unidbg.AbstractEmulator;
import com.github.unidbg.Emulator;
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.backend.Backend;
import com.github.unidbg.arm.backend.BackendException;
import com.github.unidbg.arm.context.Arm32RegisterContext;
import com.github.unidbg.arm.context.RegisterContext;
import com.github.unidbg.file.FileIO;
import com.github.unidbg.file.FileResult;
import com.github.unidbg.file.IOResolver;
import com.github.unidbg.file.linux.AndroidFileIO;
import com.github.unidbg.file.linux.IOConstants;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.file.*;
import com.github.unidbg.linux.struct.Stat32;
import com.github.unidbg.linux.struct.SysInfo32;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.memory.MemoryMap;
import com.github.unidbg.memory.SvcMemory;
import com.github.unidbg.pointer.UnidbgPointer;
import com.github.unidbg.unix.IO;
import com.github.unidbg.unix.UnixEmulator;
import com.github.unidbg.utils.Inspector;
import com.sun.jna.Pointer;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import unicorn.ArmConst;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import static unicorn.ArmConst.UC_ARM_REG_C13_C0_3;
/**
* http://androidxref.com/6.0.0_r5/xref/bionic/libc/kernel/uapi/asm-arm/asm/unistd.h
*/
public class ARM32SyscallHandler extends AndroidSyscallHandler {
private static final Log log = LogFactory.getLog(ARM32SyscallHandler.class);
private final SvcMemory svcMemory;
public ARM32SyscallHandler(SvcMemory svcMemory) {
super();
this.svcMemory = svcMemory;
}
@SuppressWarnings("unchecked")
@Override
public void hook(Backend backend, int intno, Object user) {
Emulator emulator = (Emulator) user;
UnidbgPointer pc = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_PC);
final boolean isThumb = ARM.isThumb(backend);
final int bkpt;
if (ARM.isThumb(backend)) {
bkpt = pc.getShort(0) & 0xff;
} else {
int instruction = pc.getInt(0);
bkpt = (instruction & 0xf) | ((instruction >> 8) & 0xfff) << 4;
}
if (intno == ARMEmulator.EXCP_BKPT) { // bkpt
createBreaker(emulator).brk(pc, bkpt);
return;
}
if (intno != ARMEmulator.EXCP_SWI) {
throw new BackendException("intno=" + intno);
}
final int svcNumber;
if (isThumb) {
svcNumber = pc.getShort(-2) & 0xff;
} else {
svcNumber = pc.getInt(-4) & 0xffffff;
}
int NR = backend.reg_read(ArmConst.UC_ARM_REG_R7).intValue();
String syscall = null;
Throwable exception = null;
try {
if (svcNumber == 0 && NR == 0 && (backend.reg_read(ArmConst.UC_ARM_REG_R5).intValue()) == Svc.CALLBACK_SYSCALL_NUMBER) { // callback
int number = backend.reg_read(ArmConst.UC_ARM_REG_R4).intValue();
Svc svc = svcMemory.getSvc(number);
if (svc != null) {
svc.handleCallback(emulator);
return;
}
backend.emu_stop();
throw new IllegalStateException("svc number: " + svcNumber);
}
if (svcNumber != 0) {
Svc svc = svcMemory.getSvc(svcNumber);
if (svc != null) {
backend.reg_write(ArmConst.UC_ARM_REG_R0, (int) svc.handle(emulator));
return;
}
backend.emu_stop();
throw new IllegalStateException("svc number: " + svcNumber);
}
if (log.isDebugEnabled()) {
ARM.showThumbRegs(emulator);
}
if (handleSyscall(emulator, NR)) {
return;
}
switch (NR) {
case 1:
int status = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
System.out.println("exit status=" + status);
backend.emu_stop();
return;
case 2:
backend.reg_write(ArmConst.UC_ARM_REG_R0, fork(emulator));
return;
case 3:
backend.reg_write(ArmConst.UC_ARM_REG_R0, read(emulator));
return;
case 4:
backend.reg_write(ArmConst.UC_ARM_REG_R0, write(emulator));
return;
case 5:
backend.reg_write(ArmConst.UC_ARM_REG_R0, open(emulator));
return;
case 6:
backend.reg_write(ArmConst.UC_ARM_REG_R0, close(emulator));
return;
case 10:
backend.reg_write(ArmConst.UC_ARM_REG_R0, unlink(emulator));
return;
case 11:
backend.reg_write(ArmConst.UC_ARM_REG_R0, execve(emulator));
return;
case 19:
backend.reg_write(ArmConst.UC_ARM_REG_R0, lseek(emulator));
return;
case 26:
backend.reg_write(ArmConst.UC_ARM_REG_R0, ptrace(emulator));
return;
case 20: // getpid
case 224: // gettid
backend.reg_write(ArmConst.UC_ARM_REG_R0, emulator.getPid());
return;
case 33:
backend.reg_write(ArmConst.UC_ARM_REG_R0, access(emulator));
return;
case 36: // sync: causes all pending modifications to filesystem metadata and cached file data to be written to the underlying filesystems.
return;
case 37:
backend.reg_write(ArmConst.UC_ARM_REG_R0, kill(emulator));
return;
case 38:
backend.reg_write(ArmConst.UC_ARM_REG_R0, rename(emulator));
return;
case 39:
backend.reg_write(ArmConst.UC_ARM_REG_R0, mkdir(emulator));
return;
case 41:
backend.reg_write(ArmConst.UC_ARM_REG_R0, dup(emulator));
return;
case 42:
backend.reg_write(ArmConst.UC_ARM_REG_R0, pipe(emulator));
return;
case 45:
backend.reg_write(ArmConst.UC_ARM_REG_R0, brk(emulator));
return;
case 54:
backend.reg_write(ArmConst.UC_ARM_REG_R0, ioctl(emulator));
return;
case 57:
backend.reg_write(ArmConst.UC_ARM_REG_R0, setpgid(emulator));
return;
case 60:
backend.reg_write(ArmConst.UC_ARM_REG_R0, umask(emulator));
return;
case 63:
backend.reg_write(ArmConst.UC_ARM_REG_R0, dup2(backend, emulator));
return;
case 64:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getppid(emulator));
return;
case 67:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sigaction(backend, emulator));
return;
case 78:
backend.reg_write(ArmConst.UC_ARM_REG_R0, gettimeofday(emulator));
return;
case 85:
backend.reg_write(ArmConst.UC_ARM_REG_R0, readlink(emulator));
return;
case 88:
backend.reg_write(ArmConst.UC_ARM_REG_R0, reboot(backend, emulator));
return;
case 91:
backend.reg_write(ArmConst.UC_ARM_REG_R0, munmap(backend, emulator));
return;
case 93:
backend.reg_write(ArmConst.UC_ARM_REG_R0, ftruncate(backend));
return;
case 94:
backend.reg_write(ArmConst.UC_ARM_REG_R0, fchmod(backend));
return;
case 103:
backend.reg_write(ArmConst.UC_ARM_REG_R0, syslog(backend, emulator));
return;
case 104:
backend.reg_write(ArmConst.UC_ARM_REG_R0, setitimer(emulator));
return;
case 116:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sysinfo(emulator));
return;
case 118:
backend.reg_write(ArmConst.UC_ARM_REG_R0, fsync(backend));
return;
case 120:
backend.reg_write(ArmConst.UC_ARM_REG_R0, clone(backend, emulator));
return;
case 122:
backend.reg_write(ArmConst.UC_ARM_REG_R0, uname(emulator));
return;
case 125:
backend.reg_write(ArmConst.UC_ARM_REG_R0, mprotect(backend, emulator));
return;
case 126:
case 175:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sigprocmask(backend, emulator));
return;
case 132:
syscall = "getpgid";
break;
case 136:
backend.reg_write(ArmConst.UC_ARM_REG_R0, personality(backend));
return;
case 140:
backend.reg_write(ArmConst.UC_ARM_REG_R0, llseek(backend, emulator));
return;
case 142:
backend.reg_write(ArmConst.UC_ARM_REG_R0, newselect(backend, emulator));
return;
case 143:
backend.reg_write(ArmConst.UC_ARM_REG_R0, flock(backend));
return;
case 146:
backend.reg_write(ArmConst.UC_ARM_REG_R0, writev(backend, emulator));
return;
case 147:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getsid(emulator));
return;
case 162:
backend.reg_write(ArmConst.UC_ARM_REG_R0, nanosleep(emulator));
return;
case 163:
backend.reg_write(ArmConst.UC_ARM_REG_R0, mremap(emulator));
return;
case 168:
case 336:
backend.reg_write(ArmConst.UC_ARM_REG_R0, poll(backend, emulator));
return;
case 172:
backend.reg_write(ArmConst.UC_ARM_REG_R0, prctl(backend, emulator));
return;
case 183:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getcwd(backend, emulator));
return;
case 186:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sigaltstack(emulator));
return;
case 192:
backend.reg_write(ArmConst.UC_ARM_REG_R0, mmap2(backend, emulator));
return;
case 194:
backend.reg_write(ArmConst.UC_ARM_REG_R0, ftruncate(backend));
return;
case 195:
backend.reg_write(ArmConst.UC_ARM_REG_R0, stat64(emulator));
return;
case 196:
backend.reg_write(ArmConst.UC_ARM_REG_R0, lstat(emulator));
return;
case 197:
backend.reg_write(ArmConst.UC_ARM_REG_R0, fstat(backend, emulator));
return;
case 199: // getuid
case 200: // getgid
case 201: // geteuid
case 202: // getegid
backend.reg_write(ArmConst.UC_ARM_REG_R0, 0);
return;
case 205:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getgroups(backend, emulator));
return;
case 208:
backend.reg_write(ArmConst.UC_ARM_REG_R0, setresuid32(backend));
return;
case 210:
backend.reg_write(ArmConst.UC_ARM_REG_R0, setresgid32(backend));
return;
case 214:
backend.reg_write(ArmConst.UC_ARM_REG_R0, setgid32(emulator));
return;
case 217:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getdents64(emulator));
return;
case 220:
syscall = "madvise";
backend.reg_write(ArmConst.UC_ARM_REG_R0, 0);
return;
case 221:
backend.reg_write(ArmConst.UC_ARM_REG_R0, fcntl(backend, emulator));
return;
case 230:
backend.reg_write(ArmConst.UC_ARM_REG_R0, lgetxattr(backend, emulator));
return;
case 238:
backend.reg_write(ArmConst.UC_ARM_REG_R0, tkill(emulator));
return;
case 240:
backend.reg_write(ArmConst.UC_ARM_REG_R0, futex(emulator));
return;
case 248:
exit_group(emulator);
return;
case 263:
backend.reg_write(ArmConst.UC_ARM_REG_R0, clock_gettime(backend, emulator));
return;
case 266: {
RegisterContext context = emulator.getContext();
Pointer pathPointer = context.getPointerArg(0);
int size = context.getIntArg(1);
Pointer buf = context.getPointerArg(2).setSize(size);
String path = pathPointer.getString(0);
backend.reg_write(ArmConst.UC_ARM_REG_R0, (int) statfs64(emulator, path, buf));
return;
}
case 268:
backend.reg_write(ArmConst.UC_ARM_REG_R0, tgkill(backend));
return;
case 269:
backend.reg_write(ArmConst.UC_ARM_REG_R0, utimes(emulator));
return;
case 281:
backend.reg_write(ArmConst.UC_ARM_REG_R0, socket(backend, emulator));
return;
case 282:
backend.reg_write(ArmConst.UC_ARM_REG_R0, bind(emulator));
return;
case 283:
backend.reg_write(ArmConst.UC_ARM_REG_R0, connect(backend, emulator));
return;
case 284:
backend.reg_write(ArmConst.UC_ARM_REG_R0, listen(emulator));
return;
case 285:
backend.reg_write(ArmConst.UC_ARM_REG_R0, accept(emulator));
return;
case 286:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getsockname(backend, emulator));
return;
case 287:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getpeername(backend, emulator));
return;
case 290:
backend.reg_write(ArmConst.UC_ARM_REG_R0, sendto(backend, emulator));
return;
case 292:
backend.reg_write(ArmConst.UC_ARM_REG_R0, recvfrom(emulator));
return;
case 293:
backend.reg_write(ArmConst.UC_ARM_REG_R0, shutdown(backend, emulator));
return;
case 294:
backend.reg_write(ArmConst.UC_ARM_REG_R0, setsockopt(backend, emulator));
return;
case 295:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getsockopt(backend, emulator));
return;
case 322:
backend.reg_write(ArmConst.UC_ARM_REG_R0, openat(backend, emulator));
return;
case 323:
backend.reg_write(ArmConst.UC_ARM_REG_R0, mkdirat(backend, emulator));
return;
case 327:
backend.reg_write(ArmConst.UC_ARM_REG_R0, fstatat64(backend, emulator));
return;
case 328:
backend.reg_write(ArmConst.UC_ARM_REG_R0, unlinkat(emulator));
return;
case 332:
backend.reg_write(ArmConst.UC_ARM_REG_R0, readlinkat(emulator));
return;
case 329:
backend.reg_write(ArmConst.UC_ARM_REG_R0, renameat(emulator));
return;
case 334:
backend.reg_write(ArmConst.UC_ARM_REG_R0, faccessat(backend, emulator));
return;
case 335:
backend.reg_write(ArmConst.UC_ARM_REG_R0, pselect6(emulator));
return;
case 345:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getcpu(emulator));
return;
case 348:
backend.reg_write(ArmConst.UC_ARM_REG_R0, utimensat(backend, emulator));
return;
case 358:
backend.reg_write(ArmConst.UC_ARM_REG_R0, dup3(emulator));
return;
case 366:
backend.reg_write(ArmConst.UC_ARM_REG_R0, accept4(emulator));
return;
case 384:
backend.reg_write(ArmConst.UC_ARM_REG_R0, getrandom(emulator));
return;
case 0xf0002:
backend.reg_write(ArmConst.UC_ARM_REG_R0, cacheflush(backend, emulator));
return;
case 0xf0005:
backend.reg_write(ArmConst.UC_ARM_REG_R0, set_tls(backend, emulator));
return;
}
} catch (StopEmulatorException e) {
backend.emu_stop();
return;
} catch (Throwable e) {
backend.emu_stop();
exception = e;
}
if (exception == null && handleUnknownSyscall(emulator, NR)) {
return;
}
log.warn("handleInterrupt intno=" + intno + ", NR=" + NR + ", svcNumber=0x" + Integer.toHexString(svcNumber) + ", PC=" + pc + ", syscall=" + syscall, exception);
if (exception instanceof RuntimeException) {
throw (RuntimeException) exception;
}
}
private int getrandom(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer buf = context.getPointerArg(0);
int bufSize = context.getIntArg(1);
int flags = context.getIntArg(2);
return getrandom(buf, bufSize, flags);
}
private int clone(Backend backend, Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
Pointer child_stack = context.getPointerArg(1);
if (child_stack == null &&
context.getPointerArg(2) == null) {
// http://androidxref.com/6.0.1_r10/xref/bionic/libc/bionic/fork.cpp#47
return fork(emulator); // vfork
}
int fn = context.getR5Int();
int arg = context.getR6Int();
if (child_stack != null && child_stack.getInt(-4) == fn && child_stack.getInt(-8) == arg) {
// http://androidxref.com/6.0.1_r10/xref/bionic/libc/arch-arm/bionic/__bionic_clone.S#49
return bionic_clone(backend, emulator);
} else {
return pthread_clone(backend, emulator);
}
}
private int tkill(Emulator emulator) {
RegisterContext context = emulator.getContext();
int tid = context.getIntArg(0);
int sig = context.getIntArg(1);
if (log.isDebugEnabled()) {
log.debug("tkill tid=" + tid + ", sig=" + sig);
}
return 0;
}
private int setpgid(Emulator emulator) {
RegisterContext context = emulator.getContext();
int pid = context.getIntArg(0);
int pgid = context.getIntArg(1);
if (log.isDebugEnabled()) {
log.debug("setpgid pid=" + pid + ", pgid=" + pgid);
}
return 0;
}
private int getsid(Emulator emulator) {
RegisterContext context = emulator.getContext();
int pid = context.getIntArg(0);
if (log.isDebugEnabled()) {
log.debug("getsid pid=" + pid);
}
return emulator.getPid();
}
private int readlinkat(Emulator emulator) {
RegisterContext context = emulator.getContext();
int dirfd = context.getIntArg(0);
Pointer pathname = context.getPointerArg(1);
Pointer buf = context.getPointerArg(2);
int bufSize = context.getIntArg(3);
String path = pathname.getString(0);
if (dirfd != IO.AT_FDCWD) {
throw new BackendException();
}
return readlink(emulator, path, buf, bufSize);
}
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);
return readlink(emulator, path, buf, bufSize);
}
private int getppid(Emulator> emulator) {
if (log.isDebugEnabled()) {
log.debug("getppid");
}
return emulator.getPid();
}
private int getcpu(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
Pointer cpu = context.getR0Pointer();
Pointer node = context.getR1Pointer();
Pointer tcache = context.getR2Pointer();
if (log.isDebugEnabled()) {
log.debug("getcpu cpu=" + cpu + ", node=" + node + ", tcache=" + tcache);
}
if (cpu != null) {
cpu.setInt(0, 0);
}
if (node != null) {
node.setInt(0, 0);
}
return 0;
}
private int sysinfo(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
Pointer info = context.getR0Pointer();
if (log.isDebugEnabled()) {
log.debug("sysinfo info=" + info);
}
SysInfo32 sysInfo32 = new SysInfo32(info);
sysInfo32.pack();
return 0;
}
private static final int MREMAP_MAYMOVE = 1;
private int mremap(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
UnidbgPointer old_address = context.getR0Pointer();
int old_size = context.getR1Int();
int new_size = context.getR2Int();
int flags = context.getR3Int();
Pointer new_address = context.getR4Pointer();
if (log.isDebugEnabled()) {
log.debug("mremap old_address=" + old_address + ", old_size=" + old_size + ", new_size=" + new_size + ", flags=" + flags + ", new_address=" + new_address);
}
if (old_size == 0) {
throw new BackendException("old_size is zero");
}
if ((flags & MREMAP_MAYMOVE) == 0) {
throw new BackendException("flags=" + flags);
}
Memory memory = emulator.getMemory();
for (MemoryMap map : memory.getMemoryMap()) {
if (map.base == old_address.toUIntPeer() && map.size == old_size) {
byte[] data = new byte[old_size];
old_address.read(0, data, 0, data.length);
memory.munmap(map.base, (int) map.size);
long address = emulator.getMemory().mmap2(0, new_size, map.prot, AndroidElfLoader.MAP_ANONYMOUS, 0, 0);
UnidbgPointer pointer = UnidbgPointer.pointer(emulator, address);
assert pointer != null;
pointer.write(0, data, 0, data.length);
return (int) pointer.toUIntPeer();
}
}
throw new BackendException();
}
protected int ptrace(Emulator> emulator) {
Backend backend = emulator.getBackend();
int request = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int pid = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
Pointer addr = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
Pointer data = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R3);
log.info("ptrace request=0x" + Integer.toHexString(request) + ", pid=" + pid + ", addr=" + addr + ", data=" + data);
return 0;
}
private int utimes(Emulator> emulator) {
Pointer filename = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
Pointer times = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
if (log.isDebugEnabled()) {
log.debug("utimes filename=" + filename.getString(0) + ", times=" + times);
}
return 0;
}
private int utimensat(Backend backend, Emulator> emulator) {
int dirfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer pathname = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
Pointer times = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
int flags = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
if (log.isDebugEnabled()) {
log.debug("utimensat dirfd=" + dirfd + ", pathname=" + pathname.getString(0) + ", times=" + times + ", flags=" + flags);
}
return 0;
}
private int fsync(Backend backend) {
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
if (log.isDebugEnabled()) {
log.debug("fsync fd=" + fd);
}
return 0;
}
private int rename(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
Pointer oldpath = context.getR0Pointer();
Pointer newpath = context.getR1Pointer();
log.info("rename oldpath=" + oldpath.getString(0) + ", newpath=" + newpath.getString(0));
return 0;
}
private int renameat(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
int olddirfd = context.getR0Int();
Pointer oldpath = context.getR1Pointer();
int newdirfd = context.getR2Int();
Pointer newpath = context.getR3Pointer();
log.info("renameat olddirfd=" + olddirfd + ", oldpath=" + oldpath.getString(0) + ", newdirfd=" + newdirfd + ", newpath=" + newpath.getString(0));
return 0;
}
private int unlinkat(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
int dirfd = context.getR0Int();
Pointer pathname = context.getR1Pointer();
int flags = context.getR2Int();
log.info("unlinkat dirfd=" + dirfd + ", pathname=" + pathname.getString(0) + ", flags=" + flags);
return 0;
}
private int unlink(Emulator> emulator) {
Pointer pathname = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
String path = FilenameUtils.normalize(pathname.getString(0), true);
log.info("unlink path=" + path);
return 0;
}
private int pipe(Emulator> emulator) {
Pointer pipefd = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
if (log.isDebugEnabled()) {
int readfd = pipefd.getInt(0);
int writefd = pipefd.getInt(4);
log.debug("pipe readfd=" + readfd + ", writefd=" + writefd);
}
emulator.getMemory().setErrno(UnixEmulator.EFAULT);
return -1;
}
private int sigaltstack(Emulator> emulator) {
Pointer ss = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
Pointer old_ss = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
if (log.isDebugEnabled()) {
log.debug("sigaltstack ss=" + ss + ", old_ss=" + old_ss);
}
return 0;
}
private int set_tls(Backend backend, Emulator> emulator) {
UnidbgPointer tls = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
if (log.isDebugEnabled()) {
log.debug("set_tls: " + tls);
}
backend.reg_write(UC_ARM_REG_C13_C0_3, tls.peer);
return 0;
}
private int cacheflush(Backend backend, Emulator> emulator) {
Pointer begin = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
Pointer end = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int cache = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
if (log.isDebugEnabled()) {
log.debug("cacheflush begin=" + begin + ", end=" + end + ", cache=" + cache);
}
return 0;
}
protected int fork(Emulator> emulator) {
log.info("fork");
emulator.getMemory().setErrno(UnixEmulator.ENOSYS);
return -1;
}
private int tgkill(Backend backend) {
int tgid = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int tid = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int sig = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
if (log.isDebugEnabled()) {
log.debug("tgkill tgid=" + tgid + ", tid=" + tid + ", sig=" + sig);
}
return 0;
}
private int threadId;
private static final int CLONE_VM = 0x00000100;
private static final int CLONE_FS = 0x00000200;
private static final int CLONE_FILES = 0x00000400;
private static final int CLONE_SIGHAND = 0x00000800;
private static final int CLONE_PTRACE = 0x00002000;
private static final int CLONE_VFORK = 0x00004000;
private static final int CLONE_PARENT = 0x00008000;
private static final int CLONE_THREAD = 0x00010000;
private static final int CLONE_NEWNS = 0x00020000;
private static final int CLONE_SYSVSEM = 0x00040000;
private static final int CLONE_SETTLS = 0x00080000;
private static final int CLONE_PARENT_SETTID = 0x00100000;
private static final int CLONE_CHILD_CLEARTID = 0x00200000;
private static final int CLONE_DETACHED = 0x00400000;
private static final int CLONE_UNTRACED = 0x00800000;
private static final int CLONE_CHILD_SETTID = 0x01000000;
private static final int CLONE_STOPPED = 0x02000000;
private int pthread_clone(Backend backend, Emulator> emulator) {
int flags = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer child_stack = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
List list = new ArrayList<>();
if ((flags & CLONE_VM) != 0) {
list.add("CLONE_VM");
}
if ((flags & CLONE_FS) != 0) {
list.add("CLONE_FS");
}
if ((flags & CLONE_FILES) != 0) {
list.add("CLONE_FILES");
}
if ((flags & CLONE_SIGHAND) != 0) {
list.add("CLONE_SIGHAND");
}
if ((flags & CLONE_PTRACE) != 0) {
list.add("CLONE_PTRACE");
}
if ((flags & CLONE_VFORK) != 0) {
list.add("CLONE_VFORK");
}
if ((flags & CLONE_PARENT) != 0) {
list.add("CLONE_PARENT");
}
if ((flags & CLONE_THREAD) != 0) {
list.add("CLONE_THREAD");
}
if ((flags & CLONE_NEWNS) != 0) {
list.add("CLONE_NEWNS");
}
if ((flags & CLONE_SYSVSEM) != 0) {
list.add("CLONE_SYSVSEM");
}
if ((flags & CLONE_SETTLS) != 0) {
list.add("CLONE_SETTLS");
}
if ((flags & CLONE_PARENT_SETTID) != 0) {
list.add("CLONE_PARENT_SETTID");
}
if ((flags & CLONE_CHILD_CLEARTID) != 0) {
list.add("CLONE_CHILD_CLEARTID");
}
if ((flags & CLONE_DETACHED) != 0) {
list.add("CLONE_DETACHED");
}
if ((flags & CLONE_UNTRACED) != 0) {
list.add("CLONE_UNTRACED");
}
if ((flags & CLONE_CHILD_SETTID) != 0) {
list.add("CLONE_CHILD_SETTID");
}
if ((flags & CLONE_STOPPED) != 0) {
list.add("CLONE_STOPPED");
}
int threadId = ++this.threadId;
Pointer fn = child_stack.getPointer(0);
child_stack = child_stack.share(4);
Pointer arg = child_stack.getPointer(0);
child_stack = child_stack.share(4);
log.info("pthread_clone child_stack=" + child_stack + ", thread_id=" + threadId + ", fn=" + fn + ", arg=" + arg + ", flags=" + list);
threadMap.put(threadId, new LinuxThread(child_stack, fn, arg));
lastThread = threadId;
return threadId;
}
private int bionic_clone(Backend backend, Emulator> emulator) {
int flags = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer child_stack = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
Pointer pid = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
Pointer tls = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R3);
Pointer ctid = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R4);
Pointer fn = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R5);
Pointer arg = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R6);
List list = new ArrayList<>();
if ((flags & CLONE_VM) != 0) {
list.add("CLONE_VM");
}
if ((flags & CLONE_FS) != 0) {
list.add("CLONE_FS");
}
if ((flags & CLONE_FILES) != 0) {
list.add("CLONE_FILES");
}
if ((flags & CLONE_SIGHAND) != 0) {
list.add("CLONE_SIGHAND");
}
if ((flags & CLONE_PTRACE) != 0) {
list.add("CLONE_PTRACE");
}
if ((flags & CLONE_VFORK) != 0) {
list.add("CLONE_VFORK");
}
if ((flags & CLONE_PARENT) != 0) {
list.add("CLONE_PARENT");
}
if ((flags & CLONE_THREAD) != 0) {
list.add("CLONE_THREAD");
}
if ((flags & CLONE_NEWNS) != 0) {
list.add("CLONE_NEWNS");
}
if ((flags & CLONE_SYSVSEM) != 0) {
list.add("CLONE_SYSVSEM");
}
if ((flags & CLONE_SETTLS) != 0) {
list.add("CLONE_SETTLS");
}
if ((flags & CLONE_PARENT_SETTID) != 0) {
list.add("CLONE_PARENT_SETTID");
}
if ((flags & CLONE_CHILD_CLEARTID) != 0) {
list.add("CLONE_CHILD_CLEARTID");
}
if ((flags & CLONE_DETACHED) != 0) {
list.add("CLONE_DETACHED");
}
if ((flags & CLONE_UNTRACED) != 0) {
list.add("CLONE_UNTRACED");
}
if ((flags & CLONE_CHILD_SETTID) != 0) {
list.add("CLONE_CHILD_SETTID");
}
if ((flags & CLONE_STOPPED) != 0) {
list.add("CLONE_STOPPED");
}
if (log.isDebugEnabled()) {
log.debug("bionic_clone child_stack=" + child_stack + ", thread_id=" + threadId + ", pid=" + pid + ", tls=" + tls + ", ctid=" + ctid + ", fn=" + fn + ", arg=" + arg + ", flags=" + list);
}
emulator.getMemory().setErrno(UnixEmulator.EAGAIN);
throw new AbstractMethodError();
}
private int flock(Backend backend) {
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int operation = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
if (log.isDebugEnabled()) {
log.debug("flock fd=" + fd + ", operation=" + operation);
}
return 0;
}
private int fchmod(Backend backend) {
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int mode = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
if (log.isDebugEnabled()) {
log.debug("fchmod fd=" + fd + ", mode=" + mode);
}
return 0;
}
private int llseek(Backend backend, Emulator> emulator) {
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
long offset_high = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue() & 0xffffffffL;
long offset_low = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue() & 0xffffffffL;
long offset = (offset_high<<32) | offset_low;
Pointer result = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R3);
int whence = backend.reg_read(ArmConst.UC_ARM_REG_R4).intValue();
if (log.isDebugEnabled()) {
log.debug("llseek fd=" + fd + ", offset_high=" + offset_high + ", offset_low=" + offset_low + ", result=" + result + ", whence=" + whence);
}
FileIO io = fdMap.get(fd);
if (io == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
} else {
return io.llseek(offset, result, whence);
}
}
private int access(Emulator emulator) {
Backend backend = emulator.getBackend();
Pointer pathname = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
int mode = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
if (pathname == null) {
emulator.getMemory().setErrno(UnixEmulator.EINVAL);
return -1;
}
String path = pathname.getString(0);
if (log.isDebugEnabled()) {
log.debug("access pathname=" + path + ", mode=" + mode);
}
int ret = faccessat(emulator, path);
if (ret == -1) {
log.info("access pathname=" + path + ", mode=" + mode);
}
return ret;
}
private int execve(Emulator> emulator) {
Pointer filename = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
Pointer argv = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
Pointer envp = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
assert filename != null;
List args = new ArrayList<>();
Pointer pointer;
while ((pointer = argv.getPointer(0)) != null) {
args.add(pointer.getString(0));
argv = argv.share(4);
}
List env = new ArrayList<>();
while ((pointer = envp.getPointer(0)) != null) {
env.add(pointer.getString(0));
envp = envp.share(4);
}
log.info("execve filename=" + filename.getString(0) + ", args=" + args + ", env=" + env);
emulator.getMemory().setErrno(UnixEmulator.EACCES);
return -1;
}
private long persona;
private int personality(Backend backend) {
long persona = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue() & 0xffffffffL;
if (log.isDebugEnabled()) {
log.debug("personality persona=0x" + Long.toHexString(persona));
}
int old = (int) this.persona;
if (persona != 0xffffffffL) {
this.persona = persona;
}
return old;
}
private int shutdown(Backend backend, Emulator> emulator) {
int sockfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int how = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
if (log.isDebugEnabled()) {
log.debug("shutdown sockfd=" + sockfd + ", how=" + how);
}
FileIO io = fdMap.get(sockfd);
if (io == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
return io.shutdown(how);
}
private int dup(Emulator> emulator) {
Backend backend = emulator.getBackend();
int oldfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
FileIO io = fdMap.get(oldfd);
if (io == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
if (log.isDebugEnabled()) {
log.debug("dup oldfd=" + oldfd + ", io=" + io);
}
AndroidFileIO _new = (AndroidFileIO) io.dup2();
if (_new == null) {
throw new UnsupportedOperationException();
}
int newfd = getMinFd();
fdMap.put(newfd, _new);
return newfd;
}
private int stat64(Emulator emulator) {
Pointer pathname = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
Pointer statbuf = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
String path = FilenameUtils.normalize(pathname.getString(0), true);
if (log.isDebugEnabled()) {
log.debug("stat64 pathname=" + path + ", statbuf=" + statbuf);
}
return stat64(emulator, path, statbuf);
}
private int lstat(Emulator emulator) {
Pointer pathname = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
Pointer statbuf = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
String path = FilenameUtils.normalize(pathname.getString(0), true);
if (log.isDebugEnabled()) {
log.debug("lstat pathname=" + path + ", statbuf=" + 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()) {
return result.io.fstat(emulator, new Stat32(statbuf));
}
log.info("stat64 pathname=" + pathname + ", LR=" + emulator.getContext().getLRPointer());
emulator.getMemory().setErrno(result != null ? result.errno : UnixEmulator.ENOENT);
return -1;
}
private int newselect(Backend backend, Emulator> emulator) {
int nfds = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer readfds = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
Pointer writefds = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
Pointer exceptfds = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R3);
Pointer timeout = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R4);
int size = (nfds - 1) / 8 + 1;
if (log.isDebugEnabled()) {
log.debug("newselect nfds=" + nfds + ", readfds=" + readfds + ", writefds=" + writefds + ", exceptfds=" + exceptfds + ", timeout=" + 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);
if (count > 0) {
return count;
}
}
if (readfds != null) {
int count = select(nfds, readfds, writefds);
if (count > 0) {
return count;
}
}
throw new AbstractMethodError();
}
private int select(int nfds, Pointer checkfds, Pointer clearfds) {
int count = 0;
for (int i = 0; i < nfds; i++) {
int mask = checkfds.getInt(i / 32);
if(((mask >> i) & 1) == 1) {
count++;
}
}
if (count > 0) {
if (clearfds != null) {
for (int i = 0; i < nfds; i++) {
clearfds.setInt(i / 32, 0);
}
}
}
return count;
}
private int pselect6(Emulator> emulator) {
Arm32RegisterContext 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.getR4Pointer();
int size = (nfds - 1) / 8 + 1;
if (log.isDebugEnabled()) {
log.debug("pselect6 nfds=" + nfds + ", readfds=" + readfds + ", writefds=" + writefds + ", exceptfds=" + exceptfds + ", timeout=" + 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);
if (count > 0) {
return count;
}
}
if (readfds != null) {
int count = select(nfds, readfds, writefds);
if (count > 0) {
return count;
}
}
throw new AbstractMethodError();
}
private int getpeername(Backend backend, Emulator> emulator) {
int sockfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer addr = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
Pointer addrlen = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
if (log.isDebugEnabled()) {
log.debug("getpeername sockfd=" + sockfd + ", addr=" + addr + ", addrlen=" + addrlen);
}
FileIO io = fdMap.get(sockfd);
if (io == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
return io.getpeername(addr, addrlen);
}
private static final short POLLIN = 0x0001;
private static final short POLLOUT = 0x0004;
private int poll(Backend backend, Emulator> emulator) {
Pointer fds = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
int nfds = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int timeout = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
int count = 0;
for (int i = 0; i < nfds; i++) {
Pointer pollfd = fds.share(i * 8);
int fd = pollfd.getInt(0);
short events = pollfd.getShort(4); // requested events
if (log.isDebugEnabled()) {
log.debug("poll fds=" + fds + ", nfds=" + nfds + ", timeout=" + timeout + ", fd=" + fd + ", events=" + events);
}
if (fd < 0) {
pollfd.setShort(6, (short) 0);
} else {
short revents = 0;
if((events & POLLOUT) != 0) {
revents = POLLOUT;
} else if ((events & POLLIN) != 0) {
revents = POLLIN;
}
pollfd.setShort(6, revents); // returned events
count++;
}
}
return count;
}
private int mask = 0x12;
private int umask(Emulator> emulator) {
Backend backend = emulator.getBackend();
int mask = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
if (log.isDebugEnabled()) {
log.debug("umask mask=0x" + Long.toHexString(mask));
}
int old = this.mask;
this.mask = mask;
return old;
}
private int setresuid32(Backend backend) {
int ruid = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int euid = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int suid = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
if (log.isDebugEnabled()) {
log.debug("setresuid32 ruid=" + ruid + ", euid=" + euid + ", suid=" + suid);
}
return 0;
}
private int setgid32(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int gid = context.getIntArg(0);
if (log.isDebugEnabled()) {
log.debug("setgid32 gid=" + gid);
}
return 0;
}
private int setresgid32(Backend backend) {
int rgid = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int egid = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int sgid = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
if (log.isDebugEnabled()) {
log.debug("setresgid32 rgid=" + rgid + ", egid=" + egid + ", sgid=" + sgid);
}
return 0;
}
private int mkdir(Emulator> emulator) {
Backend backend = emulator.getBackend();
Pointer pathname = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
int mode = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
if (log.isDebugEnabled()) {
log.debug("mkdir pathname=" + pathname.getString(0) + ", mode=" + mode);
}
emulator.getMemory().setErrno(UnixEmulator.EACCES);
return -1;
}
private int syslog(Backend backend, Emulator> emulator) {
int type = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer bufp = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int len = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
if (log.isDebugEnabled()) {
log.debug("syslog type=" + type + ", bufp=" + bufp + ", len=" + len);
}
throw new UnsupportedOperationException();
}
private int sigprocmask(Backend backend, Emulator> emulator) {
int how = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer set = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
Pointer oldset = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
return sigprocmask(emulator, how, set, oldset);
}
private int lgetxattr(Backend backend, Emulator> emulator) {
Pointer path = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
Pointer name = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
Pointer value = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
int size = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
if (log.isDebugEnabled()) {
log.debug("lgetxattr path=" + path.getString(0) + ", name=" + name.getString(0) + ", value=" + value + ", size=" + size);
}
throw new UnsupportedOperationException();
}
private int reboot(Backend backend, Emulator> emulator) {
int magic = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int magic2 = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int cmd = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
Pointer arg = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R3);
if (log.isDebugEnabled()) {
log.debug("reboot magic=" + magic + ", magic2=" + magic2 + ", cmd=" + cmd + ", arg=" + arg);
}
emulator.getMemory().setErrno(UnixEmulator.EPERM);
return -1;
}
private int nanosleep(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
Pointer req = context.getR0Pointer();
Pointer rem = context.getR1Pointer();
int tv_sec = req.getInt(0);
int tv_nsec = req.getInt(4);
if (log.isDebugEnabled()) {
log.debug("nanosleep req=" + req + ", rem=" + rem + ", tv_sec=" + tv_sec + ", tv_nsec=" + tv_nsec);
}
try {
java.lang.Thread.sleep(tv_sec * 1000L + tv_nsec / 1000000L);
} catch (InterruptedException ignored) {
}
return 0;
}
protected int kill(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int pid = context.getIntArg(0);
int sig = context.getIntArg(1);
if (log.isDebugEnabled()) {
log.debug("kill pid=" + pid + ", sig=" + sig);
}
throw new UnsupportedOperationException("kill pid=" + pid + ", sig=" + sig + ", LR=" + context.getLRPointer());
}
private int setitimer(Emulator> emulator) {
Arm32RegisterContext context = emulator.getContext();
int which = context.getR0Int();
Pointer new_value = context.getR1Pointer();
Pointer old_value = context.getR2Pointer();
if (log.isDebugEnabled()) {
log.debug("setitimer which=" + which + ", new_value=" + new_value + ", old_value=" + old_value);
}
return 0;
}
private int sigaction(Backend backend, Emulator> emulator) {
int signum = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer act = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
Pointer oldact = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
return sigaction(signum, act, oldact);
}
private int recvfrom(Emulator> emulator) {
Backend backend = emulator.getBackend();
int sockfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer buf = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int len = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
int flags = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
Pointer src_addr = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R4);
Pointer addrlen = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R5);
if (log.isDebugEnabled()) {
log.debug("recvfrom sockfd=" + sockfd + ", buf=" + buf + ", flags=" + flags + ", src_addr=" + src_addr + ", addrlen=" + addrlen);
}
FileIO file = fdMap.get(sockfd);
if (file == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
return file.recvfrom(backend, buf, len, flags, src_addr, addrlen);
}
private int sendto(Backend backend, Emulator> emulator) {
int sockfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer buf = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int len = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
int flags = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
Pointer dest_addr = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R4);
int addrlen = backend.reg_read(ArmConst.UC_ARM_REG_R5).intValue();
return sendto(emulator, sockfd, buf, len, flags, dest_addr, addrlen);
}
private int connect(Backend backend, Emulator> emulator) {
int sockfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer addr = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int addrlen = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
return connect(emulator, sockfd, addr, addrlen);
}
private int accept(Emulator emulator) {
RegisterContext context = emulator.getContext();
int sockfd = context.getIntArg(0);
Pointer addr = context.getPointerArg(1);
Pointer addrlen = context.getPointerArg(2);
return accept(emulator, sockfd, addr, addrlen, 0);
}
private int accept4(Emulator emulator) {
RegisterContext context = emulator.getContext();
int sockfd = context.getIntArg(0);
Pointer addr = context.getPointerArg(1);
Pointer addrlen = context.getPointerArg(2);
int flags = context.getIntArg(3);
return accept(emulator, sockfd, addr, addrlen, flags);
}
protected final int accept(Emulator emulator, int sockfd, Pointer addr, Pointer addrlen, int flags) {
if (log.isDebugEnabled()) {
log.debug("accept sockfd=" + sockfd + ", addr=" + addr + ", addrlen=" + addrlen + ", flags=" + flags);
}
AndroidFileIO file = fdMap.get(sockfd);
if (file == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
AndroidFileIO newIO = file.accept(addr, addrlen);
if (newIO == null) {
return -1;
} else {
int fd = getMinFd();
fdMap.put(fd, newIO);
return fd;
}
}
private int listen(Emulator emulator) {
RegisterContext context = emulator.getContext();
int sockfd = context.getIntArg(0);
int backlog = context.getIntArg(1);
return listen(emulator, sockfd, backlog);
}
private int bind(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int sockfd = context.getIntArg(0);
Pointer addr = context.getPointerArg(1);
int addrlen = context.getIntArg(2);
return bind(emulator, sockfd, addr, addrlen);
}
private int getsockname(Backend backend, Emulator> emulator) {
int sockfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer addr = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
Pointer addrlen = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
if (log.isDebugEnabled()) {
log.debug("getsockname sockfd=" + sockfd + ", addr=" + addr + ", addrlen=" + addrlen);
}
FileIO file = fdMap.get(sockfd);
if (file == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
return file.getsockname(addr, addrlen);
}
private int getsockopt(Backend backend, Emulator> emulator) {
int sockfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int level = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int optname = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
Pointer optval = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R3);
Pointer optlen = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R4);
if (log.isDebugEnabled()) {
log.debug("getsockopt sockfd=" + sockfd + ", level=" + level + ", optname=" + optname + ", optval=" + optval + ", optlen=" + optlen + ", from=" + UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_LR));
}
FileIO file = fdMap.get(sockfd);
if (file == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
return file.getsockopt(level, optname, optval, optlen);
}
private int setsockopt(Backend backend, Emulator> emulator) {
int sockfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int level = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int optname = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
Pointer optval = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R3);
int optlen = backend.reg_read(ArmConst.UC_ARM_REG_R4).intValue();
if (log.isDebugEnabled()) {
log.debug("setsockopt sockfd=" + sockfd + ", level=" + level + ", optname=" + optname + ", optval=" + optval + ", optlen=" + optlen);
}
FileIO file = fdMap.get(sockfd);
if (file == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
return file.setsockopt(level, optname, optval, optlen);
}
private int sdk;
@Override
public void addIOResolver(IOResolver resolver) {
super.addIOResolver(resolver);
if (resolver instanceof AndroidResolver) {
sdk = ((AndroidResolver) resolver).getSdk();
}
}
/**
* create AF_UNIX local SOCK_STREAM
*/
protected AndroidFileIO createLocalSocketIO(Emulator> emulator, int sdk) {
return new LocalSocketIO(emulator, sdk);
}
private int socket(Backend backend, Emulator> emulator) {
int domain = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int type = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue() & 0x7ffff;
int protocol = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
if (log.isDebugEnabled()) {
log.debug("socket domain=" + domain + ", type=" + type + ", protocol=" + protocol);
}
if (protocol == SocketIO.IPPROTO_ICMP) {
throw new UnsupportedOperationException();
}
int fd;
switch (domain) {
case SocketIO.AF_UNSPEC:
throw new UnsupportedOperationException();
case SocketIO.AF_LOCAL:
switch (type) {
case SocketIO.SOCK_STREAM:
fd = getMinFd();
fdMap.put(fd, createLocalSocketIO(emulator, sdk));
return fd;
case SocketIO.SOCK_DGRAM:
fd = getMinFd();
fdMap.put(fd, new LocalAndroidUdpSocket(emulator));
return fd;
default:
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;
}
log.warn("socket domain=" + domain + ", type=" + type + ", protocol=" + protocol);
emulator.getMemory().setErrno(UnixEmulator.EAFNOSUPPORT);
return -1;
}
private int getgroups(Backend backend, Emulator> emulator) {
int size = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer list = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
if (log.isDebugEnabled()) {
log.debug("getgroups size=" + size + ", list=" + list);
}
return 0;
}
protected int uname(Emulator> emulator) {
Pointer buf = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
if (log.isDebugEnabled()) {
log.debug("uname buf=" + buf);
}
final int SYS_NMLN = 65;
Pointer sysname = buf.share(0);
sysname.setString(0, "Linux");
Pointer nodename = sysname.share(SYS_NMLN);
nodename.setString(0, "localhost");
Pointer release = nodename.share(SYS_NMLN);
release.setString(0, "1.0.0-unidbg");
Pointer version = release.share(SYS_NMLN);
version.setString(0, "#1 SMP PREEMPT Thu Apr 19 14:36:58 CST 2018");
Pointer machine = version.share(SYS_NMLN);
machine.setString(0, "armv7l");
Pointer domainname = machine.share(SYS_NMLN);
domainname.setString(0, "");
return 0;
}
private int getcwd(Backend backend, Emulator> emulator) {
UnidbgPointer buf = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
int size = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
File workDir = emulator.getFileSystem().createWorkDir();
String path = workDir.getAbsolutePath();
if (log.isDebugEnabled()) {
log.debug("getcwd buf=" + buf + ", size=" + size + ", path=" + path);
}
buf.setString(0, ".");
return (int) buf.peer;
}
private void exit_group(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int status = context.getIntArg(0);
if (log.isDebugEnabled()) {
log.debug("exit with code: " + status, new Exception("exit_group status=" + status));
} else {
System.out.println("exit with code: " + status);
}
if (LogFactory.getLog(AbstractEmulator.class).isDebugEnabled()) {
createBreaker(emulator).debug();
}
emulator.getBackend().emu_stop();
}
private int munmap(Backend backend, Emulator> emulator) {
long timeInMillis = System.currentTimeMillis();
long start = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue() & 0xffffffffL;
int length = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int ret = emulator.getMemory().munmap(start, length);
if (log.isDebugEnabled()) {
log.debug("munmap start=0x" + Long.toHexString(start) + ", length=" + length + ", ret=" + ret + ", offset=" + (System.currentTimeMillis() - timeInMillis) + ", from=" + UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_LR));
}
return ret;
}
private static final int PR_GET_DUMPABLE = 3;
private static final int PR_SET_DUMPABLE = 4;
private static final int PR_SET_NAME = 15;
private static final int PR_GET_NAME = 16;
private static final int BIONIC_PR_SET_VMA = 0x53564d41;
private static final int PR_SET_PTRACER = 0x59616d61;
private int prctl(Backend backend, Emulator> emulator) {
int option = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
long arg2 = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue() & 0xffffffffL;
if (log.isDebugEnabled()) {
log.debug("prctl option=0x" + Integer.toHexString(option) + ", arg2=0x" + Long.toHexString(arg2));
}
switch (option) {
case PR_GET_DUMPABLE:
case PR_SET_DUMPABLE:
return 0;
case PR_SET_NAME: {
Pointer threadName = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
String name = threadName.getString(0);
if (log.isDebugEnabled()) {
log.debug("prctl set thread name: " + name);
}
return 0;
}
case PR_GET_NAME: {
String name = Thread.currentThread().getName();
if (name.length() > 15) {
name = name.substring(0, 15);
}
if (log.isDebugEnabled()) {
log.debug("prctl get thread name: " + name);
}
Pointer buffer = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
buffer.setString(0, name);
return 0;
}
case BIONIC_PR_SET_VMA:
Pointer addr = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
int len = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
Pointer pointer = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R4);
if (log.isDebugEnabled()) {
log.debug("prctl set vma addr=" + addr + ", len=" + len + ", pointer=" + pointer + ", name=" + pointer.getString(0));
}
return 0;
case PR_SET_PTRACER:
int pid = (int) arg2;
if (log.isDebugEnabled()) {
log.debug("prctl set ptracer: " + pid);
}
return 0;
}
throw new UnsupportedOperationException("option=" + option);
}
private static final int CLOCK_REALTIME = 0;
private static final int CLOCK_MONOTONIC = 1;
private static final int CLOCK_MONOTONIC_RAW = 4;
private static final int CLOCK_MONOTONIC_COARSE = 6;
private static final int CLOCK_BOOTTIME = 7;
private final long nanoTime = System.nanoTime();
private int clock_gettime(Backend backend, Emulator> emulator) {
int clk_id = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer tp = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
long offset = clk_id == CLOCK_REALTIME ? System.currentTimeMillis() * 1000000L : System.nanoTime() - nanoTime;
long tv_sec = offset / 1000000000L;
long tv_nsec = offset % 1000000000L;
if (log.isDebugEnabled()) {
log.debug("clock_gettime clk_id=" + clk_id + ", tp=" + tp + ", offset=" + offset + ", tv_sec=" + tv_sec + ", tv_nsec=" + tv_nsec);
}
switch (clk_id) {
case CLOCK_REALTIME:
case CLOCK_MONOTONIC:
case CLOCK_MONOTONIC_RAW:
case CLOCK_MONOTONIC_COARSE:
case CLOCK_BOOTTIME:
tp.setInt(0, (int) tv_sec);
tp.setInt(4, (int) tv_nsec);
return 0;
}
throw new UnsupportedOperationException("clk_id=" + clk_id);
}
private int fcntl(Backend backend, Emulator> emulator) {
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int cmd = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int arg = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
return fcntl(emulator, fd, cmd, arg);
}
private int writev(Backend backend, Emulator> emulator) {
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer iov = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int iovcnt = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
if (log.isDebugEnabled()) {
for (int i = 0; i < iovcnt; i++) {
Pointer iov_base = iov.getPointer(i * 8);
int iov_len = iov.getInt(i * 8 + 4);
byte[] data = iov_base.getByteArray(0, iov_len);
Inspector.inspect(data, "writev fd=" + fd + ", iov=" + iov + ", iov_base=" + iov_base);
}
}
FileIO file = fdMap.get(fd);
if (file == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
int count = 0;
for (int i = 0; i < iovcnt; i++) {
Pointer iov_base = iov.getPointer(i * 8);
int iov_len = iov.getInt(i * 8 + 4);
byte[] data = iov_base.getByteArray(0, iov_len);
count += file.write(data);
}
return count;
}
private static final int FUTEX_WAIT = 0;
private static final int FUTEX_WAKE = 1;
private int futex(Emulator> emulator) {
RegisterContext context = emulator.getContext();
Pointer uaddr = context.getPointerArg(0);
int futex_op = context.getIntArg(1);
int val = context.getIntArg(2);
int old = uaddr.getInt(0);
if (log.isDebugEnabled()) {
log.debug("futex uaddr=" + uaddr + ", _futexop=" + futex_op + ", op=" + (futex_op & 0x7f) + ", val=" + val + ", old=" + old);
}
switch (futex_op & 0x7f) {
case FUTEX_WAIT:
if (old != val) {
throw new IllegalStateException("old=" + old + ", val=" + val);
}
Thread.yield();
Pointer timeout = context.getPointerArg(3);
int mytype = val & 0xc000;
int shared = val & 0x2000;
if (log.isDebugEnabled()) {
log.debug("futex FUTEX_WAIT mytype=" + mytype + ", shared=" + shared + ", timeout=" + timeout + ", test=" + (mytype | shared));
}
uaddr.setInt(0, mytype | shared);
return 0;
case FUTEX_WAKE:
return 0;
default:
throw new AbstractMethodError();
}
}
private int brk(Emulator> emulator) {
Backend backend = emulator.getBackend();
long address = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue() & 0xffffffffL;
if (log.isDebugEnabled()) {
log.debug("brk address=0x" + Long.toHexString(address));
}
return emulator.getMemory().brk(address);
}
private int mprotect(Backend backend, Emulator> emulator) {
long address = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue() & 0xffffffffL;
int length = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int prot = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
long alignedAddress = address / ARMEmulator.PAGE_ALIGN * ARMEmulator.PAGE_ALIGN; // >> 12 << 12;
long offset = address - alignedAddress;
long alignedLength = ARM.alignSize(length + offset, emulator.getPageAlign());
if (log.isDebugEnabled()) {
log.debug("mprotect address=0x" + Long.toHexString(address) + ", alignedAddress=0x" + Long.toHexString(alignedAddress) + ", offset=" + offset + ", length=" + length + ", alignedLength=" + alignedLength + ", prot=0x" + Integer.toHexString(prot));
}
return emulator.getMemory().mprotect(alignedAddress, (int) alignedLength, prot);
}
private static final int MMAP2_SHIFT = 12;
private int mmap2(Backend backend, Emulator> emulator) {
long start = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue() & 0xffffffffL;
int length = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int prot = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
int flags = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R4).intValue();
int offset = backend.reg_read(ArmConst.UC_ARM_REG_R5).intValue() << MMAP2_SHIFT;
boolean warning = length >= 0x10000000;
if (log.isDebugEnabled() || warning) {
String msg = "mmap2 start=0x" + Long.toHexString(start) + ", length=" + length + ", prot=0x" + Integer.toHexString(prot) + ", flags=0x" + Integer.toHexString(flags) + ", fd=" + fd + ", offset=" + offset + ", from=" + UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_LR);
if (warning) {
log.warn(msg);
} else {
log.debug(msg);
}
}
return (int) emulator.getMemory().mmap2(start, length, prot, flags, fd, offset);
}
private int gettimeofday(Emulator> emulator) {
Pointer tv = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
Pointer tz = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
return gettimeofday(emulator, tv, tz);
}
private int faccessat(Backend backend, Emulator emulator) {
int dirfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer pathname_p = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int oflags = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
int mode = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
String pathname = pathname_p.getString(0);
String msg = "faccessat dirfd=" + dirfd + ", pathname=" + pathname + ", oflags=0x" + Integer.toHexString(oflags) + ", mode=" + Integer.toHexString(mode);
if (log.isDebugEnabled()) {
log.debug(msg);
}
int ret = faccessat(emulator, pathname);
if (ret == -1) {
log.info(msg);
}
return ret;
}
private int faccessat(Emulator emulator, String pathname) {
FileResult> result = resolve(emulator, pathname, IOConstants.O_RDONLY);
if (result != null && result.isSuccess()) {
return 0;
}
emulator.getMemory().setErrno(result != null ? result.errno : UnixEmulator.EACCES);
return -1;
}
private int fstatat64(Backend backend, Emulator emulator) {
int dirfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer pathname = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
Pointer statbuf = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R2);
int flags = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
String path = FilenameUtils.normalize(pathname.getString(0), true);
if (log.isDebugEnabled()) {
log.debug("fstatat64 dirfd=" + dirfd + ", pathname=" + path + ", statbuf=" + statbuf + ", flags=" + flags);
}
if (dirfd != IO.AT_FDCWD && !path.startsWith("/")) {
throw new BackendException();
}
return stat64(emulator, path, statbuf);
}
private int mkdirat(Backend backend, Emulator> emulator) {
int dirfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer pathname_p = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int mode = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
String pathname = pathname_p.getString(0);
if (log.isDebugEnabled()) {
log.debug("mkdirat dirfd=" + dirfd + ", pathname=" + pathname + ", mode=" + Integer.toHexString(mode));
}
emulator.getMemory().setErrno(UnixEmulator.EACCES);
return -1;
}
private int openat(Backend backend, Emulator emulator) {
int dirfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer pathname_p = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int oflags = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
int mode = backend.reg_read(ArmConst.UC_ARM_REG_R3).intValue();
String pathname = pathname_p.getString(0);
String msg = "openat dirfd=" + dirfd + ", pathname=" + pathname + ", oflags=0x" + Integer.toHexString(oflags) + ", mode=" + Integer.toHexString(mode);
if (log.isDebugEnabled()) {
log.debug(msg);
}
pathname = FilenameUtils.normalize(pathname, true);
if ("/data/misc/zoneinfo/current/tzdata".equals(pathname) || "/dev/pmsg0".equals(pathname)) {
emulator.getMemory().setErrno(UnixEmulator.ENOENT);
return -1;
}
if (pathname.startsWith("/")) {
int fd = open(emulator, pathname, oflags);
if (fd == -1) {
emulator.getMemory().setErrno(UnixEmulator.ENOENT);
log.info(msg);
}
return fd;
} else {
if (dirfd != IO.AT_FDCWD) {
throw new BackendException();
}
log.warn(msg);
emulator.getMemory().setErrno(UnixEmulator.ENOENT);
return -1;
}
}
private int open(Emulator emulator) {
Backend backend = emulator.getBackend();
Pointer pathname_p = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
int oflags = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int mode = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
String pathname = pathname_p.getString(0);
String msg = "open pathname=" + pathname + ", oflags=0x" + Integer.toHexString(oflags) + ", mode=" + Integer.toHexString(mode) + ", from=" + UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_LR);
if (log.isDebugEnabled()) {
log.debug(msg);
}
int fd = open(emulator, pathname, oflags);
if (fd == -1) {
log.info(msg);
}
return fd;
}
private int ftruncate(Backend backend) {
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int length = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
if (log.isDebugEnabled()) {
log.debug("ftruncate fd=" + fd + ", length=" + length);
}
FileIO file = fdMap.get(fd);
if (file == null) {
throw new UnsupportedOperationException();
}
return file.ftruncate(length);
}
private int lseek(Emulator> emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int offset = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
int whence = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
FileIO file = fdMap.get(fd);
if (file == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
int pos = file.lseek(offset, whence);
if (log.isDebugEnabled()) {
log.debug("lseek fd=" + fd + ", offset=" + offset + ", whence=" + whence + ", pos=" + pos + ", from=" + UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_LR));
}
return pos;
}
private int close(Emulator> emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
if (log.isDebugEnabled()) {
log.debug("close fd=" + fd);
}
return close(emulator, fd);
}
private int getdents64(Emulator emulator) {
RegisterContext context = emulator.getContext();
int fd = context.getIntArg(0);
UnidbgPointer dirp = context.getPointerArg(1);
int size = context.getIntArg(2);
if (log.isDebugEnabled()) {
log.debug("getdents64 fd=" + fd + ", dirp=" + dirp + ", size=" + size);
}
AndroidFileIO io = fdMap.get(fd);
if (io == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
} else {
dirp.setSize(size);
return io.getdents64(dirp, size);
}
}
private int fstat(Backend backend, Emulator> emulator) {
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer stat = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
return fstat(emulator, fd, stat);
}
protected int fstat(Emulator> emulator, int fd, Pointer stat) {
AndroidFileIO file = fdMap.get(fd);
if (file == null) {
if (log.isDebugEnabled()) {
log.debug("fstat fd=" + fd + ", stat=" + stat + ", errno=" + UnixEmulator.EBADF);
}
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
if (log.isDebugEnabled()) {
log.debug("fstat file=" + file + ", stat=" + stat + ", from=" + emulator.getContext().getLRPointer());
}
return file.fstat(emulator, new Stat32(stat));
}
private int ioctl(Emulator> emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
long request = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue() & 0xffffffffL;
long argp = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue() & 0xffffffffL;
if (log.isDebugEnabled()) {
log.debug("ioctl fd=" + fd + ", request=0x" + Long.toHexString(request) + ", argp=0x" + Long.toHexString(argp));
}
FileIO file = fdMap.get(fd);
if (file == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
int ret = file.ioctl(emulator, request, argp);
if (ret == -1) {
emulator.getMemory().setErrno(UnixEmulator.ENOTTY);
}
return ret;
}
private int write(Emulator> emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer buffer = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int count = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
return write(emulator, fd, buffer, count);
}
private int read(Emulator> emulator) {
Backend backend = emulator.getBackend();
int fd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
Pointer buffer = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_R1);
int count = backend.reg_read(ArmConst.UC_ARM_REG_R2).intValue();
return read(emulator, fd, buffer, count);
}
private int dup2(Backend backend, Emulator> emulator) {
int oldfd = backend.reg_read(ArmConst.UC_ARM_REG_R0).intValue();
int newfd = backend.reg_read(ArmConst.UC_ARM_REG_R1).intValue();
if (log.isDebugEnabled()) {
log.debug("dup2 oldfd=" + oldfd + ", newfd=" + newfd);
}
FileIO old = fdMap.get(oldfd);
if (old == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
if (oldfd == newfd) {
return newfd;
}
AndroidFileIO _new = fdMap.remove(newfd);
if (_new != null) {
_new.close();
}
_new = (AndroidFileIO) old.dup2();
fdMap.put(newfd, _new);
return newfd;
}
private int dup3(Emulator> emulator) {
RegisterContext context = emulator.getContext();
int oldfd = context.getIntArg(0);
int newfd = context.getIntArg(1);
int flags = context.getIntArg(2);
if (log.isDebugEnabled()) {
log.debug("dup3 oldfd=" + oldfd + ", newfd=" + newfd + ", flags=0x" + Integer.toHexString(flags));
}
FileIO old = fdMap.get(oldfd);
if (old == null) {
emulator.getMemory().setErrno(UnixEmulator.EBADF);
return -1;
}
if (oldfd == newfd) {
return newfd;
}
AndroidFileIO _new = fdMap.remove(newfd);
if (_new != null) {
_new.close();
}
_new = (AndroidFileIO) old.dup2();
fdMap.put(newfd, _new);
return newfd;
}
@Override
protected AndroidFileIO createByteArrayFileIO(String pathname, int oflags, byte[] data) {
return new ByteArrayFileIO(oflags, pathname, data);
}
@Override
protected AndroidFileIO createDriverFileIO(Emulator> emulator, int oflags, String pathname) {
return DriverFileIO.create(emulator, oflags, pathname);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy