Reverse Debugging with ReplayEngine : Using ReplayEngine : Known Limitations and Issues
Known Limitations and Issues
Limitations
*Obscure instructions: Use of AMD 3DNow! and other extended AMD instructions is not supported (though Intel SSE, SSE2, SSE3 and SSE4 instructions are supported). Instructions that modify CS, DS, ES or SS registers are also not supported.
*AsyncIO: ReplayEngine does not support asynchronous IO operations. io_cancel, io_destroy, io_getevents, ioperm, iopl, io_setup, and io_submit system calls are all unsupported.
*Exec: ReplayEngine does not support the execve syscall, as used by libc's execl(), execlp(), execle(), execv(), execvp(), and execve() functions. If the target program attempts to issue this system call, forward execution will not be possible beyond this point (though reverse execution is still possible).
*Obscure system calls: Certain rarely used system calls are not supported. If the target program attempts to issue an unsupported system call, forward execution will not be possible beyond this point (though reverse execution is still possible). The following system calls are either esoteric or obsolete, and only maintained in the kernel for backward compatibility with binaries written for early 2.x series kernels: ssetmask, modify_ldt, pivot_root, vm86, and unshare.
*Use of setrlimit(): If the target program uses setrlimit to reduce the amount of memory, processes, or other resources consumed, ReplayEngine may not be able to operate properly due to lack of resources.
*Use of x86 inter-segment (aka 'far') jumps/calls: ReplayEngine does not support the use of far jumps/calls in the target program. Any such attempt will result in forward execution not being able to continue from the point at which the far jump/call instruction is issued.
*Non-executable memory: ReplayEngine ignores the executable status of memory when running code, so code that would usually fail because it is in non-executable memory will run successfully.
*Disk usage: Depending on the target program, ReplayEngine can create large temporary files within /tmp. See System Resources ReplayEngine Uses” for information on how to use alternative temporary directories.
*Statically-linked target programs: ReplayEngine cannot start a statically-linked target program. However, it can attach to an existing statically-linked target program process.
*Self-modifying code: Self-modifying code is supported as long as the target program executes at least one branch instruction between the writing of the code and its execution.
*Shared memory accesses straddling valid and invalid pages: Accessing shared memory where the instruction's operand straddles a page boundary such that the first part of the operand is in accessible shared memory, but the second part is in mapped shared memory which is not backed by a valid shared object (e.g. because the file which is mapped has been truncated) should receive signal SIGBUS. Under ReplayEngine, a target program making such an access will not receive SIGBUS but will read zeroes for the part of the operand that straddles into unbacked memory. Note that normal attempted access to shared memory not backed by a shared object will generate a SIGBUS as normal; the issue is only with a single instruction's access that lies half in valid memory and half in invalid memory that should generate a SIGBUS.
*Breakpoints: All breakpoints used with ReplayEngine work like hardware breakpoints. In particular, if the code where the breakpoint resides is not modified, writing to that code will not remove the breakpoint, and setting a breakpoint that is not at the first byte of an instruction will have no effect.
*System call output buffers: Any system calls that write to memory must be passed a buffer entirely within writable memory. For example, if read() is passed an 8k buffer of which only the first 4k is in user-writable memory, if that read() would normally return 4k or fewer characters then natively it may succeed, but on ReplayEngine it will fail with EFAULT. If a system call that writes to memory is passed a buffer which is not in writable memory at all, but fails for some other reason before the kernel tries to write to the buffer, then natively it may fail with some error other than EFAULT, but on ReplayEngine it may fail with EFAULT. If two buffers which overlap are passed to a system call which writes to both of them or reads from one and writes to the other, the behavior in ReplayEngine may differ from the native behavior (although behavior in such cases is liable to vary between kernel versions, too.)
*Adjust Flag: According to the Intel manuals, the state of the Adjust Flag (AF) after some instructions is "undefined." On some processor models, different executions of the same code can produce different states of AF. If the behavior of a program depends on the state of AF when it is supposed to be undefined, the program may not run correctly with ReplayEngine.
*SIGCHLD while attaching: If a SIGCHLD arrives for a process while ReplayEngine is in the middle of attaching to the process, the SIGCHLD may be silently lost. Once the process has been attached to, SIGCHLD is handled normally.