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).
• Fork: ReplayEngine does not follow fork() or vfork() system calls.
• 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.
• Self-modifying code: ReplayEngine mostly works with self-modifying code, but in some situations the effects of writing into the currently executing “basic block” may be delayed (that is, writing instructions just ahead of the current program counter such that the processor executes the newly written code by virtue of “running in to” rather than “jumping to” it).
• 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 zeros 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 applies only when 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.
• Loading a previous recording session: The successful reloading and debugging of a previously saved replay recording session requires that both the environment that saved the session and the environment replaying the recording session be exactly the same.