├── .android ├── Dockerfile ├── README.md └── build.sh ├── .buildkite ├── .gitignore ├── CTestCostData.txt ├── Manifest.toml ├── Project.toml ├── capture_tmpdir.jl ├── lib │ ├── common.jl │ ├── generate.jl │ ├── launch.jl │ └── types.jl └── pipeline.yml ├── .clang-format ├── .github └── workflows │ ├── android-build.yml │ ├── build-and-test-main.yml │ └── build-and-test.yml ├── .gitignore ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── Vagrantfile ├── configure ├── include └── rr │ └── rr.h ├── release-process ├── README.md ├── distro-configs │ ├── centos9.json │ ├── debian11.json │ ├── debian12.json │ ├── ubuntu20-lts.json │ ├── ubuntu22-lts.json │ ├── ubuntu24-lts.json │ └── ubuntu24.10.json ├── prepare-release.py ├── rr-testing-cloud-formation.json ├── rr-testing.sh ├── test-data │ ├── rr-test-doc.odt │ └── test.html └── test-system.py ├── rr.spec ├── scripts ├── checkpoint-visualizer.html ├── github-actions-CTestCostData.txt ├── github-actions-build.sh ├── github-actions-test.sh ├── reformat.sh ├── rr-collect-symbols.py ├── rr-gdb-script-host.py ├── rr_completion ├── rr_completion.zsh ├── signal-rr-recording.sh ├── update-gh-pages.sh ├── zen_workaround.py └── zen_workaround.service ├── snap └── snapcraft.yaml ├── src ├── AddressSpace.cc ├── AddressSpace.h ├── AutoRemoteSyscalls.cc ├── AutoRemoteSyscalls.h ├── BpfMapMonitor.h ├── BreakpointCondition.h ├── BuildidCommand.cc ├── CPUFeaturesCommand.cc ├── CPUIDBugDetector.cc ├── CPUIDBugDetector.h ├── Command.cc ├── Command.h ├── CompressedReader.cc ├── CompressedReader.h ├── CompressedWriter.cc ├── CompressedWriter.h ├── ContextSwitchEvent.cc ├── ContextSwitchEvent.h ├── DebuggerExtensionCommand.cc ├── DebuggerExtensionCommand.h ├── DebuggerExtensionCommandHandler.cc ├── DebuggerExtensionCommandHandler.h ├── DiversionSession.cc ├── DiversionSession.h ├── DumpCommand.cc ├── DumpCommand.h ├── Dwarf.cc ├── Dwarf.h ├── ElfReader.cc ├── ElfReader.h ├── EmuFs.cc ├── EmuFs.h ├── Event.cc ├── Event.h ├── ExportImportCheckpoints.cc ├── ExportImportCheckpoints.h ├── ExtraRegisters.cc ├── ExtraRegisters.h ├── FdTable.cc ├── FdTable.h ├── FileMonitor.cc ├── FileMonitor.h ├── FileNameCommand.cc ├── Flags.cc ├── Flags.h ├── GdbInitCommand.cc ├── GdbServer.cc ├── GdbServer.h ├── GdbServerConnection.cc ├── GdbServerConnection.h ├── GdbServerExpression.cc ├── GdbServerExpression.h ├── GdbServerRegister.h ├── HasTaskSet.cc ├── HasTaskSet.h ├── HelpCommand.cc ├── LldbInitCommand.cc ├── LsCommand.cc ├── MagicSaveDataMonitor.cc ├── MagicSaveDataMonitor.h ├── MemoryRange.h ├── MmappedFileMonitor.cc ├── MmappedFileMonitor.h ├── MonitoredSharedMemory.cc ├── MonitoredSharedMemory.h ├── Monkeypatcher.cc ├── Monkeypatcher.h ├── MvCommand.cc ├── NonvirtualPerfCounterMonitor.h ├── ODirectFileMonitor.h ├── PackCommand.cc ├── PerfCounterBuffers.cc ├── PerfCounterBuffers.h ├── PerfCounters.cc ├── PerfCounters.h ├── PerfCounters_aarch64.h ├── PerfCounters_x86.h ├── PidFdMonitor.cc ├── PidFdMonitor.h ├── PreserveFileMonitor.h ├── ProcFdDirMonitor.cc ├── ProcFdDirMonitor.h ├── ProcMemMonitor.cc ├── ProcMemMonitor.h ├── ProcStatMonitor.cc ├── ProcStatMonitor.h ├── ProcessorTraceDecoder.cc ├── ProcessorTraceDecoder.h ├── PsCommand.cc ├── RRPageMonitor.h ├── RecordCommand.cc ├── RecordCommand.h ├── RecordSession.cc ├── RecordSession.h ├── RecordTask.cc ├── RecordTask.h ├── Registers.cc ├── Registers.h ├── ReplayCommand.cc ├── ReplayCommand.h ├── ReplaySession.cc ├── ReplaySession.h ├── ReplayTask.cc ├── ReplayTask.h ├── ReplayTimeline.cc ├── ReplayTimeline.h ├── RerunCommand.cc ├── ReturnAddressList.cc ├── ReturnAddressList.h ├── RmCommand.cc ├── Scheduler.cc ├── Scheduler.h ├── ScopedFd.h ├── SeccompFilterRewriter.cc ├── SeccompFilterRewriter.h ├── Session.cc ├── Session.h ├── SourcesCommand.cc ├── StdioMonitor.cc ├── StdioMonitor.h ├── StringVectorToCharArray.h ├── SysCpuMonitor.cc ├── SysCpuMonitor.h ├── TargetDescription.cc ├── TargetDescription.h ├── Task.cc ├── Task.h ├── TaskishUid.h ├── ThreadDb.cc ├── ThreadDb.h ├── ThreadGroup.cc ├── ThreadGroup.h ├── Ticks.h ├── TraceField.cc ├── TraceField.h ├── TraceFrame.cc ├── TraceFrame.h ├── TraceInfoCommand.cc ├── TraceStream.cc ├── TraceStream.h ├── TraceTaskEvent.h ├── TraceeAttentionSet.cc ├── TraceeAttentionSet.h ├── VirtualPerfCounterMonitor.cc ├── VirtualPerfCounterMonitor.h ├── WaitManager.cc ├── WaitManager.h ├── WaitStatus.cc ├── WaitStatus.h ├── assembly_templates.py ├── audit │ ├── rtld-audit.c │ ├── rtld-audit.h │ ├── stap-note-iter.c │ └── stap-note-iter.h ├── bpf │ └── async_event_filter.c ├── chaos-test │ ├── chaos-test.sh │ ├── chaosutil.h │ ├── core_count.c │ ├── futex_wakeup.c │ ├── getaffinity_core_count.c │ ├── harness.py │ ├── mmap_adjacent.c │ ├── mmap_bits.c │ ├── pipe_wakeup.c │ ├── startup.c │ ├── starvation_multithreaded.c │ └── starvation_singlethreaded.c ├── core.h ├── counters-test │ ├── README.md │ └── counters.cc ├── cpp_supplement.h ├── exec_stub.c ├── extra_version_string.h.in ├── fast_forward.cc ├── fast_forward.h ├── ftrace.cc ├── ftrace.h ├── ftrace │ └── ftrace_helper.c ├── generate_syscalls.py ├── git_revision.h.in ├── kernel_abi.cc ├── kernel_abi.h ├── kernel_metadata.cc ├── kernel_metadata.h ├── kernel_supplement.h ├── launch_debugger.cc ├── launch_debugger.h ├── log.cc ├── log.h ├── main.cc ├── main.h ├── perf-test │ ├── many-threads-wake.c │ ├── many-threads-wake.md │ ├── many-threads.c │ ├── many-threads.md │ ├── unbuffered-syscalls.c │ └── unbuffered-syscalls.md ├── preload │ ├── overrides.c │ ├── preload_interface.h │ ├── raw_syscall.S │ ├── rr_page.S │ ├── rr_page.ld.in │ ├── rr_page_instructions.S │ ├── rr_vdso.S │ ├── rrcalls.h │ ├── syscall_hook.S │ ├── syscallbuf.c │ ├── syscallbuf.h │ └── tweak_librrpage.py ├── processor_trace_check.cc ├── processor_trace_check.h ├── record_signal.cc ├── record_signal.h ├── record_syscall.cc ├── record_syscall.h ├── remote_code_ptr.cc ├── remote_code_ptr.h ├── remote_ptr.h ├── replay_syscall.cc ├── replay_syscall.h ├── rr_trace.capnp ├── seccomp-bpf.h ├── syscalls.py ├── test-monitor │ └── test-monitor.cc ├── test │ ├── 64bit_child.c │ ├── _llseek.c │ ├── abort.c │ ├── abort_nonmain.c │ ├── abort_nonmain.run │ ├── accept.c │ ├── acct.c │ ├── adjtimex.c │ ├── aio.c │ ├── alarm.c │ ├── alarm2.c │ ├── alsa_ioctl.c │ ├── alternate_thread_diversion.c │ ├── alternate_thread_diversion.py │ ├── alternate_thread_diversion.run │ ├── args.c │ ├── args.run │ ├── arm │ │ ├── arch_timer.c │ │ ├── arch_timer.run │ │ ├── brk_nonzero.c │ │ ├── diversion_arch_timer.py │ │ ├── tagged_addr_ctrl.c │ │ ├── util.h │ │ ├── util.py │ │ └── util.sh │ ├── async_kill_with_syscallbuf.c │ ├── async_kill_with_syscallbuf.run │ ├── async_kill_with_syscallbuf2.c │ ├── async_kill_with_syscallbuf2.run │ ├── async_kill_with_threads.c │ ├── async_kill_with_threads.run │ ├── async_kill_with_threads_main_running.c │ ├── async_kill_with_threads_main_running.run │ ├── async_kill_with_threads_thread_running.c │ ├── async_kill_with_threads_thread_running.run │ ├── async_segv.c │ ├── async_segv.run │ ├── async_segv_ignored.c │ ├── async_signal_syscalls.c │ ├── async_signal_syscalls.run │ ├── async_signal_syscalls2.c │ ├── async_signal_syscalls2.run │ ├── async_signal_syscalls_100.run │ ├── async_signal_syscalls_1000.run │ ├── async_signal_syscalls_siginfo.c │ ├── async_signal_syscalls_siginfo.run │ ├── async_usr1.c │ ├── async_usr1.run │ ├── at_threadexit.c │ ├── bad_breakpoint.run │ ├── bad_good_break.py │ ├── bad_ip.c │ ├── bad_syscall.c │ ├── barrier.c │ ├── basic_test.run │ ├── big_buffers.c │ ├── big_select.c │ ├── blacklist.c │ ├── blacklist.run │ ├── block.c │ ├── block_clone_checkpoint.c │ ├── block_clone_checkpoint.py │ ├── block_clone_checkpoint.run │ ├── block_clone_interrupted.c │ ├── block_clone_interrupted.run │ ├── block_clone_syscallbuf_overflow.c │ ├── block_clone_syscallbuf_overflow.run │ ├── block_intr_sigchld.c │ ├── block_intr_sigchld.run │ ├── block_open.c │ ├── blocked_bad_ip.c │ ├── blocked_bad_ip.py │ ├── blocked_bad_ip.run │ ├── blocked_sigill.c │ ├── blocked_sigill.run │ ├── bpf.c │ ├── bpf_map.c │ ├── bpf_prog_map.c │ ├── bpf_query.c │ ├── break_block.py │ ├── break_block.run │ ├── break_clock.py │ ├── break_clock.run │ ├── break_clone.py │ ├── break_clone.run │ ├── break_exec.run │ ├── break_int3.py │ ├── break_int3.run │ ├── break_mmap_private.py │ ├── break_mmap_private.run │ ├── break_msg.run │ ├── break_sigreturn.run │ ├── break_sync_signal.run │ ├── break_thread.run │ ├── break_time_slice.py │ ├── break_time_slice.run │ ├── breakpoint.c │ ├── breakpoint.py │ ├── breakpoint.run │ ├── breakpoint_conditions.c │ ├── breakpoint_conditions.py │ ├── breakpoint_conditions.run │ ├── breakpoint_consistent.py │ ├── breakpoint_consistent.run │ ├── breakpoint_overlap.c │ ├── breakpoint_overlap.py │ ├── breakpoint_overlap.run │ ├── breakpoint_print.py │ ├── breakpoint_print.run │ ├── breakpoint_print_command.py │ ├── breakpoint_print_command.run │ ├── brk.c │ ├── brk2.c │ ├── call_exit.py │ ├── call_exit.run │ ├── call_function.c │ ├── call_function.py │ ├── call_function.run │ ├── call_gettid.c │ ├── call_gettid.py │ ├── call_gettid.run │ ├── capget.c │ ├── chaos_oom.c │ ├── chaos_oom.run │ ├── check_lost_interrupts.c │ ├── check_lost_interrupts.run │ ├── check_patched_pthread.py │ ├── check_patched_pthread.run │ ├── check_session_leaks.c │ ├── check_session_leaks.py │ ├── check_session_leaks.run │ ├── check_syscall_perf_interval.py │ ├── checkpoint_async_signal_syscalls_1000.run │ ├── checkpoint_dying_threads.c │ ├── checkpoint_dying_threads.py │ ├── checkpoint_dying_threads.run │ ├── checkpoint_invalid.py │ ├── checkpoint_invalid.run │ ├── checkpoint_mixed_mode.c │ ├── checkpoint_mixed_mode.py │ ├── checkpoint_mixed_mode.run │ ├── checkpoint_mmap_shared.run │ ├── checkpoint_prctl_name.run │ ├── checkpoint_simple.run │ ├── checksum_block_open.run │ ├── checksum_sanity.c │ ├── checksum_sanity.run │ ├── checksum_sanity_noclone.run │ ├── chew_cpu.c │ ├── chmod.c │ ├── chown.c │ ├── clock.c │ ├── clock_adjtime.c │ ├── clock_nanosleep.c │ ├── clock_time64.c │ ├── clone.c │ ├── clone_bad_stack.c │ ├── clone_bad_tls.c │ ├── clone_cleartid_coredump.c │ ├── clone_fail.c │ ├── clone_file_range.c │ ├── clone_file_range.run │ ├── clone_immediate_exit.c │ ├── clone_interruption.c │ ├── clone_interruption.py │ ├── clone_interruption.run │ ├── clone_interruption_finder.py │ ├── clone_newflags.c │ ├── clone_parent.c │ ├── clone_share_vm.c │ ├── clone_share_vm.py │ ├── clone_share_vm.run │ ├── clone_syscallbuf_cleanup_blocked.c │ ├── clone_syscallbuf_cleanup_blocked.run │ ├── clone_syscallbuf_cleanup_cpu.c │ ├── clone_syscallbuf_cleanup_cpu.run │ ├── clone_untraced.c │ ├── clone_vfork.c │ ├── clone_vfork.run │ ├── clone_vfork_pidfd.c │ ├── cloned_sigmask.c │ ├── close_range.c │ ├── comm.py │ ├── comm.run │ ├── concurrent_signals.c │ ├── concurrent_signals.run │ ├── conditional_breakpoint_calls.c │ ├── conditional_breakpoint_calls.py │ ├── conditional_breakpoint_calls.run │ ├── conditional_breakpoint_offload.c │ ├── conditional_breakpoint_offload.py │ ├── conditional_breakpoint_offload.run │ ├── condvar_stress.c │ ├── condvar_stress.run │ ├── constructor.c │ ├── cont_race.c │ ├── cont_race.run │ ├── cont_signal.py │ ├── cont_signal.run │ ├── context_switch_after_patch.c │ ├── context_switch_after_patch.run │ ├── copy_all.py │ ├── copy_all.run │ ├── copy_file_range.c │ ├── crash.c │ ├── crash.run │ ├── crash_in_function.c │ ├── crash_in_function.py │ ├── crash_in_function.run │ ├── creat_address_not_truncated.c │ ├── cwd_inaccessible.c │ ├── daemon.c │ ├── daemon_read.c │ ├── daemon_read.run │ ├── dconf_mock.c │ ├── dconf_mock.run │ ├── dead_thread_target.py │ ├── dead_thread_target.run │ ├── deliver_async_signal_during_syscalls.run │ ├── desched_blocking_poll.c │ ├── desched_sigkill.c │ ├── desched_ticks.py │ ├── desched_ticks.run │ ├── detach_huge_mmap.c │ ├── detach_sigkill.c │ ├── detach_sigkill_exit.c │ ├── detach_state.c │ ├── detach_terminal.c │ ├── detach_terminal.run │ ├── detach_threads.c │ ├── deterministic_sigsys.c │ ├── dev_tty.c │ ├── dev_tty.run │ ├── dev_zero.c │ ├── direct.c │ ├── diversion_sigtrap.c │ ├── diversion_sigtrap.py │ ├── diversion_sigtrap.run │ ├── diversion_syscall.c │ ├── diversion_syscall.py │ ├── diversion_syscall.run │ ├── dlchecksum.c │ ├── dlopen.c │ ├── dlopen.py │ ├── dlopen.run │ ├── doublesegv.c │ ├── dup.c │ ├── early_error.c │ ├── early_error.run │ ├── elapsed_time.c │ ├── elapsed_time.py │ ├── elapsed_time.run │ ├── env_newline.run │ ├── epoll_create.c │ ├── epoll_create1.c │ ├── epoll_edge.c │ ├── epoll_many.c │ ├── epoll_pwait2.c │ ├── epoll_pwait_eintr_sigmask.c │ ├── eventfd.c │ ├── exclusion_region.c │ ├── exclusion_region.run │ ├── exec_deleted.run │ ├── exec_failed.c │ ├── exec_failed.py │ ├── exec_failed.run │ ├── exec_flags.c │ ├── exec_from_main_thread.c │ ├── exec_from_other_thread.c │ ├── exec_many.c │ ├── exec_many.run │ ├── exec_no_env.c │ ├── exec_self.c │ ├── exec_shared_as.c │ ├── exec_shared_as.run │ ├── exec_stop.py │ ├── exec_stop.run │ ├── exec_stopsig.c │ ├── execp.run │ ├── execve_failed.run │ ├── execve_loop.c │ ├── execve_loop.run │ ├── execveat.c │ ├── exit_codes.c │ ├── exit_codes.run │ ├── exit_fast.c │ ├── exit_group.c │ ├── exit_group.run │ ├── exit_race.c │ ├── exit_race.run │ ├── exit_status.c │ ├── exit_status.run │ ├── exit_with_syscallbuf_signal.c │ ├── expect_in_atomic_printf.py │ ├── expect_in_exit.py │ ├── explicit_checkpoint_clone.py │ ├── explicit_checkpoint_clone.run │ ├── fadvise.c │ ├── fanotify.c │ ├── fatal_init_signal.c │ ├── fatal_sigsegv_thread.c │ ├── fcntl_dupfd.c │ ├── fcntl_lease.c │ ├── fcntl_misc.c │ ├── fcntl_notify.c │ ├── fcntl_owner_ex.c │ ├── fcntl_rw_hints.c │ ├── fcntl_seals.c │ ├── fcntl_sig.c │ ├── fd_cleanup.c │ ├── fd_limit.c │ ├── fd_limit.run │ ├── fd_tracking_across_threads.c │ ├── fds_clean.c │ ├── fexecve.c │ ├── fexecve_memfd.c │ ├── file_name_newline.run │ ├── final_sigkill.py │ ├── final_sigkill.run │ ├── first_instruction.py │ ├── first_instruction.run │ ├── flock.c │ ├── flock2.c │ ├── flock_ofd.c │ ├── fork_brk.c │ ├── fork_child_crash.c │ ├── fork_exec_info_thr.run │ ├── fork_many.c │ ├── fork_stress.c │ ├── fork_stress.run │ ├── fork_syscalls.c │ ├── fork_syscalls.run │ ├── fsmount.c │ ├── fstatat.c │ ├── function_calls.c │ ├── function_calls.py │ ├── function_calls.run │ ├── futex_exit_race.c │ ├── futex_exit_race_sigsegv.c │ ├── futex_invalid_op.c │ ├── futex_pi.c │ ├── futex_priorities.c │ ├── futex_requeue.c │ ├── futex_restart_clone.c │ ├── futex_restart_race.c │ ├── gcrypt_rdrand.c │ ├── gdb_bogus_breakpoint.c │ ├── gdb_bogus_breakpoint.py │ ├── gdb_bogus_breakpoint.run │ ├── gdb_qpasssignals.c │ ├── gdb_qpasssignals.py │ ├── gdb_qpasssignals.run │ ├── generic_break.py │ ├── get_thread_list.py │ ├── get_thread_list.run │ ├── getcpu.c │ ├── getcwd.c │ ├── getcwd.run │ ├── getgroups.c │ ├── getpwnam.c │ ├── getrandom.c │ ├── getsid.c │ ├── gettimeofday.c │ ├── goto_event.c │ ├── goto_event.py │ ├── goto_event.run │ ├── grandchild_threads.c │ ├── grandchild_threads_main_running.c │ ├── grandchild_threads_parent_alive.c │ ├── grandchild_threads_thread_running.c │ ├── group_stop_thundering_herd.c │ ├── hardlink_mmapped_files.run │ ├── hbreak.py │ ├── hbreak.run │ ├── hello.c │ ├── hello.run │ ├── history.c │ ├── history.py │ ├── history.run │ ├── hooks.c │ ├── hooks.run │ ├── ignore_nested.c │ ├── ignore_nested.run │ ├── ignored_async_usr1.c │ ├── ignored_async_usr1.run │ ├── ignored_sigsegv.c │ ├── ignored_sigsegv.run │ ├── immediate_restart.c │ ├── immediate_restart.py │ ├── immediate_restart.run │ ├── inotify.c │ ├── int3.c │ ├── interrupt.c │ ├── interrupt.py │ ├── interrupt.run │ ├── intr_futex_wait_restart.c │ ├── intr_poll.c │ ├── intr_ppoll.c │ ├── intr_pselect.c │ ├── intr_ptrace_decline.c │ ├── intr_ptrace_decline.run │ ├── intr_read_no_restart.c │ ├── intr_read_restart.c │ ├── intr_sleep.c │ ├── intr_sleep_no_restart.c │ ├── invalid_exec.c │ ├── invalid_fcntl.c │ ├── invalid_interpreter.c │ ├── invalid_interpreter.py │ ├── invalid_interpreter.run │ ├── invalid_ioctl.c │ ├── invalid_jump.c │ ├── invalid_jump.py │ ├── invalid_jump.run │ ├── io.c │ ├── io_uring.c │ ├── ioctl.c │ ├── ioctl_blk.c │ ├── ioctl_br.c │ ├── ioctl_fb.c │ ├── ioctl_fs.c │ ├── ioctl_hidraw.c │ ├── ioctl_pty.c │ ├── ioctl_sg.c │ ├── ioctl_tty.c │ ├── ioctl_vt.c │ ├── ioprio.c │ ├── jit_proc_mem.c │ ├── jit_proc_mem.py │ ├── jit_proc_mem.run │ ├── join_threads.c │ ├── joystick.c │ ├── kcmp.c │ ├── keyctl.c │ ├── kill_newborn.c │ ├── kill_ptracee.c │ ├── landlock.c │ ├── large_file.run │ ├── large_hole.c │ ├── large_write_deadlock.c │ ├── legacy_ugid.c │ ├── link.c │ ├── link.run │ ├── madvise.c │ ├── madvise_dontfork.c │ ├── madvise_dontfork.py │ ├── madvise_dontfork.run │ ├── madvise_dontneed_private.c │ ├── madvise_fracture_flags.c │ ├── madvise_fracture_flags.run │ ├── madvise_free.c │ ├── madvise_misc.c │ ├── madvise_remove.c │ ├── madvise_wipeonfork.c │ ├── main_thread_exit.c │ ├── main_thread_exit.py │ ├── main_thread_exit.run │ ├── many_yields.c │ ├── many_yields.run │ ├── map_fixed.c │ ├── map_shared_syscall.c │ ├── membarrier.c │ ├── memfd_create.c │ ├── memfd_create_efault.c │ ├── memfd_create_shared.c │ ├── memfd_create_shared_huge.c │ ├── mincore.c │ ├── mknod.c │ ├── mlock.c │ ├── mlock_madvise.c │ ├── mmap_adjacent_to_rr_usage.c │ ├── mmap_fd_reuse_checkpoint.c │ ├── mmap_fd_reuse_checkpoint.py │ ├── mmap_fd_reuse_checkpoint.run │ ├── mmap_private.c │ ├── mmap_private_grow_under_map.c │ ├── mmap_recycle.c │ ├── mmap_replace_most_mappings.c │ ├── mmap_replace_most_mappings.py │ ├── mmap_replace_most_mappings.run │ ├── mmap_ro.c │ ├── mmap_self_maps_shared.c │ ├── mmap_shared.c │ ├── mmap_shared_dev_zero.c │ ├── mmap_shared_extern.c │ ├── mmap_shared_extern.run │ ├── mmap_shared_grow.c │ ├── mmap_shared_grow_under_map.c │ ├── mmap_shared_multiple.c │ ├── mmap_shared_prot.c │ ├── mmap_shared_prot.py │ ├── mmap_shared_prot.run │ ├── mmap_shared_subpage.c │ ├── mmap_shared_write.c │ ├── mmap_shared_write_exec_race.c │ ├── mmap_shared_write_exec_race.run │ ├── mmap_shared_write_fork.c │ ├── mmap_short_file.c │ ├── mmap_tmpfs.c │ ├── mmap_tmpfs.run │ ├── mmap_write.c │ ├── mmap_write.run │ ├── mmap_write_complex.c │ ├── mmap_write_private.c │ ├── mmap_write_private.run │ ├── mmap_zero_size_fd.c │ ├── mount_ns_exec.c │ ├── mount_ns_exec2.c │ ├── mount_ns_execveat.c │ ├── mprotect.c │ ├── mprotect_checkpoint.c │ ├── mprotect_checkpoint.py │ ├── mprotect_checkpoint.run │ ├── mprotect_growsdown.c │ ├── mprotect_growsdown.run │ ├── mprotect_heterogenous.c │ ├── mprotect_none.c │ ├── mprotect_stack.c │ ├── mprotect_step.py │ ├── mprotect_step.run │ ├── mprotect_syscallbuf_overflow.c │ ├── mprotect_syscallbuf_overflow.run │ ├── mq.c │ ├── mremap.c │ ├── mremap_after_coalesce.c │ ├── mremap_dontunmap.c │ ├── mremap_grow.c │ ├── mremap_grow_shared.c │ ├── mremap_non_page_size.c │ ├── mremap_overwrite.c │ ├── mremap_private_grow_under_map.c │ ├── mremap_shrink.c │ ├── msg.c │ ├── msg_trunc.c │ ├── msync.c │ ├── mtio.c │ ├── multiple_pending_signals.c │ ├── multiple_pending_signals_sequential.c │ ├── munmap_discontinuous.c │ ├── munmap_segv.c │ ├── mutex_pi_stress.c │ ├── mutex_pi_stress.run │ ├── nanosleep.c │ ├── nested_detach.run │ ├── nested_detach_kill.run │ ├── nested_detach_kill_stuck.c │ ├── nested_detach_kill_stuck.run │ ├── nested_detach_stop.run │ ├── nested_detach_wait.c │ ├── nested_detach_wait.run │ ├── nested_release.run │ ├── nested_release_exit_code.run │ ├── nested_release_signal.c │ ├── nested_release_signal.run │ ├── netfilter.c │ ├── netfilter_ipv6.c │ ├── netlink_mmap_disable.c │ ├── no_mask_timeslice.c │ ├── nscd.c │ ├── nsutils.h │ ├── numa.c │ ├── open_tree.c │ ├── openat2.c │ ├── openat_null.c │ ├── orphan_process.c │ ├── overflow_branch_counter.c │ ├── overflow_branch_counter.run │ ├── pack.c │ ├── pack.run │ ├── pack_dir.run │ ├── packet_mmap_disable.c │ ├── parent_no_break_child_bkpt.py │ ├── parent_no_break_child_bkpt.run │ ├── parent_no_stop_child_crash.py │ ├── parent_no_stop_child_crash.run │ ├── patch_page_end.c │ ├── patch_page_end.run │ ├── pause.c │ ├── perf_event.c │ ├── perf_event_ioctl.c │ ├── perf_event_mmap.c │ ├── personality.c │ ├── pid_ns_kill_child.c │ ├── pid_ns_kill_child_threads.c │ ├── pid_ns_kill_child_zombie.c │ ├── pid_ns_kill_threads.c │ ├── pid_ns_kill_threads_exit_wait.c │ ├── pid_ns_reap.c │ ├── pid_ns_segv.c │ ├── pid_ns_shutdown.c │ ├── pidfd.c │ ├── pidfd_getfd.c │ ├── pivot_root.c │ ├── poll_sig_race.c │ ├── post_exec_fpu_regs.py │ ├── post_exec_fpu_regs.run │ ├── ppoll.c │ ├── ppoll_deliver.c │ ├── prctl.c │ ├── prctl_anon_vma_name.c │ ├── prctl_auxv.c │ ├── prctl_caps.c │ ├── prctl_deathsig.c │ ├── prctl_name.c │ ├── prctl_short_name.c │ ├── prctl_speculation_ctrl.c │ ├── prctl_tsc.c │ ├── prctl_tsc.run │ ├── prctl_tsc_supported.c │ ├── priority.c │ ├── priority.run │ ├── privileged_net_ioctl.c │ ├── proc_fds.c │ ├── proc_maps.py │ ├── proc_maps.run │ ├── proc_mem.c │ ├── protect_rr_fds.c │ ├── prw.c │ ├── pthread_condvar_locking.c │ ├── pthread_mutex_timedlock.c │ ├── pthread_pi_mutex.c │ ├── pthread_rwlocks.c │ ├── ptrace_attach_null_status.c │ ├── ptrace_attach_running.c │ ├── ptrace_attach_sleeping.c │ ├── ptrace_attach_stopped.c │ ├── ptrace_attach_syscall.c │ ├── ptrace_attach_thread_running.c │ ├── ptrace_breakpoint.c │ ├── ptrace_change_patched_syscall.c │ ├── ptrace_exec.c │ ├── ptrace_group_stop.c │ ├── ptrace_kill_grandtracee.c │ ├── ptrace_remote_unmap.c │ ├── ptrace_remote_unmap.py │ ├── ptrace_remote_unmap.run │ ├── ptrace_seize.c │ ├── ptrace_sigchld.c │ ├── ptrace_sigchld_blocked.c │ ├── ptrace_signals.c │ ├── ptrace_singlestep.c │ ├── ptrace_syscall.c │ ├── ptrace_syscall_clone_untraced.c │ ├── ptrace_sysemu_syscall.c │ ├── ptrace_trace_clone.c │ ├── ptrace_trace_exit.c │ ├── ptrace_traceme.c │ ├── ptrace_util.h │ ├── ptrace_waiter_thread.c │ ├── ptracer_death.c │ ├── ptracer_death_multithread.c │ ├── ptracer_death_multithread_peer.c │ ├── quotactl.c │ ├── read_bad_mem.py │ ├── read_bad_mem.run │ ├── read_big_struct.c │ ├── read_big_struct.py │ ├── read_big_struct.run │ ├── read_large.c │ ├── read_nothing.c │ ├── read_oversize.c │ ├── readdir.c │ ├── readlink.c │ ├── readlinkat.c │ ├── readv.c │ ├── record_replay.run │ ├── record_replay_subject.c │ ├── recvfrom.c │ ├── redzone_integrity.c │ ├── remove_latest_trace.c │ ├── remove_latest_trace.run │ ├── remove_watchpoint.py │ ├── remove_watchpoint.run │ ├── rename.c │ ├── replay_overlarge_event_number.run │ ├── replay_serve_files.py │ ├── replay_serve_files.run │ ├── restart_abnormal_exit.c │ ├── restart_abnormal_exit.py │ ├── restart_abnormal_exit.run │ ├── restart_breakpoint.py │ ├── restart_diversion.py │ ├── restart_diversion.run │ ├── restart_finish.py │ ├── restart_invalid_checkpoint.py │ ├── restart_invalid_checkpoint.run │ ├── restart_unstable.py │ ├── restart_unstable.run │ ├── reverse_alarm.py │ ├── reverse_alarm.run │ ├── reverse_continue_breakpoint.c │ ├── reverse_continue_breakpoint.py │ ├── reverse_continue_breakpoint.run │ ├── reverse_continue_exec_subprocess.py │ ├── reverse_continue_exec_subprocess.run │ ├── reverse_continue_fork_subprocess.py │ ├── reverse_continue_fork_subprocess.run │ ├── reverse_continue_int3.py │ ├── reverse_continue_int3.run │ ├── reverse_continue_multiprocess.c │ ├── reverse_continue_multiprocess.py │ ├── reverse_continue_multiprocess.run │ ├── reverse_continue_process_signal.c │ ├── reverse_continue_process_signal.py │ ├── reverse_continue_process_signal.run │ ├── reverse_continue_start.py │ ├── reverse_continue_start.run │ ├── reverse_finish.py │ ├── reverse_finish.run │ ├── reverse_many_breakpoints.c │ ├── reverse_many_breakpoints.py │ ├── reverse_many_breakpoints.run │ ├── reverse_step_breakpoint.py │ ├── reverse_step_breakpoint.run │ ├── reverse_step_long.c │ ├── reverse_step_long.py │ ├── reverse_step_long.run │ ├── reverse_step_signal.py │ ├── reverse_step_signal.run │ ├── reverse_step_threads.c │ ├── reverse_step_threads.py │ ├── reverse_step_threads.run │ ├── reverse_step_threads2.py │ ├── reverse_step_threads2.run │ ├── reverse_step_threads_break.c │ ├── reverse_step_threads_break.py │ ├── reverse_step_threads_break.run │ ├── reverse_watchpoint.py │ ├── reverse_watchpoint.run │ ├── reverse_watchpoint_syscall.py │ ├── reverse_watchpoint_syscall.run │ ├── rlimit.c │ ├── robust_futex.c │ ├── rr_ps.c │ ├── rr_ps.run │ ├── rr_ps_ns.c │ ├── rr_ps_ns.run │ ├── rseq.c │ ├── rseq.py │ ├── rseq.run │ ├── rseq_cpu_id_reset.c │ ├── rseq_cpu_id_reset_longrunning.c │ ├── rseq_cpu_id_reset_longrunning.py │ ├── rseq_cpu_id_reset_longrunning.run │ ├── rseq_syscallbuf.c │ ├── rseq_syscallbuf.run │ ├── run_end.py │ ├── run_end.run │ ├── run_in_function.py │ ├── run_in_function.run │ ├── rusage.c │ ├── samask.c │ ├── sanity.py │ ├── sanity.run │ ├── save_data_fd.c │ ├── sched_attr.c │ ├── sched_setaffinity.c │ ├── sched_setparam.c │ ├── sched_yield.c │ ├── sched_yield_to_lower_priority.c │ ├── scm_rights.c │ ├── scratch_read.c │ ├── search.c │ ├── search.py │ ├── search.run │ ├── seccomp.c │ ├── seccomp_blocks_rr.c │ ├── seccomp_blocks_rr.run │ ├── seccomp_clone_fail.c │ ├── seccomp_cloning.c │ ├── seccomp_desched.c │ ├── seccomp_kill_exit.c │ ├── seccomp_null.c │ ├── seccomp_open.c │ ├── seccomp_open.run │ ├── seccomp_signals.c │ ├── seccomp_signals.run │ ├── seccomp_sigsys_args.c │ ├── seccomp_sigsys_sigtrap.c │ ├── seccomp_sigsys_syscallbuf.c │ ├── seccomp_tsync.c │ ├── seccomp_veto_exec.c │ ├── seekticks.py │ ├── seekticks.run │ ├── seekticks_threads.c │ ├── seekticks_threads.py │ ├── seekticks_threads.run │ ├── segfault.c │ ├── segfault.run │ ├── self_shebang.c │ ├── self_sigint.c │ ├── sem.c │ ├── send_block.c │ ├── sendfile.c │ ├── set_ptracer.c │ ├── set_tid_address.c │ ├── setgid.c │ ├── setgroups.c │ ├── setitimer.c │ ├── setsid.c │ ├── setuid.c │ ├── setuid.run │ ├── shared_exec.c │ ├── shared_map.c │ ├── shared_map.run │ ├── shared_monitor.c │ ├── shared_offset.c │ ├── shared_persistent_file.c │ ├── shared_persistent_file.py │ ├── shared_persistent_file.run │ ├── shared_write.c │ ├── shm.c │ ├── shm_checkpoint.py │ ├── shm_checkpoint.run │ ├── shm_unmap.c │ ├── sigaction_old.c │ ├── sigaltstack.c │ ├── sigchld_interrupt_signal.c │ ├── sigcont.c │ ├── sigcont_threaded.c │ ├── sigframe_grow_stack.c │ ├── sighandler_bad_rsp_sigsegv.c │ ├── sighandler_fork.c │ ├── sighandler_mask.c │ ├── sigill.c │ ├── siginfo.py │ ├── siginfo.run │ ├── signal_checkpoint.py │ ├── signal_checkpoint.run │ ├── signal_deferred.c │ ├── signal_during_preload_init.c │ ├── signal_frame.c │ ├── signal_numbers.c │ ├── signal_numbers.py │ ├── signal_numbers.run │ ├── signal_stop.py │ ├── signal_stop.run │ ├── signal_unstoppable.c │ ├── signalfd.c │ ├── sigprocmask.c │ ├── sigprocmask_ensure_delivery.c │ ├── sigprocmask_evil.c │ ├── sigprocmask_exec.c │ ├── sigprocmask_in_syscallbuf_sighandler.c │ ├── sigprocmask_race.c │ ├── sigprocmask_race.run │ ├── sigprocmask_rr_sigs.c │ ├── sigprocmask_rr_sigs_nondefault.c │ ├── sigprocmask_rr_sigs_nondefault.run │ ├── sigprocmask_syscallbuf.c │ ├── sigprof.c │ ├── sigpwr.c │ ├── sigqueueinfo.c │ ├── sigreturn_reg.c │ ├── sigreturnmask.c │ ├── sigrt.c │ ├── sigstop.c │ ├── sigstop2.c │ ├── sigsuspend.c │ ├── sigtrap.c │ ├── sigtrap_process_group.c │ ├── simple.c │ ├── simple.run │ ├── simple_script.run │ ├── simple_script.sh │ ├── simple_script_debug.py │ ├── simple_script_debug.run │ ├── simple_threads_stress.c │ ├── simple_winch.py │ ├── simple_winch.run │ ├── sioc.c │ ├── small_holes.c │ ├── sock_name_null.c │ ├── sock_names_opts.c │ ├── spinlock_priorities.c │ ├── splice.c │ ├── stack_growth.c │ ├── stack_growth.py │ ├── stack_growth.run │ ├── stack_growth_after_syscallbuf.c │ ├── stack_growth_syscallbuf.c │ ├── stack_growth_with_guard.c │ ├── stack_invalid.c │ ├── stack_overflow.c │ ├── stack_overflow_altstack.c │ ├── stack_overflow_debug.py │ ├── stack_overflow_debug.run │ ├── stack_overflow_with_guard.c │ ├── statfs.c │ ├── statx.c │ ├── std_random.cc │ ├── stdout_child.c │ ├── stdout_cloexec.c │ ├── stdout_dup.c │ ├── stdout_redirect.c │ ├── step1.py │ ├── step1.run │ ├── step_into_lib.c │ ├── step_into_lib.py │ ├── step_into_lib.run │ ├── step_signal.py │ ├── step_signal.run │ ├── step_thread.c │ ├── step_thread.py │ ├── step_thread.run │ ├── stray_time_slice_signal.c │ ├── stray_time_slice_signal.run │ ├── strict_priorities.c │ ├── strict_priorities.run │ ├── subprocess_exit_ends_session.py │ ├── subprocess_exit_ends_session.run │ ├── switch_processes.py │ ├── switch_processes.run │ ├── switch_read.c │ ├── symlink.c │ ├── sync.c │ ├── sync_file_range.c │ ├── syscall_bp.c │ ├── syscall_in_writable_mem.c │ ├── syscallbuf_fd_disabling.c │ ├── syscallbuf_fd_disabling.run │ ├── syscallbuf_signal_blocking.c │ ├── syscallbuf_signal_blocking_read.c │ ├── syscallbuf_signal_blocking_read.run │ ├── syscallbuf_signal_reset.c │ ├── syscallbuf_sigstop.c │ ├── syscallbuf_timeslice.c │ ├── syscallbuf_timeslice2.c │ ├── syscallbuf_timeslice2_250.run │ ├── syscallbuf_timeslice_250.run │ ├── sysconf.c │ ├── sysconf_conf.c │ ├── sysconf_onln.c │ ├── sysconf_onln.run │ ├── sysctl.c │ ├── sysemu_singlestep.c │ ├── sysinfo.c │ ├── syslog.c │ ├── target_fork.c │ ├── target_fork.run │ ├── target_process.c │ ├── target_process.run │ ├── tcp_sockets.c │ ├── tcp_sockets.run │ ├── term_nonmain.c │ ├── term_nonmain.run │ ├── term_rr.c │ ├── term_rr.py │ ├── term_rr.run │ ├── term_rr_ok.c │ ├── term_rr_ok.run │ ├── term_trace_cpu.run │ ├── term_trace_reset.c │ ├── term_trace_reset.run │ ├── term_trace_syscall.c │ ├── term_trace_syscall.run │ ├── test_lib.c │ ├── test_setup.gdb │ ├── test_setup.lldb │ ├── tgkill.c │ ├── thread_exit_signal.c │ ├── thread_exit_signal.run │ ├── thread_open_race.c │ ├── thread_open_race.run │ ├── thread_stress.c │ ├── thread_stress.run │ ├── thread_yield.c │ ├── threaded_syscall_spam.c │ ├── threaded_syscall_spam.run │ ├── threads.c │ ├── threads.run │ ├── tick0.c │ ├── tick0.py │ ├── tick0.run │ ├── tick0_less.run │ ├── timer.c │ ├── timerfd.c │ ├── times.c │ ├── tls.c │ ├── tls.py │ ├── tls.run │ ├── trace_events.run │ ├── trace_version.run │ ├── tracee_unmap_vdso.c │ ├── tracee_unmap_vdso.run │ ├── transient_fault_replay_all.run │ ├── truncate_temp.c │ ├── tty.run │ ├── ttyname.c │ ├── ttyname.run │ ├── tun.c │ ├── two_signals_with_mask.c │ ├── ulimit_low.c │ ├── uname.c │ ├── unexpected_exit.c │ ├── unexpected_exit_execve.c │ ├── unexpected_exit_execve_twice.c │ ├── unexpected_exit_pid_ns.c │ ├── unexpected_stack_growth.c │ ├── unexpected_stack_growth.py │ ├── unexpected_stack_growth.run │ ├── unicode.c │ ├── unicode.py │ ├── unicode.run │ ├── unjoined_thread.c │ ├── unmap_vdso.run │ ├── unshare.c │ ├── unwind_on_signal.py │ ├── unwind_on_signal.run │ ├── unwind_rr_page.cc │ ├── usb.c │ ├── user_ignore_sig.c │ ├── user_ignore_sig.run │ ├── userfaultfd.c │ ├── util.h │ ├── util.py │ ├── util.sh │ ├── util_internal.h │ ├── util_syscall.h │ ├── utimes.c │ ├── v4l_dmabuf.c │ ├── vdso_clock_gettime_stack.c │ ├── vdso_clock_gettime_stack.run │ ├── vdso_gettimeofday_stack.c │ ├── vdso_gettimeofday_stack.run │ ├── vdso_parts.c │ ├── vdso_stack.py │ ├── vdso_symbols.c │ ├── vdso_time_stack.c │ ├── vdso_time_stack.run │ ├── vfork.c │ ├── vfork.run │ ├── vfork_break_parent.py │ ├── vfork_break_parent.run │ ├── vfork_done.c │ ├── vfork_done_clone.run │ ├── vfork_exec.run │ ├── vfork_flush.c │ ├── vfork_read_clone_stress.c │ ├── vfork_read_clone_stress.py │ ├── vfork_read_clone_stress.run │ ├── vfork_setopts.c │ ├── vfork_shared.c │ ├── video_capture.c │ ├── vm_readv_writev.c │ ├── vsyscall.c │ ├── vsyscall_reverse_next.c │ ├── vsyscall_reverse_next.py │ ├── vsyscall_reverse_next.run │ ├── vsyscall_singlestep.run │ ├── vsyscall_timeslice.c │ ├── wait.c │ ├── wait_for_all.c │ ├── wait_for_all.run │ ├── wait_sigstop.c │ ├── watch_code.py │ ├── watch_code.run │ ├── watchpoint.c │ ├── watchpoint.py │ ├── watchpoint.run │ ├── watchpoint_at_sched.c │ ├── watchpoint_at_sched.py │ ├── watchpoint_at_sched.run │ ├── watchpoint_before_signal.c │ ├── watchpoint_before_signal.py │ ├── watchpoint_before_signal.run │ ├── watchpoint_cond.py │ ├── watchpoint_cond.run │ ├── watchpoint_no_progress.c │ ├── watchpoint_no_progress.py │ ├── watchpoint_no_progress.run │ ├── watchpoint_size_change.c │ ├── watchpoint_size_change.py │ ├── watchpoint_size_change.run │ ├── watchpoint_step.py │ ├── watchpoint_step.run │ ├── watchpoint_syscall.c │ ├── watchpoint_syscall.py │ ├── watchpoint_syscall.run │ ├── watchpoint_unaligned.c │ ├── watchpoint_unaligned.py │ ├── watchpoint_unaligned.run │ ├── watchpoint_unaligned2.c │ ├── watchpoint_unaligned2.py │ ├── watchpoint_unaligned2.run │ ├── when.py │ ├── when.run │ ├── when_threads.c │ ├── when_threads.py │ ├── when_threads.run │ ├── write_race.c │ ├── writev.c │ ├── x86 │ │ ├── arch_prctl_x86.c │ │ ├── arch_prctl_xstate.c │ │ ├── blocked_sigsegv.c │ │ ├── blocked_sigsegv.run │ │ ├── break_rdtsc.run │ │ ├── chew_cpu_cpuid.c │ │ ├── cpuid.c │ │ ├── cpuid.run │ │ ├── cpuid_loop.S │ │ ├── cpuid_same_state.c │ │ ├── cpuid_singlestep.c │ │ ├── cpuid_singlestep.py │ │ ├── cpuid_singlestep.run │ │ ├── cross_arch.c │ │ ├── deferred_patch.c │ │ ├── diversion_rdtsc.c │ │ ├── diversion_rdtsc.py │ │ ├── diversion_rdtsc.run │ │ ├── explicit_checkpoints.c │ │ ├── explicit_checkpoints.py │ │ ├── explicit_checkpoints.run │ │ ├── fault_in_code_page.c │ │ ├── fxregs.c │ │ ├── fxregs.py │ │ ├── fxregs.run │ │ ├── gdb_avx512.c │ │ ├── gdb_avx512.py │ │ ├── gdb_avx512.run │ │ ├── hle.c │ │ ├── hlt.c │ │ ├── int3_ok.c │ │ ├── int3_ok.run │ │ ├── ioperm.c │ │ ├── iopl.c │ │ ├── la57.c │ │ ├── lsl.c │ │ ├── modify_ldt.c │ │ ├── morestack_unwind.c │ │ ├── morestack_unwind.py │ │ ├── morestack_unwind.run │ │ ├── old_fork.c │ │ ├── patch_40_80_f6_81.c │ │ ├── patch_40_80_f6_81.run │ │ ├── patch_syscall_restart.c │ │ ├── pkeys.c │ │ ├── ptrace.c │ │ ├── ptrace_debug_regs.c │ │ ├── ptrace_exec32.c │ │ ├── ptrace_sysemu.c │ │ ├── ptrace_tls.c │ │ ├── rdtsc.c │ │ ├── rdtsc_flags.c │ │ ├── rdtsc_interfering.c │ │ ├── rdtsc_interfering.run │ │ ├── rdtsc_loop.c │ │ ├── rdtsc_loop.run │ │ ├── rdtsc_loop2.c │ │ ├── rdtsc_loop2.run │ │ ├── signal_xmm_state.c │ │ ├── sigreturn.c │ │ ├── sigreturn_checksum.run │ │ ├── singlestep_pushf.c │ │ ├── singlestep_pushf.py │ │ ├── singlestep_pushf.run │ │ ├── step_rdtsc.py │ │ ├── step_rdtsc.run │ │ ├── string_instructions.c │ │ ├── string_instructions.py │ │ ├── string_instructions.run │ │ ├── string_instructions_async_signals.c │ │ ├── string_instructions_async_signals.run │ │ ├── string_instructions_async_signals_shared.c │ │ ├── string_instructions_async_signals_shared.run │ │ ├── string_instructions_break.py │ │ ├── string_instructions_break.run │ │ ├── string_instructions_multiwatch.c │ │ ├── string_instructions_multiwatch.py │ │ ├── string_instructions_multiwatch.run │ │ ├── string_instructions_replay.c │ │ ├── string_instructions_replay.run │ │ ├── string_instructions_replay_quirk.py │ │ ├── string_instructions_replay_quirk.run │ │ ├── string_instructions_singlestep_fastforward.c │ │ ├── string_instructions_singlestep_fastforward.run │ │ ├── string_instructions_watch.c │ │ ├── string_instructions_watch.py │ │ ├── string_instructions_watch.run │ │ ├── syscallbuf_branch_check.c │ │ ├── syscallbuf_branch_check.run │ │ ├── syscallbuf_rdtsc_page.c │ │ ├── syscallbuf_rdtsc_page.run │ │ ├── sysfs.c │ │ ├── util.h │ │ ├── util.py │ │ ├── util.sh │ │ ├── watchpoint_error.c │ │ ├── watchpoint_error.py │ │ ├── watchpoint_error.run │ │ └── x87env.c │ ├── xattr.c │ └── zero_length_read.c ├── util.cc └── util.h └── third-party ├── blake2 ├── README ├── blake2-impl.h ├── blake2.h ├── neon │ ├── blake2b-load-neon.h │ ├── blake2b-neon.c │ ├── blake2b-round.h │ └── blake2b.c └── sse │ ├── blake2-config.h │ ├── blake2b-load-sse2.h │ ├── blake2b-load-sse41.h │ ├── blake2b-round.h │ └── blake2b.c ├── brotli ├── README.md ├── common │ ├── constants.c │ ├── constants.h │ ├── context.c │ ├── context.h │ ├── dictionary.bin │ ├── dictionary.bin.br │ ├── dictionary.c │ ├── dictionary.h │ ├── platform.c │ ├── platform.h │ ├── shared_dictionary.c │ ├── shared_dictionary_internal.h │ ├── transform.c │ ├── transform.h │ └── version.h ├── dec │ ├── bit_reader.c │ ├── bit_reader.h │ ├── decode.c │ ├── huffman.c │ ├── huffman.h │ ├── prefix.h │ ├── state.c │ └── state.h ├── enc │ ├── backward_references.c │ ├── backward_references.h │ ├── backward_references_hq.c │ ├── backward_references_hq.h │ ├── backward_references_inc.h │ ├── bit_cost.c │ ├── bit_cost.h │ ├── bit_cost_inc.h │ ├── block_encoder_inc.h │ ├── block_splitter.c │ ├── block_splitter.h │ ├── block_splitter_inc.h │ ├── brotli_bit_stream.c │ ├── brotli_bit_stream.h │ ├── cluster.c │ ├── cluster.h │ ├── cluster_inc.h │ ├── command.c │ ├── command.h │ ├── compound_dictionary.c │ ├── compound_dictionary.h │ ├── compress_fragment.c │ ├── compress_fragment.h │ ├── compress_fragment_two_pass.c │ ├── compress_fragment_two_pass.h │ ├── dictionary_hash.c │ ├── dictionary_hash.h │ ├── encode.c │ ├── encoder_dict.c │ ├── encoder_dict.h │ ├── entropy_encode.c │ ├── entropy_encode.h │ ├── entropy_encode_static.h │ ├── fast_log.c │ ├── fast_log.h │ ├── find_match_length.h │ ├── hash.h │ ├── hash_composite_inc.h │ ├── hash_forgetful_chain_inc.h │ ├── hash_longest_match64_inc.h │ ├── hash_longest_match_inc.h │ ├── hash_longest_match_quickly_inc.h │ ├── hash_rolling_inc.h │ ├── hash_to_binary_tree_inc.h │ ├── histogram.c │ ├── histogram.h │ ├── histogram_inc.h │ ├── literal_cost.c │ ├── literal_cost.h │ ├── memory.c │ ├── memory.h │ ├── metablock.c │ ├── metablock.h │ ├── metablock_inc.h │ ├── params.h │ ├── prefix.h │ ├── quality.h │ ├── ringbuffer.h │ ├── state.h │ ├── static_dict.c │ ├── static_dict.h │ ├── static_dict_lut.h │ ├── utf8_util.c │ ├── utf8_util.h │ └── write_bits.h └── include │ └── brotli │ ├── decode.h │ ├── encode.h │ ├── port.h │ ├── shared_dictionary.h │ └── types.h ├── gdb ├── 32bit-avx.xml ├── 32bit-avx512.xml ├── 32bit-core.xml ├── 32bit-linux.xml ├── 32bit-pkeys.xml ├── 32bit-sse.xml ├── 64bit-avx.xml ├── 64bit-avx512.xml ├── 64bit-core.xml ├── 64bit-linux.xml ├── 64bit-pkeys.xml ├── 64bit-seg.xml ├── 64bit-sse.xml ├── README ├── aarch64-core.xml ├── aarch64-fpu.xml └── aarch64-pauth.xml ├── proc-service ├── README └── proc_service.h └── zen-pmu-workaround ├── Makefile ├── README └── zen_workaround.c /.buildkite/.gitignore: -------------------------------------------------------------------------------- 1 | test.yml 2 | test-*.yml 3 | -------------------------------------------------------------------------------- /.buildkite/Project.toml: -------------------------------------------------------------------------------- 1 | [deps] 2 | YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6" 3 | -------------------------------------------------------------------------------- /.buildkite/lib/common.jl: -------------------------------------------------------------------------------- 1 | include(joinpath(@__DIR__, "types.jl")) 2 | 3 | function get_yaml_path(platform::Platform) 4 | lib_dir = @__DIR__ 5 | buildkite_dir = dirname(lib_dir) 6 | yaml_path = joinpath(buildkite_dir, "test-$(platform.arch).yml") 7 | return yaml_path 8 | end 9 | -------------------------------------------------------------------------------- /.buildkite/lib/launch.jl: -------------------------------------------------------------------------------- 1 | include(joinpath(@__DIR__, "common.jl")) 2 | 3 | function launch(platform::Platform) 4 | yaml_path = get_yaml_path(platform) 5 | cmd = `buildkite-agent pipeline upload $(yaml_path)` 6 | run(cmd) 7 | return nothing 8 | end 9 | 10 | launch.(platforms) 11 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Helper to make |./configure && make| do what you expect. 4 | cmake . 5 | -------------------------------------------------------------------------------- /release-process/test-data/rr-test-doc.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rr-debugger/rr/daaab24f10c81394f209cf05ef1191af3365ccd8/release-process/test-data/rr-test-doc.odt -------------------------------------------------------------------------------- /release-process/test-data/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Hello! 5 | 8 | -------------------------------------------------------------------------------- /scripts/reformat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | find src -regex '.*\.\(c\|h\|cc\)$'|xargs clang-format -style=file -i 4 | -------------------------------------------------------------------------------- /src/BreakpointCondition.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #ifndef RR_BREAKPOINT_CONDITION_H_ 4 | #define RR_BREAKPOINT_CONDITION_H_ 5 | 6 | namespace rr { 7 | 8 | class ReplayTask; 9 | 10 | class BreakpointCondition { 11 | public: 12 | virtual ~BreakpointCondition() {} 13 | virtual bool evaluate(ReplayTask* t) const = 0; 14 | }; 15 | 16 | } // namespace rr 17 | 18 | #endif // RR_BREAKPOINT_CONDITION_H_ 19 | -------------------------------------------------------------------------------- /src/Flags.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "Flags.h" 4 | 5 | namespace rr { 6 | 7 | Flags& Flags::get_for_init() { return singleton; } 8 | 9 | Flags Flags::singleton; 10 | 11 | } // namespace rr 12 | -------------------------------------------------------------------------------- /src/Ticks.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #ifndef RR_TICKS_H_ 4 | #define RR_TICKS_H_ 5 | 6 | #include 7 | 8 | namespace rr { 9 | 10 | typedef int64_t Ticks; 11 | 12 | } // namespace rr 13 | 14 | #endif /* RR_TICKS_H_ */ 15 | -------------------------------------------------------------------------------- /src/audit/rtld-audit.h: -------------------------------------------------------------------------------- 1 | #ifndef __RR_RTLD_AUDIT_H__ 2 | #define __RR_RTLD_AUDIT_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define PRIxELFADDR _PRIxELFADDR(PRIx, __ELF_NATIVE_CLASS) 9 | #define _PRIxELFADDR(f, w) _PRIxELFADDR_1(f, w) 10 | #define _PRIxELFADDR_1(f, w) f##w 11 | 12 | extern bool rr_audit_debug; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/exec_stub.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | void _start(void) {} 4 | -------------------------------------------------------------------------------- /src/extra_version_string.h.in: -------------------------------------------------------------------------------- 1 | #ifndef RR_EXTRA_VERSION_STRING_H_ 2 | #define RR_EXTRA_VERSION_STRING_H_ 3 | 4 | #define EXTRA_VERSION_STRING "@EXTRA_VERSION_STRING@" 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/git_revision.h.in: -------------------------------------------------------------------------------- 1 | #ifndef RR_GIT_REVISION_H_ 2 | #define RR_GIT_REVISION_H_ 3 | 4 | #define GIT_REVISION "@GIT_REVISION@" 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/perf-test/many-threads-wake.md: -------------------------------------------------------------------------------- 1 | `many-threads-wake` creates 5000 threads. Each new thread has to wait for the creator thread to exit a critical section before proceeding. 2 | 3 | Cheat sheet: 4 | ```` 5 | cd ~/rr/obj 6 | cmake -DCMAKE_BUILD_TYPE=RELEASE ../rr 7 | make -j8 8 | 9 | gcc -g -o many-threads-wake ../rr/src/perf-test/many-threads-wake.c 10 | time bin/rr record ./many-threads-wake 11 | ```` 12 | -------------------------------------------------------------------------------- /src/perf-test/many-threads.md: -------------------------------------------------------------------------------- 1 | `many-threads` creates 5000 threads and then forces 20000 ping-pongs between two of the threads. This tests performance of thread creation and context switching. 2 | 3 | Cheat sheet: 4 | ```` 5 | cd ~/rr/obj 6 | cmake -DCMAKE_BUILD_TYPE=RELEASE ../rr 7 | make -j8 8 | 9 | gcc -g -o many-threads ../rr/src/perf-test/many-threads.c 10 | time bin/rr record ./many-threads 11 | ```` 12 | -------------------------------------------------------------------------------- /src/perf-test/unbuffered-syscalls.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) { 4 | for (int i = 0; i < 500000; ++i) { 5 | getsid(0); 6 | } 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /src/preload/syscallbuf.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #ifndef RR_SYSCALLBUF_H_ 4 | #define RR_SYSCALLBUF_H_ 5 | 6 | struct timespec; 7 | 8 | #define RR_HIDDEN __attribute__((visibility("hidden"))) 9 | 10 | RR_HIDDEN extern struct preload_globals globals; 11 | 12 | RR_HIDDEN extern char impose_syscall_delay; 13 | RR_HIDDEN extern char impose_spurious_desched; 14 | 15 | #endif /* RR_SYSCALLBUF_H_ */ 16 | -------------------------------------------------------------------------------- /src/processor_trace_check.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #ifndef RR_PROCESSOR_TRACE_CHECK_H_ 4 | #define RR_PROCESSOR_TRACE_CHECK_H_ 5 | 6 | #include 7 | 8 | namespace rr { 9 | 10 | class ReplayTask; 11 | 12 | void check_intel_pt_if_enabled(ReplayTask* t); 13 | 14 | void emergency_check_intel_pt(ReplayTask* t, std::ostream& stream); 15 | 16 | } // namespace rr 17 | 18 | #endif /* RR_PROCESSOR_TRACE_CHECK_H_ */ 19 | -------------------------------------------------------------------------------- /src/remote_code_ptr.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "remote_code_ptr.h" 4 | 5 | using namespace std; 6 | 7 | namespace rr { 8 | 9 | ostream& operator<<(ostream& stream, remote_code_ptr p) { 10 | stream << (void*)p.register_value(); 11 | return stream; 12 | } 13 | 14 | } // namespace rr 15 | -------------------------------------------------------------------------------- /src/test/_llseek.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(__attribute__((unused)) int argc, char* argv[]) { 6 | int fd = open(argv[0], O_RDONLY); 7 | #ifdef SYS__llseek 8 | loff_t result = -1234; 9 | #endif 10 | test_assert(fd >= 0); 11 | #ifdef SYS__llseek 12 | test_assert(syscall(SYS__llseek, fd, 0L, 0, &result, SEEK_SET) == 0); 13 | test_assert(result == 0); 14 | #endif 15 | 16 | atomic_puts("EXIT-SUCCESS"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/test/abort.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | atomic_puts("EXIT-SUCCESS"); 7 | kill(0, SIGABRT); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /src/test/abort_nonmain.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | compare_test 'killing...' 3 | -------------------------------------------------------------------------------- /src/test/acct.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int ret = acct("this_file_does_not_exist.1903901"); 7 | test_assert(ret < 0 && (errno == EPERM || errno == ENOENT)); 8 | atomic_puts("EXIT-SUCCESS"); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/test/aio.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | aio_context_t ctx; 7 | int ret = syscall(__NR_io_setup, 1, &ctx); 8 | test_assert(ret < 0 && errno == ENOSYS); 9 | 10 | atomic_puts("EXIT-SUCCESS"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/test/alternate_thread_diversion.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | bp = breakpoint_at_function('break_here') 4 | cont() 5 | expect_breakpoint_stop(bp) 6 | 7 | expect_threads(num_threads=2, selected_thread=2) 8 | 9 | select_thread(1) 10 | scheduler_locking_on() 11 | expect_expression('get_value()', 1) 12 | scheduler_locking_off() 13 | cont() 14 | expect_signal_stop('SIGKILL') 15 | 16 | ok() 17 | -------------------------------------------------------------------------------- /src/test/alternate_thread_diversion.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test 3 | -------------------------------------------------------------------------------- /src/test/args.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | test_assert(6 == argc); 7 | test_assert(!strcmp("-no", argv[1])); 8 | test_assert(!strcmp("--force-syscall-buffer=foo", argv[2])); 9 | test_assert(!strcmp("-c", argv[3])); 10 | test_assert(!strcmp("1000", argv[4])); 11 | test_assert(!strcmp("hello", argv[5])); 12 | 13 | atomic_puts("EXIT-SUCCESS"); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/test/args.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record args$bitness "-no --force-syscall-buffer=foo -c 1000 hello" 3 | replay 4 | check 'EXIT-SUCCESS' 5 | -------------------------------------------------------------------------------- /src/test/arm/arch_timer.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | if ! prctl_tsc_supported; then 3 | exit 77 4 | fi 5 | compare_test EXIT-SUCCESS 6 | debug_gdb_only arm/diversion_arch_timer 7 | -------------------------------------------------------------------------------- /src/test/arm/diversion_arch_timer.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1') 8 | 9 | send_gdb('call diversion_check()') 10 | expect_gdb('diversion_check passed') 11 | 12 | ok() 13 | -------------------------------------------------------------------------------- /src/test/arm/util.h: -------------------------------------------------------------------------------- 1 | #include "../util.h" 2 | -------------------------------------------------------------------------------- /src/test/arm/util.py: -------------------------------------------------------------------------------- 1 | ../util.py -------------------------------------------------------------------------------- /src/test/arm/util.sh: -------------------------------------------------------------------------------- 1 | TEST_PREFIX=arm/ 2 | source `dirname $0`/../util.sh 3 | -------------------------------------------------------------------------------- /src/test/async_kill_with_syscallbuf.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | # SIGKILL, wait 2.0s 3 | record_async_signal 9 2.0 $TESTNAME 4 | replay 5 | check 'EXIT-SUCCESS' 6 | -------------------------------------------------------------------------------- /src/test/async_kill_with_syscallbuf2.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | # SIGKILL, wait 1.0s 3 | record_async_signal 9 1.0 $TESTNAME 4 | replay 5 | check 'EXIT-SUCCESS' 6 | -------------------------------------------------------------------------------- /src/test/async_kill_with_threads.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void* start_thread(__attribute__((unused)) void* p) { 6 | atomic_puts("ready"); 7 | sleep(1000); 8 | return NULL; 9 | } 10 | 11 | int main(void) { 12 | pthread_t thread; 13 | 14 | pthread_create(&thread, NULL, start_thread, NULL); 15 | atomic_puts("EXIT-SUCCESS"); 16 | sleep(1000); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/test/async_kill_with_threads.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | # SIGKILL, wait 2.0s 3 | record_async_signal 9 2.0 $TESTNAME 4 | replay 5 | check 'EXIT-SUCCESS' 6 | -------------------------------------------------------------------------------- /src/test/async_kill_with_threads_main_running.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void* start_thread(__attribute__((unused)) void* p) { 6 | sleep(1000); 7 | return NULL; 8 | } 9 | 10 | int main(void) { 11 | pthread_t thread; 12 | 13 | atomic_puts("ready"); 14 | 15 | pthread_create(&thread, NULL, start_thread, NULL); 16 | atomic_puts("EXIT-SUCCESS"); 17 | while (1) { 18 | asm("" : : : "memory"); 19 | } 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /src/test/async_kill_with_threads_main_running.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | # SIGKILL, wait 2.0s 3 | record_async_signal 9 2.0 $TESTNAME 4 | replay 5 | check 'EXIT-SUCCESS' 6 | -------------------------------------------------------------------------------- /src/test/async_kill_with_threads_thread_running.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void* start_thread(__attribute__((unused)) void* p) { 6 | atomic_puts("ready"); 7 | while (1) { 8 | asm("" : : : "memory"); 9 | } 10 | return NULL; 11 | } 12 | 13 | int main(void) { 14 | pthread_t thread; 15 | 16 | pthread_create(&thread, NULL, start_thread, NULL); 17 | atomic_puts("EXIT-SUCCESS"); 18 | sleep(1000); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /src/test/async_kill_with_threads_thread_running.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | # SIGKILL, wait 6.0s 3 | # The timeout must be greater than rr's alarm threshold of 3s, because 4 | # the spinning-thread may not do any conditional branches so we rely 5 | # on the alarm fallback to ensure there's a context switch to the main 6 | # thread to print EXIT-SUCCESS. 7 | record_async_signal 9 6.0 $TESTNAME 8 | replay 9 | check 'EXIT-SUCCESS' 10 | -------------------------------------------------------------------------------- /src/test/async_segv.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | # SIGSEGV, wait 2.0s 3 | record_async_signal 11 2.0 $TESTNAME 4 | replay 5 | check EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/async_segv_ignored.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | signal(SIGSEGV, SIG_IGN); 7 | 8 | kill(getpid(), SIGSEGV); 9 | 10 | atomic_puts("EXIT-SUCCESS"); 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/test/async_signal_syscalls.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Without the syscallbuf, trying to record the large number of 4 | # syscalls in this test is impractical. 5 | skip_if_no_syscall_buf 6 | 7 | # 2^17 iterations is arbitrarily chosen to take ~3s on a fast machine 8 | record $TESTNAME 17 9 | 10 | replay 11 | check 'EXIT-SUCCESS' 12 | passed 13 | -------------------------------------------------------------------------------- /src/test/async_signal_syscalls2.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Without the syscallbuf, trying to record the large number of 4 | # syscalls in this test is impractical. 5 | skip_if_no_syscall_buf 6 | 7 | compare_test EXIT-SUCCESS 8 | -------------------------------------------------------------------------------- /src/test/async_signal_syscalls_100.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Ensure that the test records some SCHED interrupt events. 4 | timeslice=100 5 | RECORD_ARGS="-c$timeslice" 6 | 7 | # 2^9 iterations is arbitrarily chosen to record and replay < 15s, 8 | # both with and without the syscallbuf, on a fast machine. 9 | record async_signal_syscalls$bitness 9 10 | replay 11 | check 'EXIT-SUCCESS' 12 | -------------------------------------------------------------------------------- /src/test/async_signal_syscalls_1000.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Ensure that the test records some USR_SCHED interrupt events. 4 | timeslice=1000 5 | RECORD_ARGS="-c$timeslice" 6 | 7 | # 2^9 iterations is arbitrarily chosen to record and replay < 15s, 8 | # both with and without the syscallbuf, on a fast machine. 9 | record async_signal_syscalls$bitness 9 10 | replay 11 | check 'EXIT-SUCCESS' 12 | -------------------------------------------------------------------------------- /src/test/async_signal_syscalls_siginfo.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Without the syscallbuf, trying to record the large number of 4 | # syscalls in this test is impractical. 5 | skip_if_no_syscall_buf 6 | 7 | # 2^17 iterations is arbitrarily chosen to take ~3s on a fast machine 8 | record $TESTNAME 17 9 | 10 | replay 11 | check 'EXIT-SUCCESS' 12 | passed 13 | -------------------------------------------------------------------------------- /src/test/async_usr1.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | # SIGUSR1, wait 2.0s 3 | record_async_signal 10 2.0 $TESTNAME 4 | replay 5 | check 'EXIT-SUCCESS' 6 | -------------------------------------------------------------------------------- /src/test/bad_breakpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | for i in $(seq 15 25); do 4 | echo Replaying to event $i ... 5 | debug_gdb_only restart_finish "-g $i" 6 | if [[ "$leave_data" == "y" ]]; then 7 | break 8 | fi 9 | done 10 | -------------------------------------------------------------------------------- /src/test/bad_good_break.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b bad_breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('b good_breakpoint') 7 | expect_gdb('Breakpoint 2') 8 | 9 | send_gdb('c') 10 | # If we hit bad_breakpoint, then we never continue and never reach 11 | # good_breakpoint. 12 | expect_gdb('Breakpoint 2, good_breakpoint') 13 | 14 | ok() 15 | -------------------------------------------------------------------------------- /src/test/bad_syscall.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int ret = syscall(-10); 7 | test_assert(-1 == ret && ENOSYS == errno); 8 | ret = syscall(9999); 9 | test_assert(-1 == ret && ENOSYS == errno); 10 | atomic_puts("EXIT-SUCCESS"); 11 | return ret; 12 | } 13 | -------------------------------------------------------------------------------- /src/test/basic_test.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | compare_test EXIT-SUCCESS 3 | -------------------------------------------------------------------------------- /src/test/blacklist.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | touch rr-test-blacklist-file_name 3 | compare_test EXIT-SUCCESS 4 | -------------------------------------------------------------------------------- /src/test/block_clone_checkpoint.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1') 8 | send_gdb('c') 9 | expect_gdb('Breakpoint 1') 10 | 11 | send_gdb('checkpoint') 12 | expect_gdb('Checkpoint 1') 13 | 14 | send_gdb('c') 15 | expect_gdb('Breakpoint 1') 16 | 17 | send_gdb('restart 1') 18 | expect_gdb('breakpoint') 19 | 20 | send_gdb('disable') 21 | send_gdb('c') 22 | expect_rr('EXIT-SUCCESS') 23 | 24 | ok() 25 | -------------------------------------------------------------------------------- /src/test/block_clone_checkpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | 4 | -------------------------------------------------------------------------------- /src/test/block_clone_interrupted.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="-c100" 4 | compare_test EXIT-SUCCESS 5 | 6 | -------------------------------------------------------------------------------- /src/test/block_clone_syscallbuf_overflow.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Use 4K syscallbuf size to force frequent overflows 4 | RECORD_ARGS=--syscall-buffer-size=4 5 | compare_test EXIT-SUCCESS 6 | 7 | -------------------------------------------------------------------------------- /src/test/block_intr_sigchld.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # The underlying failure here is difficult to reproduce without a lot 4 | # of tracee concurrency. 5 | RECORD_ARGS="-s" 6 | 7 | compare_test EXIT-SUCCESS 8 | -------------------------------------------------------------------------------- /src/test/blocked_bad_ip.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('c') 4 | expect_rr('EXIT-SUCCESS') 5 | expect_gdb('SIGSEGV') 6 | 7 | send_gdb('reverse-stepi') 8 | expect_gdb('SIGSEGV') 9 | 10 | send_gdb('reverse-stepi') 11 | expect_gdb('start_thread') 12 | 13 | ok() 14 | -------------------------------------------------------------------------------- /src/test/blocked_bad_ip.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/blocked_sigill.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | ( record $TESTNAME ) >& /dev/null 3 | replay 4 | check EXIT-SUCCESS 5 | -------------------------------------------------------------------------------- /src/test/break_block.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | 6 | for i in range(2): 7 | send_gdb('c') 8 | expect_gdb('Breakpoint 1, breakpoint') 9 | 10 | ok() 11 | -------------------------------------------------------------------------------- /src/test/break_block.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record block$bitness 3 | debug_gdb_only break_block 4 | -------------------------------------------------------------------------------- /src/test/break_clock.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | 6 | for i in range(3): 7 | send_gdb('c') 8 | expect_gdb('Breakpoint 1, breakpoint') 9 | 10 | ok() 11 | -------------------------------------------------------------------------------- /src/test/break_clock.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record clock$bitness 3 | debug_gdb_only break_clock 4 | -------------------------------------------------------------------------------- /src/test/break_clone.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | 6 | for i in range(3): 7 | send_gdb('c') 8 | expect_gdb('Breakpoint 1, breakpoint') 9 | 10 | ok() 11 | -------------------------------------------------------------------------------- /src/test/break_clone.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record clone$bitness 3 | debug_gdb_only break_clone 4 | -------------------------------------------------------------------------------- /src/test/break_exec.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record exec_self$bitness 3 | debug_gdb_only generic_break 4 | -------------------------------------------------------------------------------- /src/test/break_int3.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b int3.c:6') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1, breakpoint') 8 | 9 | ok() 10 | -------------------------------------------------------------------------------- /src/test/break_int3.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | record int3$bitness 4 | debug_gdb_only break_int3 5 | -------------------------------------------------------------------------------- /src/test/break_mmap_private.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | 6 | for i in range(3): 7 | send_gdb('c') 8 | expect_gdb('Breakpoint 1, breakpoint') 9 | 10 | ok() 11 | -------------------------------------------------------------------------------- /src/test/break_mmap_private.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record mmap_private$bitness 3 | debug_gdb_only break_mmap_private 4 | debug_gdb_only break_mmap_private --share-private-mappings 5 | -------------------------------------------------------------------------------- /src/test/break_msg.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record msg$bitness 3 | debug_gdb_only generic_break 4 | -------------------------------------------------------------------------------- /src/test/break_sigreturn.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record intr_sleep$bitness 3 | debug_gdb_only generic_break 4 | -------------------------------------------------------------------------------- /src/test/break_sync_signal.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record segfault$bitness 3 | debug_gdb_only generic_break 4 | -------------------------------------------------------------------------------- /src/test/break_thread.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record barrier$bitness 3 | debug_gdb_only generic_break 4 | -------------------------------------------------------------------------------- /src/test/break_time_slice.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1, breakpoint') 8 | 9 | send_gdb('c') 10 | expect_gdb('exited normally') 11 | 12 | ok() 13 | -------------------------------------------------------------------------------- /src/test/break_time_slice.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record chew_cpu$bitness 3 | debug_gdb_only break_time_slice 4 | -------------------------------------------------------------------------------- /src/test/breakpoint.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | breakpoint = breakpoint_at_function('C') 4 | cont() 5 | 6 | expect_rr('calling C') 7 | expect_breakpoint_stop(breakpoint) 8 | 9 | backtrace() 10 | expect_debugger('#0[^C]+C[^#]+#1[^B]+B[^#]+#2[^A]+A[^#]+#3.+main') 11 | 12 | ok() 13 | -------------------------------------------------------------------------------- /src/test/breakpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test 3 | -------------------------------------------------------------------------------- /src/test/breakpoint_conditions.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/breakpoint_consistent.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b C') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('b main') 7 | expect_gdb('Breakpoint 2') 8 | send_gdb('c') 9 | expect_gdb('Breakpoint 2, main') 10 | 11 | send_gdb('cond 1 rand()&1 < 10') 12 | 13 | send_gdb('c') 14 | 15 | expect_rr('calling C') 16 | 17 | expect_gdb('Breakpoint 1(.*) C') 18 | 19 | send_gdb('check') 20 | send_gdb('c') 21 | expect_rr('finished C') 22 | 23 | ok() 24 | -------------------------------------------------------------------------------- /src/test/breakpoint_consistent.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record breakpoint$bitness 3 | debug_gdb_only breakpoint_consistent 4 | -------------------------------------------------------------------------------- /src/test/breakpoint_overlap.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="-c100" 4 | record breakpoint_overlap$bitness 3 4 5 | # Don't use pipes here since we need 'debug' to run in the same bash process 6 | rr --suppress-environment-warnings dump $workdir/latest-trace > $workdir/plaintext-trace 7 | debug_gdb_only breakpoint_overlap < $workdir/plaintext-trace 8 | -------------------------------------------------------------------------------- /src/test/breakpoint_print.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | bp = breakpoint_at_function('main') 5 | set_breakpoint_commands(bp, ['print 123 + 456']) 6 | cont() 7 | expect_debugger('579') 8 | 9 | ok() 10 | -------------------------------------------------------------------------------- /src/test/breakpoint_print.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug breakpoint_print 4 | -------------------------------------------------------------------------------- /src/test/breakpoint_print_command.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('b main') 5 | expect_gdb('Breakpoint 1') 6 | send_gdb('commands 1') 7 | send_gdb('p 1234') 8 | send_gdb('end') 9 | send_gdb('c') 10 | expect_gdb('Breakpoint 1') 11 | expect_gdb('1234') 12 | 13 | ok() 14 | -------------------------------------------------------------------------------- /src/test/breakpoint_print_command.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only breakpoint_print_command 4 | -------------------------------------------------------------------------------- /src/test/call_exit.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only call_exit 4 | -------------------------------------------------------------------------------- /src/test/call_function.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/call_gettid.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | 7 | expect_gdb('Breakpoint 1, breakpoint') 8 | 9 | send_gdb('call check_pid()') 10 | expect_gdb('SUCCESS') 11 | 12 | send_gdb('c') 13 | expect_gdb('Breakpoint 1, breakpoint') 14 | 15 | send_gdb('call check_tid()') 16 | expect_gdb('SUCCESS') 17 | 18 | send_gdb('c') 19 | expect_rr('EXIT-SUCCESS') 20 | 21 | ok() 22 | -------------------------------------------------------------------------------- /src/test/call_gettid.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/chaos_oom.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="--chaos" 4 | compare_test EXIT-SUCCESS 5 | -------------------------------------------------------------------------------- /src/test/check_lost_interrupts.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static int dummy; 6 | 7 | static void do_some_ticks(void) { 8 | int i; 9 | for (i = 0; i < 1000; ++i) { 10 | dummy += i % 99; 11 | } 12 | } 13 | 14 | int main(void) { 15 | int i; 16 | 17 | for (i = 0; i < 100000; ++i) { 18 | do_some_ticks(); 19 | int fd = open("/dev/null", O_RDONLY); 20 | close(fd); 21 | } 22 | 23 | atomic_puts("EXIT-SUCCESS"); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /src/test/check_lost_interrupts.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | skip_if_no_syscall_buf 4 | 5 | RECORD_ARGS="-c10000" 6 | compare_test EXIT-SUCCESS 7 | 8 | -------------------------------------------------------------------------------- /src/test/check_patched_pthread.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('b main') 5 | expect_gdb('Breakpoint 1') 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1') 8 | 9 | send_gdb('p ((int*)&__elision_aconf)[2]') 10 | expect_gdb(re.compile(r'= 0|No symbol')) 11 | send_gdb('p/x *(char*)elision_init') 12 | expect_gdb(re.compile(r'= 0xc3|No symbol')) 13 | 14 | ok() 15 | -------------------------------------------------------------------------------- /src/test/check_patched_pthread.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record threads$bitness 3 | debug_gdb_only check_patched_pthread 4 | -------------------------------------------------------------------------------- /src/test/check_session_leaks.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('b atomic_puts') 5 | expect_gdb('Breakpoint 1') 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1') 8 | 9 | for i in range(1,100): 10 | send_gdb('checkpoint') 11 | expect_gdb('Checkpoint %d '%i) 12 | send_gdb('stepi') 13 | send_gdb('restart %d'%i) 14 | expect_gdb('stopped') 15 | send_gdb('delete checkpoint %d'%i) 16 | send_gdb('stepi') 17 | send_gdb('stepi') 18 | 19 | ok() 20 | -------------------------------------------------------------------------------- /src/test/check_session_leaks.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/checkpoint_dying_threads.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('checkpoint') 9 | send_gdb('c') 10 | expect_rr('EXIT-SUCCESS') 11 | expect_gdb('exited normally') 12 | 13 | ok() 14 | -------------------------------------------------------------------------------- /src/test/checkpoint_dying_threads.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | record $TESTNAME 4 | TARGET_PID=$(grep 'child ' record.out | awk '{print $2}') 5 | 6 | echo Targeting recorded pid $TARGET_PID ... 7 | debug_gdb_only checkpoint_dying_threads "-f $TARGET_PID" 8 | -------------------------------------------------------------------------------- /src/test/checkpoint_invalid.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only checkpoint_invalid 4 | -------------------------------------------------------------------------------- /src/test/checkpoint_mixed_mode.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('checkpoint') 9 | expect_gdb('Checkpoint 1 at') 10 | 11 | send_gdb('n') 12 | send_gdb('restart 1') 13 | expect_gdb('breakpoint') 14 | 15 | send_gdb('c') 16 | expect_rr('EXIT-SUCCESS') 17 | expect_gdb('xited normally') 18 | -------------------------------------------------------------------------------- /src/test/checkpoint_mixed_mode.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/checkpoint_mmap_shared.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | checkpoint_test mmap_shared$bitness 7 9 3 | -------------------------------------------------------------------------------- /src/test/checkpoint_prctl_name.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | checkpoint_test prctl_name$bitness 11 13 3 | -------------------------------------------------------------------------------- /src/test/checkpoint_simple.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | checkpoint_test simple$bitness 3 5 3 | -------------------------------------------------------------------------------- /src/test/checksum_block_open.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | GLOBAL_OPTIONS="$GLOBAL_OPTIONS --checksum=on-all-events" 3 | record block_open$bitness 4 | replay 5 | check EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/checksum_sanity.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | GLOBAL_OPTIONS="$GLOBAL_OPTIONS --checksum=on-all-events" 3 | record $TESTNAME 4 | replay 5 | check EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/checksum_sanity_noclone.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | GLOBAL_OPTIONS="$GLOBAL_OPTIONS --checksum=on-all-events" 3 | RECORD_ARGS="--no-read-cloning --no-file-cloning" 4 | record checksum_sanity$bitness 5 | replay 6 | check EXIT-SUCCESS 7 | -------------------------------------------------------------------------------- /src/test/clone_bad_stack.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int status = -1; 7 | 8 | if (syscall(SYS_clone, SIGCHLD, (intptr_t)-1, (intptr_t)-1, (intptr_t)-1, 9 | (intptr_t)-1) == 0) { 10 | _exit(0); 11 | } 12 | 13 | test_assert(wait(&status) >= 0); 14 | 15 | atomic_puts("EXIT-SUCCESS"); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/test/clone_file_range.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | export NONTMP_WORKDIR=$nontmp_workdir 3 | compare_test EXIT-SUCCESS 4 | -------------------------------------------------------------------------------- /src/test/clone_interruption.py: -------------------------------------------------------------------------------- 1 | import collections 2 | import sys 3 | import re 4 | from util import * 5 | 6 | send_gdb('checkpoint') 7 | expect_gdb('Checkpoint 1 at') 8 | 9 | send_gdb('n') 10 | send_gdb('restart 1') 11 | send_gdb('c') 12 | 13 | expect_rr('EXIT-SUCCESS') 14 | 15 | ok() 16 | -------------------------------------------------------------------------------- /src/test/clone_interruption.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="-c100" 4 | record $TESTNAME 5 | # Don't use pipes here since we need 'debug' to run in the same bash process 6 | declare -i stop_at_event=`rr --suppress-environment-warnings dump $workdir/latest-trace | \ 7 | python3 $TESTDIR/clone_interruption_finder.py` 8 | debug_gdb_only clone_interruption "-g $stop_at_event" 9 | -------------------------------------------------------------------------------- /src/test/clone_interruption_finder.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import re 3 | 4 | syscall_re = re.compile('`SIGNAL: ') 5 | time_re = re.compile(r'global_time:(\d+)') 6 | futex_time = 999999999 7 | 8 | while True: 9 | line = sys.stdin.readline() 10 | if not line: 11 | break 12 | if syscall_re.search(line): 13 | m = time_re.search(line) 14 | if m: 15 | futex_time = m.group(1) 16 | 17 | print(futex_time) 18 | -------------------------------------------------------------------------------- /src/test/clone_share_vm.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break break_function') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('check') 9 | expect_gdb('Checkpoint 1') 10 | send_gdb('next') 11 | send_gdb('restart 1') 12 | expect_gdb('break_function') 13 | 14 | send_gdb('continue') 15 | expect_rr('EXIT-SUCCESS') 16 | 17 | ok() 18 | -------------------------------------------------------------------------------- /src/test/clone_share_vm.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/clone_syscallbuf_cleanup_blocked.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | skip_if_no_syscall_buf 3 | record $TESTNAME 4 | replay 5 | -------------------------------------------------------------------------------- /src/test/clone_syscallbuf_cleanup_cpu.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | skip_if_no_syscall_buf 3 | record $TESTNAME 4 | replay 5 | -------------------------------------------------------------------------------- /src/test/clone_vfork.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | save_exe simple$bitness 4 | record $TESTNAME simple$bitness-$nonce 5 | replay 6 | check clone-vfork-EXIT-SUCCESS 7 | -------------------------------------------------------------------------------- /src/test/close_range.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int ret = syscall(RR_close_range, 1, UINT32_MAX, 0); 7 | test_assert(ret == -1 && errno == ENOSYS); 8 | atomic_puts("EXIT-SUCCESS"); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/test/comm.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('info threads') 5 | expect_gdb(r'1\s+Thread \d+\.\d+ \(simple(_32)?-[A-Za-z0-9]+\)') 6 | 7 | ok() 8 | -------------------------------------------------------------------------------- /src/test/comm.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only comm 4 | -------------------------------------------------------------------------------- /src/test/conditional_breakpoint_calls.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int counter; 6 | int dot_counter; 7 | 8 | int checker(void) { 9 | ++counter; 10 | return 0; 11 | } 12 | 13 | static void print_dot(void) { 14 | atomic_printf("."); 15 | ++dot_counter; 16 | } 17 | 18 | int main(void) { 19 | int i; 20 | 21 | for (i = 0; i < 10; ++i) { 22 | print_dot(); 23 | } 24 | 25 | atomic_puts("\nEXIT-SUCCESS"); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /src/test/conditional_breakpoint_calls.py: -------------------------------------------------------------------------------- 1 | import re 2 | from util import * 3 | 4 | send_gdb('b print_dot if checker()') 5 | expect_gdb('Breakpoint 1') 6 | send_gdb('watch dot_counter if checker()') 7 | expect_gdb('Hardware watchpoint 2') 8 | send_gdb('c') 9 | expect_rr('EXIT-SUCCESS') 10 | 11 | ok() 12 | -------------------------------------------------------------------------------- /src/test/conditional_breakpoint_calls.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/conditional_breakpoint_offload.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void breakpoint(void) { 6 | int break_here = 1; 7 | (void)break_here; 8 | } 9 | 10 | static int var; 11 | 12 | int main(void) { 13 | int i; 14 | 15 | for (i = 0; i < 5000; ++i) { 16 | ++var; 17 | breakpoint(); 18 | } 19 | 20 | atomic_puts("EXIT-SUCCESS"); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /src/test/conditional_breakpoint_offload.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('handle SIGKILL stop') 4 | 5 | send_gdb('b breakpoint') 6 | expect_gdb('Breakpoint 1') 7 | send_gdb('cond 1 var==-1') 8 | 9 | send_gdb('b main') 10 | expect_gdb('Breakpoint 2') 11 | 12 | send_gdb('c') 13 | expect_gdb('Breakpoint 2') 14 | send_gdb('c') 15 | # This should complete in a reasonable amount of time! 16 | expect_gdb('SIGKILL') 17 | 18 | send_gdb('reverse-continue') 19 | # And so should this! 20 | expect_gdb('Breakpoint 2') 21 | 22 | ok() 23 | -------------------------------------------------------------------------------- /src/test/conditional_breakpoint_offload.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | if [ $TIMEOUT -lt 300 ]; then TIMEOUT=300; fi 3 | debug_test_gdb_only 4 | -------------------------------------------------------------------------------- /src/test/condvar_stress.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Switch threads very eagerly on recorded events. 4 | RECORD_ARGS="-s" 5 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 6 | compare_test EXIT-SUCCESS 7 | -------------------------------------------------------------------------------- /src/test/constructor.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | void lib_exit_success(void); 6 | 7 | int main(void) { 8 | struct timespec ts = { 1, 0 }; 9 | /* try patching clock_nanosleep, which a library thread is in */ 10 | clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); 11 | nanosleep(&ts, NULL); 12 | 13 | lib_exit_success(); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/test/cont_race.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | if [ $TIMEOUT -lt 300 ]; then TIMEOUT=300; fi 3 | ${OBJDIR}/bin/cont_race$bitness killer & 4 | compare_test EXIT-SUCCESS 5 | -------------------------------------------------------------------------------- /src/test/cont_signal.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('c') 5 | index = expect_list([re.compile(r'exited normally'), re.compile(r'Program received signal SIGUSR1')]) 6 | 7 | if index == 1: 8 | send_gdb('c') 9 | expect_gdb('exited normally') 10 | 11 | ok() 12 | -------------------------------------------------------------------------------- /src/test/cont_signal.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | recorded_exe=async_usr1$bitness 4 | 5 | # SIGUSR1, wait 2.0s 6 | record_async_signal 10 2.0 $recorded_exe 7 | debug_gdb_only $TESTNAME_NO_BITNESS 8 | -------------------------------------------------------------------------------- /src/test/context_switch_after_patch.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="--always-switch" 4 | compare_test EXIT-SUCCESS 5 | 6 | -------------------------------------------------------------------------------- /src/test/copy_all.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | ok() 4 | -------------------------------------------------------------------------------- /src/test/copy_all.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | RR_COPY_ALL_FILES=1 record simple$bitness 3 | debug_gdb_only copy_all 4 | -------------------------------------------------------------------------------- /src/test/crash.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | volatile int* p = NULL; 7 | *p = 42; 8 | test_assert("Not reached" && 0); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/test/crash.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | record crash$bitness 4 | replay 5 | check '' 6 | -------------------------------------------------------------------------------- /src/test/crash_in_function.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | void crash(void) { crash_null_deref(); } 6 | 7 | int main(void) { 8 | atomic_puts("EXIT-SUCCESS"); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/test/crash_in_function.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/daemon_read.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="-c1000" 4 | compare_test EXIT-SUCCESS 5 | 6 | -------------------------------------------------------------------------------- /src/test/dconf_mock.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | record $TESTNAME & 4 | 5 | until grep -q ready record.out; do 6 | sleep 0 7 | done 8 | 9 | ${OBJDIR}/bin/$TESTNAME mock_dconf_update 10 | 11 | # Wait for 'record' to actually terminate. Otherwise we might start 12 | # replaying before the trace file has been completely written. 13 | wait %1 14 | 15 | echo "Replaying ..." 16 | replay 17 | check 'EXIT-SUCCESS' 18 | 19 | -------------------------------------------------------------------------------- /src/test/dead_thread_target.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record barrier$bitness 3 | debug_gdb_only dead_thread_target 4 | -------------------------------------------------------------------------------- /src/test/desched_ticks.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Without the syscallbuf, this test makes no sense 4 | # and will fail since it sets a breakpoint in the preload code. 5 | skip_if_no_syscall_buf 6 | 7 | record desched_blocking_poll$bitness 8 | debug_gdb_only desched_ticks 9 | -------------------------------------------------------------------------------- /src/test/detach_terminal.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | skip_if_test_32_bit 3 | actual_rr=$(which $RR_EXE) 4 | RR_EXE="detach_terminal$bitness --newtty $actual_rr" 5 | just_record detach_terminal$bitness "--newpgrp $actual_rr record --nested=release detach_terminal$bitness" 6 | replay 7 | check_record EXIT-SUCCESS 8 | -------------------------------------------------------------------------------- /src/test/dev_tty.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd = open("/dev/tty", O_RDWR); 7 | if (fd == -1 && errno == ENXIO) { 8 | atomic_puts("/dev/tty does not exist, skipping test"); 9 | fd = STDERR_FILENO; 10 | } else { 11 | test_assert(fd >= 0); 12 | } 13 | test_assert(13 == write(fd, "EXIT-SUCCESS\n", 13)); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/test/dev_tty.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record $TESTNAME 3 | replay 4 | token=EXIT-SUCCESS 5 | if [[ "replay.err" != $(grep -l $token replay.err) ]]; then 6 | failed ": token '$token' not in replay.err:" 7 | echo "--------------------------------------------------" 8 | cat replay.err 9 | echo "--------------------------------------------------" 10 | cat replay.out 11 | echo "--------------------------------------------------" 12 | else 13 | passed 14 | fi 15 | -------------------------------------------------------------------------------- /src/test/dev_zero.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd = open("/dev/zero", O_RDONLY); 7 | test_assert(fd >= 0); 8 | void* ptr = mmap(NULL, 0x200000, PROT_READ, MAP_PRIVATE, fd, 0); 9 | test_assert(ptr != NULL); 10 | atomic_puts("EXIT-SUCCESS"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/test/diversion_sigtrap.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static __attribute__((noinline)) void breakpoint(void) { 6 | int break_here = 1; 7 | (void)break_here; 8 | } 9 | 10 | static __attribute__((noinline)) int hardware_breakpoint(void) { 11 | debug_trap(); 12 | return 10; 13 | } 14 | 15 | int main(void) { 16 | breakpoint(); 17 | hardware_breakpoint(); 18 | } 19 | -------------------------------------------------------------------------------- /src/test/diversion_sigtrap.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re, sys 3 | 4 | send_gdb('b breakpoint') 5 | expect_gdb('Breakpoint 1') 6 | 7 | send_gdb('c') 8 | expect_gdb('Breakpoint 1') 9 | 10 | send_gdb('p hardware_breakpoint()') 11 | expect_gdb('received signal SIGTRAP') 12 | -------------------------------------------------------------------------------- /src/test/diversion_sigtrap.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record $TESTNAME 3 | debug_test_gdb_only 4 | -------------------------------------------------------------------------------- /src/test/diversion_syscall.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record $TESTNAME 3 | debug_test_gdb_only 4 | token=DIVERSION-SUCCESS 5 | if [[ "diversion_print.out" != $(grep -l $token diversion_print.out) ]]; then 6 | failed ": token '$token' not written to file by diversion" 7 | else 8 | passed 9 | fi 10 | -------------------------------------------------------------------------------- /src/test/dlopen.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | void* h = dlopen("libX11.so", RTLD_LAZY); 7 | if (h) { 8 | dlclose(h); 9 | } 10 | atomic_puts("EXIT-SUCCESS"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/test/dlopen.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('handle SIGKILL stop') 4 | send_gdb('c') 5 | expect_gdb('EXIT-SUCCESS') 6 | expect_gdb('SIGKILL') 7 | send_gdb('reverse-continue') 8 | expect_history_end() 9 | 10 | ok() 11 | -------------------------------------------------------------------------------- /src/test/dlopen.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | 4 | -------------------------------------------------------------------------------- /src/test/early_error.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | save_exe "$TESTNAME" 3 | _RR_TRACE_DIR="$workdir" test-monitor $TIMEOUT record.err "./$TESTNAME-$nonce" \ 4 | $(which rr) $GLOBAL_OPTIONS record $LIB_ARG $RECORD_ARGS "./$TESTNAME-$nonce" \ 5 | || failed "didn't get expected startup error" 6 | -------------------------------------------------------------------------------- /src/test/elapsed_time.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void breakpoint(void) { 6 | int break_here = 1; 7 | (void)break_here; 8 | } 9 | 10 | int main(void){ 11 | sleep(1); 12 | 13 | breakpoint(); 14 | 15 | atomic_puts("EXIT-SUCCESS"); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/test/elapsed_time.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/env_newline.run: -------------------------------------------------------------------------------- 1 | export BADENV='hello 2 | kitty' 3 | source `dirname $0`/util.sh 4 | compare_test EXIT-SUCCESS "" simple$bitness 5 | -------------------------------------------------------------------------------- /src/test/epoll_create.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd; 7 | 8 | fd = epoll_create(1); 9 | atomic_printf("New epoll file descriptor: %d\n", fd); 10 | 11 | if (fd >= 0) { 12 | atomic_puts("EXIT-SUCCESS"); 13 | } 14 | 15 | close(fd); 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/test/epoll_create1.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd; 7 | 8 | fd = epoll_create1(0); 9 | atomic_printf("New epoll file descriptor: %d\n", fd); 10 | 11 | if (fd >= 0) { 12 | atomic_puts("EXIT-SUCCESS"); 13 | } 14 | 15 | close(fd); 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/test/exclusion_region.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS=--chaos 4 | compare_test EXIT-SUCCESS 5 | -------------------------------------------------------------------------------- /src/test/exec_deleted.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | file=simple$bitness 4 | cp ${OBJDIR}/bin/$file $file-$nonce 5 | just_record ./$file-$nonce 6 | rm $file-$nonce 7 | replay 8 | check 'EXIT-SUCCESS' 9 | -------------------------------------------------------------------------------- /src/test/exec_failed.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void breakpoint(void) { 6 | int break_here = 1; 7 | (void)break_here; 8 | } 9 | 10 | int main(void) { 11 | execlp("/asdjfklajdfkla", "", NULL); 12 | 13 | breakpoint(); 14 | 15 | atomic_puts("EXIT-SUCCESS"); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/test/exec_failed.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | ok() 9 | 10 | -------------------------------------------------------------------------------- /src/test/exec_failed.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/exec_many.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | int count; 7 | test_assert(argc <= 2); 8 | count = argc == 1 ? 100 : atoi(argv[1]); 9 | 10 | if (count > 0) { 11 | char buf[1000]; 12 | sprintf(buf, "%d", count - 1); 13 | execlp(argv[0], argv[0], buf, NULL); 14 | test_assert("Not reached" && 0); 15 | } 16 | 17 | atomic_puts("EXIT-SUCCESS"); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /src/test/exec_many.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | ulimit -n 1024 4 | RECORD_ARGS="--scarce-fds" 5 | compare_test EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/exec_no_env.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(int argc, char** argv) { 6 | if (argc == 1) { 7 | char* args[] = { argv[0], "hello", NULL }; 8 | char* envp[] = { NULL }; 9 | execve(argv[0], args, envp); 10 | test_assert(0); 11 | return 0; 12 | } 13 | 14 | atomic_puts("EXIT-SUCCESS"); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/exec_shared_as.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | save_exe exit_fast$bitness 4 | record $TESTNAME exit_fast$bitness-$nonce 5 | replay 6 | check EXIT-SUCCESS 7 | -------------------------------------------------------------------------------- /src/test/exec_stop.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('c') 4 | expect_gdb('stopped') 5 | send_gdb('stepi') 6 | expect_gdb('stopped') 7 | send_gdb('stepi') 8 | expect_gdb('stopped') 9 | send_gdb('c') 10 | expect_gdb('stopped') 11 | send_gdb('b execve') 12 | expect_gdb('Breakpoint 1') 13 | send_gdb('rc') 14 | expect_gdb('Breakpoint 1') 15 | 16 | ok() 17 | -------------------------------------------------------------------------------- /src/test/exec_stop.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record exec_self$bitness 3 | debug_gdb_only exec_stop 4 | -------------------------------------------------------------------------------- /src/test/execp.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | exe=simple$bitness 4 | cp ${OBJDIR}/bin/$exe $exe-$nonce 5 | PATH="${PATH}:." just_record $exe-$nonce 6 | replay 7 | check 'EXIT-SUCCESS' 8 | -------------------------------------------------------------------------------- /src/test/execve_failed.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | _RR_TRACE_DIR="$workdir" $RR_EXE record program_that_does_not_exist 3 | exit_code=$? 4 | if [[ $exit_code != 69 ]]; then 5 | failed "Got exit code $exit_code, expected 69" 6 | fi 7 | -------------------------------------------------------------------------------- /src/test/execve_loop.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | record $TESTNAME 100 & 4 | 5 | for i in $(seq 1 30); do 6 | sleep 0.01 7 | kill -CHLD $rrpid $(pidof $TESTNAME-$nonce) >& /dev/null 8 | done 9 | 10 | # Wait for 'record' to actually terminate. Otherwise we might start 11 | # replaying before the trace file has been completely written. 12 | wait 13 | 14 | echo "Replaying ..." 15 | replay 16 | check 'EXIT-SUCCESS' 17 | -------------------------------------------------------------------------------- /src/test/exit_codes.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | int cmd; 7 | test_assert(argc == 2); 8 | cmd = atoi(argv[1]); 9 | 10 | if (cmd < 0) { 11 | kill(getpid(), -cmd); 12 | return 0; 13 | } 14 | 15 | return cmd; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/exit_codes.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | record $TESTNAME 3 4 | if [[ $? != 3 ]]; then 5 | failed "Expected exit code 3" 6 | fi 7 | 8 | ( record $TESTNAME -5 ) 9 | if [[ $? != 133 ]]; then 10 | failed "Expected exit signal 5" 11 | fi 12 | 13 | -------------------------------------------------------------------------------- /src/test/exit_fast.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util_syscall.h" 4 | 5 | void _start(void) { 6 | unbufferable_syscall(RR_exit, 77, 0, 0); 7 | } 8 | -------------------------------------------------------------------------------- /src/test/exit_group.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | compare_test '_exit()ing' 3 | -------------------------------------------------------------------------------- /src/test/exit_race.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="--chaos -c100" 4 | compare_test EXIT-SUCCESS 5 | -------------------------------------------------------------------------------- /src/test/exit_status.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { return 7; } 6 | -------------------------------------------------------------------------------- /src/test/exit_status.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record exit_status$bitness 3 | if [[ $? != 7 ]]; then 4 | failed "got exit status $?, expected 7" 5 | else 6 | passed 7 | fi 8 | -------------------------------------------------------------------------------- /src/test/expect_in_atomic_printf.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('bt') 5 | expect_gdb('atomic_printf') 6 | 7 | ok() 8 | -------------------------------------------------------------------------------- /src/test/expect_in_exit.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('reverse-stepi') 5 | send_gdb('bt') 6 | expect_gdb('_exit') 7 | 8 | ok() 9 | -------------------------------------------------------------------------------- /src/test/explicit_checkpoint_clone.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record clone$bitness 3 | debug_gdb_only explicit_checkpoint_clone 4 | -------------------------------------------------------------------------------- /src/test/fcntl_dupfd.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd; 7 | 8 | fd = fcntl(1, F_DUPFD, 3); 9 | test_assert(fd >= 3); 10 | close(1); 11 | 12 | fd = dup2(fd, 1); 13 | test_assert(fd == 1); 14 | 15 | atomic_puts("EXIT-SUCCESS"); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/test/fcntl_lease.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0600); 7 | test_assert(fd >= 0); 8 | int ret = fcntl(fd, F_SETLEASE, F_WRLCK); 9 | test_assert(!ret); 10 | ret = fcntl(fd, F_GETLEASE); 11 | test_assert(ret == F_WRLCK); 12 | 13 | atomic_puts("EXIT-SUCCESS"); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/test/fcntl_sig.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | test_assert(0 == fcntl(1, F_SETSIG, SIGCHLD)); 7 | test_assert(SIGCHLD == fcntl(1, F_GETSIG, 0)); 8 | 9 | atomic_puts("EXIT-SUCCESS"); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/test/fd_limit.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | ulimit -S -n 1024 3 | compare_test EXIT-SUCCESS 4 | -------------------------------------------------------------------------------- /src/test/fd_tracking_across_threads.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void* start_thread(__attribute__((unused)) void* p) { 6 | test_assert(11 == dup2(STDOUT_FILENO, 11)); 7 | test_assert(14 == write(11, "EXIT-SUCCESS\n", 14)); 8 | 9 | return NULL; 10 | } 11 | 12 | int main(void) { 13 | pthread_t thread; 14 | 15 | pthread_create(&thread, NULL, start_thread, NULL); 16 | pthread_exit(NULL); 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /src/test/fds_clean.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd; 7 | 8 | for (fd = 3; fd < 100; ++fd) { 9 | /* Check that |fd| is available to us. */ 10 | test_assert(dup2(2, fd) == fd); 11 | } 12 | 13 | atomic_puts("EXIT-SUCCESS"); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/test/file_name_newline.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | exe=simple$bitness 4 | cp ${OBJDIR}/bin/$exe "foo 5 | bar" 6 | just_record "foo 7 | bar" 8 | replay 9 | check 'EXIT-SUCCESS' 10 | (rr --suppress-environment-warnings dump -b -m -p ./latest-trace|grep -q ^bar) || failed "Can't find proper name" 11 | -------------------------------------------------------------------------------- /src/test/final_sigkill.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('handle SIGKILL stop') 5 | send_gdb('c') 6 | expect_gdb('received signal SIGKILL') 7 | 8 | restart_replay() 9 | expect_gdb('received signal SIGKILL') 10 | 11 | send_gdb('c') 12 | expect_gdb('exited normally') 13 | 14 | ok() 15 | -------------------------------------------------------------------------------- /src/test/final_sigkill.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only final_sigkill 4 | -------------------------------------------------------------------------------- /src/test/first_instruction.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('disass') 4 | expect_gdb('function _start') 5 | 6 | ok() 7 | -------------------------------------------------------------------------------- /src/test/first_instruction.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record rr_exec_stub$bitness 3 | debug_gdb_only first_instruction 4 | -------------------------------------------------------------------------------- /src/test/fork_brk.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | pid_t child = fork(); 7 | int status; 8 | 9 | if (!child) { 10 | sbrk(100000); 11 | return 77; 12 | } 13 | test_assert(child == wait(&status)); 14 | test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77); 15 | atomic_puts("EXIT-SUCCESS"); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/test/fork_stress.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | #define NUM_ITERATIONS 250 6 | 7 | int main(void) { 8 | int i; 9 | 10 | for (i = 0; i < NUM_ITERATIONS; ++i) { 11 | pid_t child = fork(); 12 | if (0 == child) { 13 | return 0; 14 | } 15 | if (0 > child) { 16 | atomic_printf("Fork failed with errno %d\n", errno); 17 | } 18 | } 19 | 20 | atomic_puts("EXIT-SUCCESS"); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /src/test/fork_stress.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 4 | compare_test EXIT-SUCCESS 5 | -------------------------------------------------------------------------------- /src/test/fork_syscalls.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | compare_test "CHILD-EXIT PARENT-EXIT" 3 | -------------------------------------------------------------------------------- /src/test/function_calls.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break main') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('n'); 9 | send_gdb('n'); 10 | send_gdb('reverse-next'); 11 | send_gdb('c'); 12 | 13 | expect_gdb('exited normally') 14 | 15 | ok() 16 | -------------------------------------------------------------------------------- /src/test/function_calls.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/futex_invalid_op.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | uint32_t ftx; 7 | int ret = syscall(SYS_futex, &ftx, 0x70, 0, NULL, NULL, 0); 8 | test_assert(ret < 0); 9 | test_assert(errno == ENOSYS); 10 | atomic_puts("EXIT-SUCCESS"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/test/gdb_bogus_breakpoint.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break my_write') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('s') 9 | 10 | send_gdb('c') 11 | # First E may be printed by itself during 's' 12 | expect_rr('XIT-SUCCESS') 13 | expect_gdb('exited normally') 14 | 15 | ok() 16 | -------------------------------------------------------------------------------- /src/test/gdb_bogus_breakpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/gdb_qpasssignals.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | static unsigned count = 0; 4 | 5 | void sig_handler(int sigNum) { 6 | (void)sigNum; 7 | ++count; 8 | } 9 | 10 | int main(void) { 11 | atomic_puts("XIT-START"); 12 | test_assert(signal(SIGURG, sig_handler) != SIG_ERR); 13 | 14 | for (int i = 0; i < 10 * 1000; ++i) { 15 | raise(SIGURG); 16 | } 17 | 18 | atomic_puts("XIT-END"); 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /src/test/gdb_qpasssignals.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('handle SIGURG noprint nostop pass') 4 | send_gdb('handle SIGKILL stop') 5 | 6 | send_gdb('c') 7 | 8 | 9 | expect_rr('XIT-END') 10 | 11 | send_gdb('b main') 12 | expect_gdb('Breakpoint 1') 13 | send_gdb('reverse-continue') 14 | 15 | expect_gdb('Breakpoint 1') 16 | ok() -------------------------------------------------------------------------------- /src/test/gdb_qpasssignals.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 4 | debug_test_gdb_only 5 | -------------------------------------------------------------------------------- /src/test/generic_break.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1, breakpoint') 8 | 9 | ok() 10 | -------------------------------------------------------------------------------- /src/test/get_thread_list.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record barrier$bitness 3 | debug_gdb_only get_thread_list 4 | -------------------------------------------------------------------------------- /src/test/getcwd.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | record $TESTNAME "$PWD" 4 | replay 5 | check EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/getgroups.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | gid_t groups[1024]; 7 | int num_groups = getgroups(ALEN(groups), groups); 8 | int i; 9 | 10 | atomic_printf("User %d belongs to %d groups:\n ", geteuid(), num_groups); 11 | for (i = 0; i < num_groups; ++i) { 12 | atomic_printf("%d,", groups[i]); 13 | } 14 | atomic_puts(""); 15 | 16 | atomic_puts("EXIT-SUCCESS"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/test/getpwnam.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | struct passwd* p = getpwnam("root"); 7 | atomic_printf("%d\n", p ? p->pw_uid : 0); 8 | atomic_puts("EXIT-SUCCESS"); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/test/getsid.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | pid_t sid = getsid(0); 7 | atomic_printf("getsid(0) session ID: %d\n", sid); 8 | test_assert(sid >= 0); 9 | 10 | atomic_puts("EXIT-SUCCESS"); 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/test/gettimeofday.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | struct timeval* tv; 7 | struct timezone* tz; 8 | 9 | ALLOCATE_GUARD(tv, 0); 10 | ALLOCATE_GUARD(tz, 'x'); 11 | test_assert(0 == gettimeofday(tv, tz)); 12 | test_assert(tv->tv_sec > 0); 13 | test_assert(tz->tz_dsttime == 0); /* always zero on Linux */ 14 | VERIFY_GUARD(tv); 15 | VERIFY_GUARD(tz); 16 | 17 | atomic_puts("EXIT-SUCCESS"); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /src/test/goto_event.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | export EVENTS=1000 4 | record $TESTNAME $EVENTS 5 | 6 | debug_gdb_only goto_event "-g $EVENTS" 7 | -------------------------------------------------------------------------------- /src/test/hardlink_mmapped_files.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | cp $OBJDIR/lib/rr/libtest_lib$bitness.so . 4 | 5 | RECORD_ARGS="--env=LD_PRELOAD=libtest_lib$bitness.so" 6 | record constructor$bitness 7 | rm libtest_lib$bitness.so 8 | replay 9 | check EXIT-SUCCESS 10 | -------------------------------------------------------------------------------- /src/test/hbreak.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('break atomic_puts') 5 | expect_gdb('Breakpoint 1') 6 | send_gdb('continue') 7 | expect_gdb('Breakpoint 1') 8 | send_gdb('hbreak main') 9 | expect_gdb('breakpoint 2') 10 | send_gdb('reverse-continue') 11 | expect_gdb('Breakpoint 2') 12 | 13 | ok() 14 | -------------------------------------------------------------------------------- /src/test/hbreak.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only hbreak 4 | -------------------------------------------------------------------------------- /src/test/hello.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(int argc, char *argv[]) { 6 | if (argc <= 1) { 7 | atomic_puts("Hi"); 8 | } else { 9 | atomic_puts(argv[1]); 10 | } 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/test/hello.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | compare_test 'Hi' 3 | -------------------------------------------------------------------------------- /src/test/history.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void breakpointA(__attribute__((unused)) int i) { 6 | int break_here = 1; 7 | (void)break_here; 8 | } 9 | 10 | int main(void) { 11 | int i; 12 | for (i = 0; i < 5; ++i) { 13 | breakpointA(i); 14 | } 15 | atomic_puts("EXIT-SUCCESS"); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/test/history.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/hooks.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # This test requires syscallbuf syscall patching 4 | skip_if_no_syscall_buf 5 | compare_test EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/ignore_nested.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | // This simply execs the commands passed to it on 4 | // the command line without passing through the 5 | // environment. The runner uses this to test 6 | // --nested=ignore in the absence of RR_UNDER_RR 7 | // environment variable. 8 | int main(int argc, char *argv[]) { 9 | if (argc > 1 && strcmp(argv[1], "--inner") == 0) { 10 | atomic_puts("EXIT-SUCCESS"); 11 | return 0; 12 | } 13 | char *newenv[] = { NULL }; 14 | return execve(argv[1], &argv[1], newenv); 15 | } 16 | -------------------------------------------------------------------------------- /src/test/ignore_nested.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record $TESTNAME "$(which rr) record --nested=ignore $PWD/$TESTNAME-$nonce --inner" 3 | replay 4 | check 'EXIT-SUCCESS' 5 | -------------------------------------------------------------------------------- /src/test/ignored_sigsegv.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | ( record $TESTNAME ) >& /dev/null 3 | replay 4 | check EXIT-SUCCESS 5 | -------------------------------------------------------------------------------- /src/test/immediate_restart.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int child; 7 | 8 | atomic_printf("%d: forking...\n", getpid()); 9 | if (0 == (child = fork())) { 10 | atomic_puts("EXIT-SUCCESS"); 11 | return 0; 12 | } 13 | 14 | atomic_printf("child %d\n", child); 15 | 16 | waitpid(child, NULL, 0); 17 | 18 | atomic_puts("EXIT-SUCCESS"); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /src/test/immediate_restart.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | restart_replay() 4 | # A single EXIT-SUCCESS is expected since the child process to which we have 5 | # attached only prints one, and it exits before the parent prints its 6 | # EXIT-SUCCESS. 7 | expect_rr('EXIT-SUCCESS') 8 | 9 | ok() 10 | -------------------------------------------------------------------------------- /src/test/immediate_restart.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | record $TESTNAME 4 | TARGET_PID=$(grep 'child ' record.out | awk '{print $2}') 5 | 6 | echo Targeting recorded pid $TARGET_PID ... 7 | debug_gdb_only immediate_restart "-f $TARGET_PID" 8 | -------------------------------------------------------------------------------- /src/test/interrupt.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | void spin(void) { 6 | int i; 7 | 8 | atomic_puts("spinning"); 9 | for (i = 1; i < (1 << 30); ++i) { 10 | if (0 == i % (1 << 20)) { 11 | write(STDOUT_FILENO, ".", 1); 12 | } 13 | if (0 == i % (79 * (1 << 20))) { 14 | write(STDOUT_FILENO, "\n", 1); 15 | } 16 | } 17 | } 18 | 19 | int main(void) { 20 | spin(); 21 | atomic_puts("done"); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /src/test/interrupt.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | # XXX this test is racy, because we don't have a way to halt replay 4 | # until some condition is satisfied. Maybe we should add that. 5 | send_gdb('c') 6 | expect_rr('spinning') 7 | interrupt_gdb() 8 | 9 | ok() 10 | -------------------------------------------------------------------------------- /src/test/interrupt.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/intr_ptrace_decline.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Ignore SIGUSR1; block its delivery to tracees. 4 | RECORD_ARGS="-i10" 5 | 6 | compare_test EXIT-SUCCESS 7 | -------------------------------------------------------------------------------- /src/test/invalid_fcntl.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | /* Do an invalid fcntl command on valid fd 0 */ 7 | test_assert(-1 == fcntl(0, 9999)); 8 | test_assert(errno == EINVAL); 9 | atomic_puts("EXIT-SUCCESS"); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/test/invalid_interpreter.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | send_gdb('checkpoint') 8 | expect_gdb('Checkpoint 1 at') 9 | send_gdb('restart 1') 10 | expect_gdb('stopped') 11 | 12 | ok() 13 | -------------------------------------------------------------------------------- /src/test/invalid_interpreter.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record invalid_interpreter$bitness 3 | debug_gdb_only invalid_interpreter 4 | -------------------------------------------------------------------------------- /src/test/invalid_ioctl.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | // Test invalid fd -1, to make sure that rr doesn't accidentally think 7 | // this is it's desched fd (esp. when syscallbuf is disabled). 8 | test_assert(-1 == ioctl(-1, PERF_EVENT_IOC_ENABLE)); 9 | test_assert(errno == EBADF); 10 | atomic_puts("EXIT-SUCCESS"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/test/invalid_jump.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('c') 4 | expect_gdb('Program received signal SIGSEGV') 5 | 6 | send_gdb('rsi') 7 | send_gdb('rsi') 8 | 9 | expect_gdb('main ()') 10 | 11 | ok() 12 | -------------------------------------------------------------------------------- /src/test/invalid_jump.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record invalid_jump$bitness 3 | debug_gdb_only invalid_jump 4 | -------------------------------------------------------------------------------- /src/test/io.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | char buf[32]; 7 | int garbage_fd = 1 << 30; 8 | 9 | read(garbage_fd, buf, sizeof(buf)); 10 | 11 | atomic_puts("EXIT-SUCCESS"); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/test/jit_proc_mem.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | send_gdb('c') 8 | expect_gdb('Breakpoint 1') 9 | send_gdb('up') 10 | send_gdb('b *space') 11 | expect_gdb('Breakpoint 2') 12 | 13 | # Should hit breakpoint 2 here rather than making it all the way back to 14 | # the first instance of breakpoint 1. 15 | send_gdb('rc') 16 | expect_gdb('Breakpoint 2') 17 | 18 | ok() 19 | -------------------------------------------------------------------------------- /src/test/jit_proc_mem.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record jit_proc_mem$bitness 3 | debug_gdb_only jit_proc_mem 4 | -------------------------------------------------------------------------------- /src/test/large_file.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | skip_if_rr_32_bit 4 | exe=simple$bitness 5 | cp ${OBJDIR}/bin/$exe $exe-$nonce 6 | truncate -s 2G $exe-$nonce 7 | PATH="${PATH}:." just_record $exe-$nonce 8 | replay 9 | check 'EXIT-SUCCESS' 10 | -------------------------------------------------------------------------------- /src/test/link.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | # NB: this test creates garbage, but it will be cleaned up along with 3 | # the other files in the tmp dir. 4 | compare_test 'EXIT-SUCCESS' 5 | -------------------------------------------------------------------------------- /src/test/madvise_dontfork.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('checkpoint') 9 | expect_gdb('Checkpoint 1 at') 10 | send_gdb('next') 11 | 12 | send_gdb('restart 1') 13 | expect_gdb('stopped') 14 | send_gdb('c') 15 | expect_rr('EXIT-SUCCESS') 16 | 17 | ok() 18 | -------------------------------------------------------------------------------- /src/test/madvise_dontfork.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/madvise_fracture_flags.run: -------------------------------------------------------------------------------- 1 | NO_CHECK_CACHED_MMAP=1 2 | source `dirname $0`/util.sh 3 | skip_if_no_syscall_buf 4 | compare_test EXIT-SUCCESS 5 | -------------------------------------------------------------------------------- /src/test/madvise_free.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | size_t page_size = sysconf(_SC_PAGESIZE); 7 | void* p = 8 | mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 9 | test_assert(p != MAP_FAILED); 10 | 11 | test_assert(-1 == madvise(p, page_size, MADV_FREE)); 12 | 13 | atomic_puts("EXIT-SUCCESS"); 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/main_thread_exit.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('checkpoint') 9 | send_gdb('n') 10 | send_gdb('restart 1') 11 | send_gdb('c') 12 | expect_rr('EXIT-SUCCESS') 13 | expect_gdb('exited normally') 14 | 15 | ok() 16 | -------------------------------------------------------------------------------- /src/test/main_thread_exit.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/memfd_create_efault.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd; 7 | 8 | /* There's no libc helper for this syscall. */ 9 | fd = syscall(RR_memfd_create, NULL, 0); 10 | if (ENOSYS == errno) { 11 | atomic_puts("SYS_memfd_create not supported on this kernel"); 12 | } else { 13 | test_assert(fd == -1); 14 | test_assert(errno == EFAULT); 15 | } 16 | 17 | atomic_puts("EXIT-SUCCESS"); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /src/test/mmap_fd_reuse_checkpoint.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break do_checkpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | send_gdb('checkpoint') 8 | expect_gdb('Checkpoint 1') 9 | send_gdb('c') 10 | expect_gdb('xited normally') 11 | send_gdb('restart 1') 12 | expect_gdb('stopped') 13 | send_gdb('c') 14 | expect_gdb('xited normally') 15 | send_gdb('c') 16 | 17 | ok() 18 | -------------------------------------------------------------------------------- /src/test/mmap_fd_reuse_checkpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record mmap_fd_reuse_checkpoint$bitness 3 | debug_gdb_only mmap_fd_reuse_checkpoint 4 | -------------------------------------------------------------------------------- /src/test/mmap_replace_most_mappings.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | send_gdb('checkpoint') 8 | expect_gdb('Checkpoint 1 at') 9 | send_gdb('restart 1') 10 | expect_gdb('stopped') 11 | send_gdb('rc') 12 | expect_history_end() 13 | send_gdb('restart 1') 14 | expect_gdb('stopped') 15 | send_gdb('c') 16 | expect_gdb('SIGKILL') 17 | 18 | ok() 19 | -------------------------------------------------------------------------------- /src/test/mmap_replace_most_mappings.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record mmap_replace_most_mappings$bitness 3 | debug_gdb_only mmap_replace_most_mappings 4 | -------------------------------------------------------------------------------- /src/test/mmap_shared_prot.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('check') 9 | expect_gdb('Checkpoint 1 at') 10 | 11 | send_gdb('c') 12 | expect_gdb('exited normally') 13 | 14 | send_gdb('restart 1') 15 | expect_gdb('stopped') 16 | send_gdb('c') 17 | expect_gdb('exited normally') 18 | 19 | ok() 20 | -------------------------------------------------------------------------------- /src/test/mmap_shared_prot.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/mmap_shared_write_exec_race.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Switch threads very eagerly on recorded events. 4 | RECORD_ARGS="-s" 5 | compare_test EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/mmap_tmpfs.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | unset RR_TRUST_TEMP_FILES 3 | compare_test EXIT-SUCCESS 4 | -------------------------------------------------------------------------------- /src/test/mmap_write.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | fails "write()s to SHARED mapped files aren't propagated to mapping during replay." 4 | 5 | compare_test 'done' 6 | -------------------------------------------------------------------------------- /src/test/mmap_write_private.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | RR_COPY_ALL_FILES=1 compare_test EXIT-SUCCESS 3 | -------------------------------------------------------------------------------- /src/test/mprotect_checkpoint.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('handle SIGKILL stop') 5 | expect_gdb('SIGKILL') 6 | send_gdb('continue') 7 | expect_gdb('Killed') 8 | 9 | send_gdb('break breakpoint') 10 | expect_gdb('Breakpoint 1') 11 | send_gdb('ignore 1 1000000') 12 | expect_gdb('Will ignore') 13 | send_gdb('reverse-continue') 14 | expect_history_end() 15 | 16 | ok() 17 | -------------------------------------------------------------------------------- /src/test/mprotect_checkpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/mprotect_growsdown.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | compare_test EXIT-SUCCESS 3 | compare_test EXIT-SUCCESS --share-private-mappings 4 | -------------------------------------------------------------------------------- /src/test/mprotect_step.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b main') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('b mprotect') 9 | expect_gdb('Breakpoint 2') 10 | send_gdb('c') 11 | expect_gdb('Breakpoint 2') 12 | 13 | # step through mprotect() until we reach the system call that 14 | # gets performed during replay 15 | for i in range(0,200): 16 | send_gdb('stepi') 17 | expect_gdb('(rr)') 18 | 19 | ok() 20 | -------------------------------------------------------------------------------- /src/test/mprotect_step.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record mprotect$bitness 3 | debug_gdb_only mprotect_step 4 | 5 | -------------------------------------------------------------------------------- /src/test/mprotect_syscallbuf_overflow.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int i; 7 | size_t page_size = sysconf(_SC_PAGESIZE); 8 | void* p = 9 | mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 10 | test_assert(p != MAP_FAILED); 11 | for (i = 0; i < 10000; ++i) { 12 | test_assert(0 == mprotect(p, page_size, PROT_READ | PROT_WRITE)); 13 | } 14 | atomic_puts("EXIT-SUCCESS"); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/mprotect_syscallbuf_overflow.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Use 4K syscallbuf size to force frequent overflows 4 | RECORD_ARGS=--syscall-buffer-size=4 5 | compare_test EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/msg_trunc.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int sockets[2]; 7 | char out[10]; 8 | 9 | test_assert(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) == 0); 10 | test_assert(send(sockets[0], "0123456789", 10, 0) == 10); 11 | memset(out, 77, sizeof(out)); 12 | test_assert(recv(sockets[1], out, 1, MSG_TRUNC) == 10); 13 | test_assert(out[1] == 77); 14 | 15 | atomic_puts("EXIT-SUCCESS"); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/test/mtio.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | struct mtget out; 7 | int ret = ioctl(STDOUT_FILENO, MTIOCGET, &out); 8 | test_assert(ret == -1 && ENOTTY == errno); 9 | atomic_puts("EXIT-SUCCESS"); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/test/mutex_pi_stress.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Switch threads very eagerly on recorded events. 4 | RECORD_ARGS="-s" 5 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 6 | compare_test EXIT-SUCCESS 7 | -------------------------------------------------------------------------------- /src/test/nested_detach.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | RECORD_ARGS="--env=_RR_TRACE_DIR=$workdir/inner" 3 | save_exe simple$bitness 4 | export RR_TEST_DELAY_SEIZE=1 5 | just_record $(which rr) "record --suppress-environment-warnings --nested=detach $PWD/simple$bitness-$nonce" 6 | # Replay outer 7 | replay 8 | check_record 9 | # Replay inner 10 | cd inner 11 | workdir_orig=$workdir 12 | workdir=$PWD 13 | wait_for_complete 14 | replay 15 | check_replay_token EXIT-SUCCESS 16 | workdir=$workdir_orig 17 | -------------------------------------------------------------------------------- /src/test/nested_detach_wait.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | mkdir $workdir/inner 4 | RECORD_ARGS="--env=_RR_TRACE_DIR=$workdir/inner" 5 | record $TESTNAME "$(which rr) record --suppress-environment-warnings --nested=detach $PWD/$TESTNAME-$nonce --inner" 6 | # Replay outer 7 | replay 8 | check_record EXIT-WAITED 9 | # Replay inner 10 | cd $workdir/inner 11 | workdir_orig=$workdir 12 | workdir=$PWD 13 | replay 14 | check_replay_token EXIT-SUCCESS 15 | workdir=$workdir_orig 16 | -------------------------------------------------------------------------------- /src/test/nested_release.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | just_record $(which rr) "record --nested=release hello NOT-IN-REPLAY" 3 | # Replay outer 4 | replay 5 | if [[ $(grep -l NOT-IN-REPLAY replay.out) ]]; then 6 | failed ": token NOT-IN-REPLAY in replay.out:" 7 | echo "--------------------------------------------------" 8 | cat replay.out 9 | echo "--------------------------------------------------" 10 | fi 11 | check_record 12 | 13 | -------------------------------------------------------------------------------- /src/test/nested_release_exit_code.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | just_record $RR_EXE "record --nested=release false" && failed "error not propagated" 3 | passed 4 | -------------------------------------------------------------------------------- /src/test/nested_release_signal.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | kill(getpid(), SIGABRT); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /src/test/nested_release_signal.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | just_record $RR_EXE "record --nested=detach nested_release_signal$bitness" && failed "error not propagated" 3 | passed 4 | -------------------------------------------------------------------------------- /src/test/nscd.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd = socket(AF_UNIX, SOCK_STREAM, 0); 7 | struct sockaddr_un addr; 8 | int ret; 9 | test_assert(fd >= 0); 10 | addr.sun_family = AF_UNIX; 11 | strcpy(addr.sun_path, "/var/run/nscd/socket"); 12 | ret = connect(fd, (struct sockaddr*)&addr, sizeof(addr)); 13 | test_assert(ret < 0 && errno == EACCES); 14 | atomic_puts("EXIT-SUCCESS"); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/openat_null.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | #include "util.h" 3 | #include 4 | 5 | int main(void) { 6 | // Use syscall(2) because the glibc prototype for openat(2) might enforce that 7 | // it's nonnull. 8 | int fd = syscall(SYS_openat, AT_FDCWD, NULL, O_RDONLY); 9 | test_assert(fd == -1); 10 | atomic_puts("EXIT-SUCCESS"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/test/overflow_branch_counter.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # This test executes LOTS of conditional branches so speed things up by 4 | # not interrupting too often. 5 | RECORD_ARGS="-c20000000" 6 | compare_test EXIT-SUCCESS 7 | -------------------------------------------------------------------------------- /src/test/parent_no_break_child_bkpt.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | def observe_normal_parent_exit(): 4 | expect_rr('EXIT-SUCCESS') 5 | expect_gdb(r'Inferior 1 \(process \d+\) exited normally') 6 | 7 | send_gdb('b breakpoint') 8 | expect_gdb('Breakpoint 1') 9 | 10 | send_gdb('c') 11 | observe_normal_parent_exit() 12 | 13 | restart_replay() 14 | observe_normal_parent_exit() 15 | 16 | ok() 17 | -------------------------------------------------------------------------------- /src/test/parent_no_break_child_bkpt.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record fork_child_crash$bitness 3 | debug_gdb_only parent_no_break_child_bkpt 4 | -------------------------------------------------------------------------------- /src/test/parent_no_stop_child_crash.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | def observe_normal_parent_exit(): 4 | expect_rr('EXIT-SUCCESS') 5 | expect_gdb(r'Inferior 1 \(process \d+\) exited normally') 6 | 7 | send_gdb('c') 8 | observe_normal_parent_exit() 9 | 10 | restart_replay() 11 | observe_normal_parent_exit() 12 | 13 | ok() 14 | -------------------------------------------------------------------------------- /src/test/parent_no_stop_child_crash.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record fork_child_crash$bitness 3 | debug_gdb_only parent_no_stop_child_crash 4 | -------------------------------------------------------------------------------- /src/test/patch_page_end.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # This test requires syscallbuf syscall patching 4 | skip_if_no_syscall_buf 5 | compare_test EXIT-SUCCESS 6 | 7 | -------------------------------------------------------------------------------- /src/test/post_exec_fpu_regs.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | arch = get_exe_arch() 5 | 6 | if arch == 'aarch64': 7 | send_gdb('p $v0.d.u') 8 | expect_gdb('{0, 0}') 9 | elif arch == 'i386' or arch == 'i386:x86-64': 10 | send_gdb('p $xmm0') 11 | expect_gdb('v4_float = {0, 0, 0, 0}') 12 | 13 | ok() 14 | -------------------------------------------------------------------------------- /src/test/post_exec_fpu_regs.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only post_exec_fpu_regs 4 | -------------------------------------------------------------------------------- /src/test/prctl_tsc.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | if ! prctl_tsc_supported; then 3 | exit 77 4 | fi 5 | compare_test EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/prctl_tsc_supported.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) { 5 | return prctl(PR_SET_TSC, PR_TSC_ENABLE) == 0 ? EXIT_SUCCESS : EXIT_FAILURE; 6 | } 7 | -------------------------------------------------------------------------------- /src/test/priority.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | renice -n 1 $$ && record $TESTNAME 3 | renice -n 2 $$ && replay 4 | check 'EXIT-SUCCESS' 5 | -------------------------------------------------------------------------------- /src/test/proc_maps.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('break main') 5 | expect_gdb('Breakpoint 1') 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1') 8 | 9 | send_gdb('info proc mappings') 10 | expect_gdb('\[vdso\]') 11 | 12 | ok() 13 | -------------------------------------------------------------------------------- /src/test/proc_maps.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only proc_maps 4 | -------------------------------------------------------------------------------- /src/test/pthread_mutex_timedlock.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | pthread_mutexattr_t attr; 7 | pthread_mutex_t mutex; 8 | struct timespec abstime = {0,0}; 9 | 10 | pthread_mutexattr_init(&attr); 11 | pthread_mutex_init(&mutex, &attr); 12 | 13 | pthread_mutex_timedlock(&mutex, &abstime); 14 | 15 | atomic_puts("EXIT-SUCCESS"); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/test/ptrace_remote_unmap.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | send_gdb('checkpoint') 8 | expect_gdb('Checkpoint 1 at') 9 | send_gdb('restart 1') 10 | expect_gdb('stopped') 11 | send_gdb('rc') 12 | expect_history_end() 13 | 14 | ok() 15 | -------------------------------------------------------------------------------- /src/test/ptrace_remote_unmap.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record ptrace_remote_unmap$bitness 3 | debug_gdb_only ptrace_remote_unmap 4 | -------------------------------------------------------------------------------- /src/test/read_bad_mem.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b main') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1, main') 8 | 9 | send_gdb('p *0xf') 10 | expect_gdb('Cannot access memory at address 0xf') 11 | 12 | send_gdb('p *0xffffffff') 13 | expect_gdb('Cannot access memory at address 0xffffffff') 14 | 15 | ok() 16 | -------------------------------------------------------------------------------- /src/test/read_bad_mem.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only read_bad_mem 4 | -------------------------------------------------------------------------------- /src/test/read_big_struct.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1, breakpoint') 8 | 9 | send_gdb('f 1') 10 | expect_gdb('(rr)') 11 | 12 | send_gdb('p big') 13 | expect_gdb('bytes = \'Z\'') 14 | 15 | ok() 16 | -------------------------------------------------------------------------------- /src/test/read_big_struct.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/record_replay.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 3 | record record_replay_subject$bitness 4 | just_record rr "--suppress-environment-warnings replay -a $workdir/*-0" 5 | replay 6 | check EXIT-SUCCESS 7 | -------------------------------------------------------------------------------- /src/test/remove_latest_trace.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(int argc, __attribute__((unused)) char** argv) { 6 | char* args[] = { "/proc/self/exe", "dummy", NULL }; 7 | 8 | if (argc > 1) { 9 | atomic_puts("EXIT-SUCCESS"); 10 | return 0; 11 | } 12 | 13 | atomic_puts("ready"); 14 | 15 | sleep(1); 16 | execve("/proc/self/exe", args, environ); 17 | test_assert(0 && "Failed exec!"); 18 | return 1; 19 | } 20 | -------------------------------------------------------------------------------- /src/test/remove_latest_trace.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record $TESTNAME 3 | 4 | replay & 5 | 6 | until grep -q ready replay.out; do 7 | sleep 0 8 | done 9 | 10 | rm -f latest-trace 11 | 12 | wait 13 | check 'EXIT-SUCCESS' 14 | 15 | -------------------------------------------------------------------------------- /src/test/remove_watchpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record watchpoint$bitness 3 | debug_gdb_only remove_watchpoint 4 | -------------------------------------------------------------------------------- /src/test/replay_overlarge_event_number.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | _RR_TRACE_DIR="$workdir" rr $GLOBAL_OPTIONS replay -s 9999 -g 3000 1> replay.out 2> replay.err 4 | if [[ $? != 0 ]]; then 5 | failed "should exit normally" 6 | fi 7 | passed 8 | -------------------------------------------------------------------------------- /src/test/replay_serve_files.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b constructor') 4 | expect_gdb('Make breakpoint pending on future shared library load?') 5 | 6 | send_gdb('y') 7 | expect_gdb('Breakpoint 1') 8 | 9 | send_gdb('c') 10 | expect_gdb('Breakpoint 1') 11 | 12 | ok() 13 | -------------------------------------------------------------------------------- /src/test/replay_serve_files.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | >&2 echo "We're in $PWD" 4 | 5 | cp $OBJDIR/lib/rr/libtest_lib$bitness.so . 6 | 7 | RECORD_ARGS="--env=LD_LIBRARY_PATH=$PWD --no-file-cloning" 8 | record constructor$bitness 9 | rr pack $workdir/latest-trace || failed "'rr pack' failed" 10 | # Make sure rr pack really copied the file 11 | truncate --size 0 libtest_lib$bitness.so 12 | rm libtest_lib$bitness.so 13 | debug_gdb_only $TESTNAME_NO_BITNESS "--serve-files" 14 | -------------------------------------------------------------------------------- /src/test/restart_abnormal_exit.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | atomic_puts("EXIT-SUCCESS"); 7 | kill(getppid(), SIGINT); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /src/test/restart_abnormal_exit.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/restart_breakpoint.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b C') 4 | expect_gdb('Breakpoint 1') 5 | 6 | def check_breakpoint(): 7 | expect_rr('calling C') 8 | 9 | expect_gdb('Breakpoint 1(.*) C') 10 | 11 | send_gdb('bt') 12 | expect_gdb('#0[^C]+C[^#]+#1[^B]+B[^#]+#2[^A]+A[^#]+#3[^m]+main') 13 | 14 | send_gdb('c') 15 | check_breakpoint() 16 | 17 | restart_replay() 18 | check_breakpoint() 19 | 20 | restart_replay() 21 | check_breakpoint() 22 | 23 | ok() 24 | -------------------------------------------------------------------------------- /src/test/restart_diversion.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only restart_diversion 4 | -------------------------------------------------------------------------------- /src/test/restart_finish.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | restart_replay() 5 | send_gdb('c') 6 | # A stop fires when we hit an exec 7 | expect_rr([ re.compile(r'exited normally'), 8 | re.compile(r'stopped') ]) 9 | 10 | ok() 11 | -------------------------------------------------------------------------------- /src/test/restart_invalid_checkpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only restart_invalid_checkpoint 4 | 5 | -------------------------------------------------------------------------------- /src/test/restart_unstable.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('c') 4 | expect_gdb('exited normally') 5 | 6 | restart_replay() 7 | 8 | expect_gdb('exited normally') 9 | 10 | ok() 11 | -------------------------------------------------------------------------------- /src/test/restart_unstable.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record exit_group$bitness 3 | debug_gdb_only restart_unstable 4 | -------------------------------------------------------------------------------- /src/test/reverse_alarm.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break main') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('break breakpoint') 6 | expect_gdb('Breakpoint 2') 7 | 8 | send_gdb('c') 9 | expect_gdb('Breakpoint 1') 10 | send_gdb('c') 11 | expect_gdb('Breakpoint 2') 12 | 13 | send_gdb('reverse-continue') 14 | expect_gdb('Breakpoint 1') 15 | 16 | ok() 17 | -------------------------------------------------------------------------------- /src/test/reverse_alarm.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record alarm$bitness 3 | debug_gdb_only reverse_alarm 4 | -------------------------------------------------------------------------------- /src/test/reverse_continue_breakpoint.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('break breakpoint2') 9 | expect_gdb('Breakpoint 2') 10 | send_gdb('reverse-cont') 11 | expect_gdb('Breakpoint 2') 12 | 13 | ok() 14 | -------------------------------------------------------------------------------- /src/test/reverse_continue_breakpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/reverse_continue_exec_subprocess.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | save_exe simple$bitness 4 | saved_simple="simple$bitness-$nonce" 5 | save_exe target_process$bitness 6 | 7 | record "target_process$bitness" "$saved_simple" 8 | TARGET_PID=$(grep 'child ' record.out | awk '{print $2}') 9 | 10 | echo Targeting recorded pid $TARGET_PID ... 11 | debug_gdb_only reverse_continue_exec_subprocess "-p $TARGET_PID" 12 | -------------------------------------------------------------------------------- /src/test/reverse_continue_fork_subprocess.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | save_exe simple$bitness 4 | saved_simple="simple$bitness-$nonce" 5 | save_exe target_process$bitness 6 | 7 | record "target_process$bitness" "$saved_simple" 8 | TARGET_PID=$(grep 'child ' record.out | awk '{print $2}') 9 | 10 | echo Targeting recorded pid $TARGET_PID ... 11 | debug_gdb_only reverse_continue_fork_subprocess "-f $TARGET_PID" 12 | -------------------------------------------------------------------------------- /src/test/reverse_continue_int3.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('c') 4 | expect_gdb('SIGTRAP') 5 | 6 | send_gdb('rc') 7 | expect_gdb('SIGTRAP') 8 | 9 | send_gdb('rc') 10 | expect_history_end() 11 | 12 | ok() 13 | -------------------------------------------------------------------------------- /src/test/reverse_continue_int3.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | record int3$bitness 4 | debug_gdb_only reverse_continue_int3 5 | -------------------------------------------------------------------------------- /src/test/reverse_continue_multiprocess.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('b breakpoint') 5 | expect_gdb('Breakpoint 1') 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1') 8 | send_gdb('c') 9 | expect_gdb('Breakpoint 1') 10 | send_gdb('rc') 11 | expect_gdb('Breakpoint 1') 12 | 13 | ok() 14 | -------------------------------------------------------------------------------- /src/test/reverse_continue_multiprocess.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/reverse_continue_process_signal.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('handle SIGKILL stop') 4 | 5 | send_gdb('c') 6 | expect_gdb('SIGKILL') 7 | send_gdb('reverse-continue') 8 | expect_history_end() 9 | 10 | ok() 11 | -------------------------------------------------------------------------------- /src/test/reverse_continue_process_signal.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/reverse_continue_start.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('reverse-cont') 5 | expect_history_end() 6 | send_gdb('reverse-cont') 7 | expect_history_end() 8 | send_gdb('reverse-stepi') 9 | expect_history_end() 10 | send_gdb('b main') 11 | expect_gdb('Breakpoint 1') 12 | send_gdb('c') 13 | expect_gdb('Breakpoint 1') 14 | send_gdb('reverse-cont') 15 | expect_history_end() 16 | send_gdb('reverse-stepi') 17 | expect_history_end() 18 | send_gdb('reverse-cont') 19 | expect_history_end() 20 | 21 | ok() 22 | -------------------------------------------------------------------------------- /src/test/reverse_continue_start.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only reverse_continue_start 4 | -------------------------------------------------------------------------------- /src/test/reverse_finish.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break atomic_puts') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('reverse-finish') 9 | expect_gdb('main') 10 | 11 | ok() 12 | -------------------------------------------------------------------------------- /src/test/reverse_finish.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only reverse_finish 4 | -------------------------------------------------------------------------------- /src/test/reverse_many_breakpoints.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void breakpoint(void) {} 6 | 7 | static volatile int result; 8 | 9 | int main(void) { 10 | int i; 11 | for (i = 0; i < 100000; ++i) { 12 | result += i * i; 13 | breakpoint(); 14 | } 15 | 16 | atomic_puts("EXIT-SUCCESS"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/test/reverse_many_breakpoints.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('handle SIGKILL stop') 4 | send_gdb('c') 5 | expect_gdb('SIGKILL') 6 | 7 | send_gdb('break breakpoint') 8 | expect_gdb('Breakpoint 1') 9 | send_gdb('reverse-continue') 10 | expect_gdb('Breakpoint 1') 11 | 12 | ok() 13 | -------------------------------------------------------------------------------- /src/test/reverse_many_breakpoints.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/reverse_step_breakpoint.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b main') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1') 8 | 9 | send_gdb('n') 10 | send_gdb('break') 11 | expect_gdb('Breakpoint 2') 12 | 13 | send_gdb('reverse-next') 14 | expect_gdb('Breakpoint 1') 15 | 16 | send_gdb('next') 17 | expect_gdb('Breakpoint 2') 18 | 19 | ok() 20 | -------------------------------------------------------------------------------- /src/test/reverse_step_breakpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only reverse_step_breakpoint 4 | -------------------------------------------------------------------------------- /src/test/reverse_step_long.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('handle SIGKILL stop') 4 | 5 | send_gdb('break breakpoint') 6 | expect_gdb('Breakpoint 1') 7 | send_gdb('c') 8 | expect_gdb('Breakpoint 1') 9 | send_gdb('c') 10 | expect_gdb('SIGKILL') 11 | # This should not hang 12 | send_gdb('reverse-stepi') 13 | send_gdb('reverse-continue') 14 | expect_gdb('Breakpoint 1') 15 | 16 | ok() 17 | -------------------------------------------------------------------------------- /src/test/reverse_step_long.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/reverse_step_signal.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record sigrt$bitness 3 | debug_gdb_only reverse_step_signal 4 | -------------------------------------------------------------------------------- /src/test/reverse_step_threads.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('set scheduler-locking off') 9 | send_gdb('reverse-step') 10 | 11 | send_gdb('c') 12 | expect_gdb('Breakpoint 1') 13 | 14 | ok() 15 | -------------------------------------------------------------------------------- /src/test/reverse_step_threads.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/reverse_step_threads2.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b spin') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | send_gdb('c') 8 | expect_gdb('Breakpoint 1') 9 | send_gdb('finish') 10 | 11 | send_gdb('set scheduler-locking off') 12 | send_gdb('reverse-step') 13 | 14 | send_gdb('reverse-continue') 15 | expect_gdb('Breakpoint 1') 16 | 17 | ok() 18 | -------------------------------------------------------------------------------- /src/test/reverse_step_threads2.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record reverse_step_threads$bitness 3 | debug_gdb_only reverse_step_threads2 4 | -------------------------------------------------------------------------------- /src/test/reverse_step_threads_break.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('b breakpoint_thread') 9 | expect_gdb('Breakpoint 2') 10 | 11 | send_gdb('set scheduler-locking off') 12 | for i in range(50): 13 | send_gdb('reverse-step') 14 | 15 | expect_gdb('Breakpoint 2') 16 | 17 | ok() 18 | -------------------------------------------------------------------------------- /src/test/reverse_step_threads_break.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/reverse_watchpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record watchpoint$bitness 3 | debug_gdb_only reverse_watchpoint 4 | -------------------------------------------------------------------------------- /src/test/reverse_watchpoint_syscall.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record watchpoint_syscall$bitness 3 | debug_gdb_only reverse_watchpoint_syscall 4 | -------------------------------------------------------------------------------- /src/test/rr_ps.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | compare_test EXIT-SUCCESS 3 | 4 | if !(do_ps | grep -q $'\t77'); then 5 | failed "Can't find return value 77" 6 | fi 7 | 8 | if !(do_ps | grep -q -- $'\t-11'); then 9 | failed "Can't find return value -11" 10 | fi 11 | 12 | if !(do_ps | grep $'\t88' | grep -q token); then 13 | failed "Can't find exec parameter 'token'" 14 | fi 15 | -------------------------------------------------------------------------------- /src/test/rseq.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break abort_ip') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('reverse-stepi') 9 | send_gdb('stepi') 10 | send_gdb('stepi') 11 | expect_gdb('Breakpoint 1') 12 | 13 | send_gdb('disable 1') 14 | send_gdb('c') 15 | expect_gdb('rogram stopped') 16 | 17 | ok() 18 | -------------------------------------------------------------------------------- /src/test/rseq.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | compare_test EXIT-SUCCESS 3 | # Skip debug_gdb_only script test if there were no jumps to abort_ip 4 | grep -q ", 0 jump aborts" record.out 5 | if [[ $? != 0 ]]; then 6 | TARGET_PID=$(grep 'child ' record.out | awk '{print $2}') 7 | debug_gdb_only rseq "-f $TARGET_PID" 8 | fi 9 | -------------------------------------------------------------------------------- /src/test/rseq_cpu_id_reset_longrunning.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('break atomic_puts') 5 | expect_gdb('Breakpoint 1') 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1') 8 | 9 | send_gdb('break event_syscall') 10 | expect_gdb('Breakpoint 2') 11 | send_gdb('rc') 12 | expect_gdb('Breakpoint 2') 13 | 14 | send_gdb('c') 15 | expect_gdb('Breakpoint 1') 16 | 17 | ok() 18 | -------------------------------------------------------------------------------- /src/test/rseq_cpu_id_reset_longrunning.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/rseq_syscallbuf.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | skip_if_no_syscall_buf 4 | 5 | compare_test EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/run_end.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only run_end 4 | -------------------------------------------------------------------------------- /src/test/run_in_function.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b main') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('call crash()') 9 | expect_gdb('SIGSEGV') 10 | restart_replay() 11 | expect_gdb('Breakpoint 1') 12 | 13 | ok() 14 | -------------------------------------------------------------------------------- /src/test/run_in_function.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record crash_in_function$bitness 3 | debug_gdb_only run_in_function 4 | -------------------------------------------------------------------------------- /src/test/rusage.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | struct rusage* r; 7 | 8 | ALLOCATE_GUARD(r, 0); 9 | test_assert(0 == getrusage(RUSAGE_SELF, r)); 10 | test_assert(r->ru_maxrss > 0); 11 | VERIFY_GUARD(r); 12 | 13 | atomic_puts("EXIT-SUCCESS"); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/test/sanity.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('c') 4 | expect_rr('Hi') 5 | 6 | ok() 7 | -------------------------------------------------------------------------------- /src/test/sanity.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record hello$bitness 3 | debug_gdb_only sanity 4 | -------------------------------------------------------------------------------- /src/test/search.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/seccomp_null.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, (void*)0); 7 | if (ret == -1 && errno == ENOSYS) { 8 | ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL); 9 | } 10 | test_assert(ret == -1 && errno == EFAULT); 11 | 12 | test_assert(0 == prctl(PR_GET_SECCOMP)); 13 | 14 | atomic_puts("EXIT-SUCCESS"); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/seccomp_open.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record $TESTNAME 75>rr-test-blacklist-file_name 3 | replay 4 | check EXIT-SUCCESS 5 | grep -q EXIT-SUCCESS rr-test-blacklist-file_name || failed "Didn't write success to rr-test-blacklist-file_name" 6 | -------------------------------------------------------------------------------- /src/test/seccomp_signals.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="-c100" 4 | compare_test EXIT-SUCCESS 5 | 6 | -------------------------------------------------------------------------------- /src/test/seekticks.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only seekticks 4 | -------------------------------------------------------------------------------- /src/test/seekticks_threads.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record seekticks_threads$bitness 3 | SCHED_EVENTS="$(get_events | grep \`SCHED\')" \ 4 | debug_gdb_only seekticks_threads 5 | -------------------------------------------------------------------------------- /src/test/segfault.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | compare_test 'caught signal 11, exiting' 3 | -------------------------------------------------------------------------------- /src/test/self_sigint.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | /* rr should ignore SIGINT */ 7 | kill(getppid(), SIGINT); 8 | atomic_puts("EXIT-SUCCESS"); 9 | kill(getpid(), SIGINT); 10 | test_assert(0 && "Shouldn't reach here"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/test/set_ptracer.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | test_assert(0 == prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY)); 7 | 8 | atomic_puts("EXIT-SUCCESS"); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/test/setgid.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | gid_t gid = getgid(); 7 | int err = setgid(gid); 8 | atomic_printf("setgid returned: %d\n", err); 9 | test_assert(0 == err); 10 | 11 | atomic_puts("EXIT-SUCCESS"); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/test/setsid.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | pid_t newsid; 7 | 8 | newsid = setsid(); 9 | atomic_printf("New session ID: %d\n", newsid); 10 | 11 | if (newsid >= 0) { 12 | atomic_puts("EXIT-SUCCESS"); 13 | } 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/setuid.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | skip_if_old_systemd 3 | compare_test EXIT-SUCCESS 4 | 5 | -------------------------------------------------------------------------------- /src/test/shared_exec.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd = open("output", O_RDWR | O_CREAT, 0777); 7 | int ret = write(fd, "x", 1); 8 | test_assert(ret == 1); 9 | char* p = (char*)mmap(NULL, 1, PROT_READ | PROT_WRITE | PROT_EXEC, 10 | MAP_SHARED, fd, 0); 11 | test_assert(p != MAP_FAILED); 12 | *p = 1; 13 | atomic_puts("EXIT-SUCCESS"); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/test/shared_map.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record $TESTNAME 3 | replay 4 | replay 5 | check 'EXIT-SUCCESS' 6 | -------------------------------------------------------------------------------- /src/test/shared_persistent_file.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('b breakpoint') 5 | expect_gdb('Breakpoint 1') 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1') 8 | send_gdb('check') 9 | expect_gdb('Checkpoint 1 at') 10 | send_gdb('c') 11 | expect_gdb('xited normally') 12 | send_gdb('restart 1') 13 | expect_gdb('stopped') 14 | send_gdb('c') 15 | expect_gdb('xited normally') 16 | 17 | ok() 18 | -------------------------------------------------------------------------------- /src/test/shared_persistent_file.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/shared_write.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd = open("output", O_RDWR | O_CREAT, 0777); 7 | int ret = write(fd, "x", 1); 8 | test_assert(ret == 1); 9 | char* p = (char*)mmap(NULL, 1, PROT_READ | PROT_WRITE, 10 | MAP_SHARED, fd, 0); 11 | test_assert(p != MAP_FAILED); 12 | *p = 1; 13 | atomic_puts("EXIT-SUCCESS"); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/test/shm_checkpoint.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b before_writing') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('b after_writing') 7 | expect_gdb('Breakpoint 2') 8 | 9 | send_gdb('c'); 10 | expect_gdb('Breakpoint 1, before_writing') 11 | 12 | send_gdb('checkpoint'); 13 | expect_gdb('Checkpoint 1 at'); 14 | 15 | send_gdb('c'); 16 | expect_gdb('Breakpoint 2, after_writing') 17 | 18 | send_gdb('restart 1'); 19 | expect_gdb('stopped') 20 | send_gdb('c'); 21 | expect_gdb('Breakpoint 2, after_writing') 22 | 23 | ok() 24 | 25 | -------------------------------------------------------------------------------- /src/test/shm_checkpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record shm$bitness 3 | TARGET_PID=$(grep 'child ' record.out | awk '{print $2}') 4 | debug_gdb_only shm_checkpoint "-f $TARGET_PID" 5 | -------------------------------------------------------------------------------- /src/test/sigill.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void sighandler(int sig) { 6 | atomic_printf("caught signal %d, exiting\n", sig); 7 | atomic_puts("EXIT-SUCCESS"); 8 | _exit(0); 9 | } 10 | 11 | int main(void) { 12 | signal(SIGILL, sighandler); 13 | 14 | atomic_puts("running undefined instruction ..."); 15 | undefined_instr(); 16 | test_assert("should have terminated!" && 0); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/test/siginfo.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('c') 5 | expect_gdb('SIGUSR1') 6 | send_gdb('print $_siginfo') 7 | expect_gdb('si_signo = 10') 8 | expect_gdb('si_code = -6') 9 | 10 | ok() 11 | -------------------------------------------------------------------------------- /src/test/siginfo.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record tgkill$bitness 3 | debug_gdb_only siginfo 4 | -------------------------------------------------------------------------------- /src/test/signal_checkpoint.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b sighandler') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Program received signal SIGILL') 8 | 9 | send_gdb('checkpoint') 10 | expect_gdb('Checkpoint 1 at') 11 | 12 | send_gdb('c') 13 | expect_gdb('Breakpoint 1, sighandler') 14 | 15 | send_gdb('restart 1'); 16 | send_gdb('c') 17 | expect_gdb('Breakpoint 1, sighandler') 18 | 19 | ok() 20 | -------------------------------------------------------------------------------- /src/test/signal_checkpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record sigill$bitness 3 | debug_gdb_only signal_checkpoint 4 | -------------------------------------------------------------------------------- /src/test/signal_numbers.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/signal_stop.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b sighandler') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Program received signal SIGILL') 8 | 9 | send_gdb('c') 10 | expect_gdb('Breakpoint 1, sighandler') 11 | 12 | ok() 13 | -------------------------------------------------------------------------------- /src/test/signal_stop.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record sigill$bitness 3 | debug_gdb_only signal_stop 4 | -------------------------------------------------------------------------------- /src/test/sigprocmask_race.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="-c100" 4 | # This test tests the interaction of the syscallbuf with frequent ticks 5 | # interrupts, so without the syscallbuf it doesn't matter. Also, 6 | # without the syscallbuf it's rather slow. 7 | skip_if_no_syscall_buf 8 | compare_test EXIT-SUCCESS 9 | -------------------------------------------------------------------------------- /src/test/sigprocmask_rr_sigs_nondefault.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | RECORD_ARGS=--syscall-buffer-sig=SIGPROF 3 | compare_test EXIT-SUCCESS 4 | -------------------------------------------------------------------------------- /src/test/sigpwr.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void handler(__attribute__((unused)) int sig) { 6 | atomic_puts("EXIT-SUCCESS"); 7 | } 8 | 9 | int main(void) { 10 | signal(SIGPWR, handler); 11 | raise(SIGPWR); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/test/sigtrap_process_group.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | atomic_puts("EXIT-SUCCESS"); 7 | kill(0, SIGTRAP); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /src/test/simple.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | atomic_puts("EXIT-SUCCESS"); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /src/test/simple.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | unset RR_TRUST_TEMP_FILES 3 | export RR_COPY_ALL_FILES=1 4 | record simple$bitness 5 | if ! ( ls $workdir/latest-trace | grep -q 'mmap_.*libc.*\.so' ); then 6 | failed "Can't find libc" 7 | fi 8 | replay 9 | check EXIT-SUCCESS 10 | -------------------------------------------------------------------------------- /src/test/simple_script.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | skip_if_rr_32_bit_with_shell_64_bit 4 | 5 | just_record $TESTDIR/simple_script.sh 6 | replay 7 | check EXIT-SUCCESS 8 | -------------------------------------------------------------------------------- /src/test/simple_script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo EXIT-SUCCESS 4 | -------------------------------------------------------------------------------- /src/test/simple_script_debug.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b write') 4 | # "Make breakpoint pending on future shared library load?" 5 | send_gdb('y') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('c') 9 | expect_gdb('Breakpoint 1') 10 | 11 | ok() 12 | -------------------------------------------------------------------------------- /src/test/simple_script_debug.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | skip_if_rr_32_bit_with_shell_64_bit 4 | 5 | just_record $TESTDIR/simple_script.sh 6 | debug_gdb_only simple_script_debug "--onprocess simple_script.sh" 7 | -------------------------------------------------------------------------------- /src/test/simple_threads_stress.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | static void* do_thread(__attribute__((unused)) void* p) { return 0; } 4 | 5 | int main(void) { 6 | int i; 7 | pthread_t thread[100]; 8 | for (i = 0; i < 100; ++i) { 9 | pthread_create(&thread[i], NULL, do_thread, NULL); 10 | } 11 | for (i = 0; i < 100; ++i) { 12 | pthread_join(thread[i], NULL); 13 | } 14 | atomic_puts("EXIT-SUCCESS"); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/simple_winch.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | # Signal all processes in the process group 4 | send_gdb('!kill -WINCH 0') 5 | send_gdb('c') 6 | expect_rr('EXIT-SUCCESS') 7 | expect_gdb('exited normally') 8 | 9 | send_gdb('break main') 10 | expect_gdb('Breakpoint 1') 11 | send_gdb('run') 12 | send_gdb('c') 13 | expect_gdb('Breakpoint 1') 14 | send_gdb('!kill -WINCH 0') 15 | send_gdb('reverse-cont') 16 | expect_history_end() 17 | 18 | ok() 19 | -------------------------------------------------------------------------------- /src/test/simple_winch.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only simple_winch 4 | -------------------------------------------------------------------------------- /src/test/sock_name_null.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); 7 | int ret; 8 | socklen_t len = 0; 9 | test_assert(sock_fd >= 0); 10 | 11 | ret = getsockname(sock_fd, NULL, &len); 12 | test_assert(ret == 0); 13 | test_assert(len > 0); 14 | 15 | atomic_puts("EXIT-SUCCESS"); 16 | return 0; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/test/stack_growth.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/stack_overflow_debug.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('handle SIGKILL stop') 4 | 5 | send_gdb('c') 6 | expect_gdb('SIGSEGV') 7 | send_gdb('stepi') 8 | expect_gdb('SIGSEGV') 9 | send_gdb('stepi') 10 | expect_gdb('SIGKILL') 11 | 12 | send_gdb('reverse-stepi') 13 | expect_gdb('SIGSEGV') 14 | send_gdb('reverse-stepi') 15 | expect_gdb('SIGSEGV') 16 | send_gdb('reverse-continue') 17 | expect_history_end() 18 | 19 | ok() 20 | -------------------------------------------------------------------------------- /src/test/stack_overflow_debug.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | record stack_overflow$bitness 4 | TARGET_PID=$(grep 'child ' record.out | awk '{print $2}') 5 | 6 | echo Targeting recorded pid $TARGET_PID ... 7 | debug_gdb_only stack_overflow_debug "-f $TARGET_PID" 8 | -------------------------------------------------------------------------------- /src/test/std_random.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | #include 6 | 7 | int main(void) { 8 | std::random_device device; 9 | atomic_printf("Random value = %d\n", device()); 10 | atomic_puts("EXIT-SUCCESS"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/test/stdout_child.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | pid_t child; 7 | int status; 8 | 9 | if (argc == 2) { 10 | atomic_puts("EXIT-SUCCESS"); 11 | return 77; 12 | } 13 | 14 | if (0 == (child = fork())) { 15 | execl(argv[0], argv[0], "step2", NULL); 16 | } 17 | test_assert(child == waitpid(child, &status, 0)); 18 | test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /src/test/stdout_dup.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd = dup(STDOUT_FILENO); 7 | 8 | static const char msg[] = "EXIT-SUCCESS\n"; 9 | write(fd, msg, sizeof(msg) - 1); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/test/step1.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b A') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_rr('calling A') 8 | expect_gdb('Breakpoint 1, A') 9 | 10 | send_gdb('n') 11 | expect_rr('calling B') 12 | 13 | send_gdb('s') 14 | expect_gdb('B ()') 15 | 16 | send_gdb('n') 17 | expect_rr('calling C') 18 | 19 | send_gdb('s') 20 | expect_gdb('C ()') 21 | 22 | send_gdb('bt') 23 | expect_gdb('#0[^C]+C[^#]+#1[^B]+B[^#]+#2[^A]+A[^#]+#3[^m]+main') 24 | 25 | ok() 26 | -------------------------------------------------------------------------------- /src/test/step1.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record breakpoint$bitness 3 | debug_gdb_only step1 4 | -------------------------------------------------------------------------------- /src/test/step_into_lib.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | void lib_exit_success(void); 6 | 7 | int main(void) { 8 | lib_exit_success(); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/test/step_into_lib.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('b main') 5 | expect_gdb('Breakpoint 1') 6 | send_gdb('continue') 7 | expect_gdb('Breakpoint 1') 8 | expect_gdb(re.compile(r'\s([a-z_]+)\(')) 9 | if last_match().group(1) == 'main': 10 | send_gdb('s') 11 | expect_gdb('lib_exit_success') 12 | 13 | send_gdb('s') 14 | # Should have stepped into lib_exit_success where there's an atomic_puts 15 | expect_gdb('atomic_puts') 16 | 17 | ok() 18 | -------------------------------------------------------------------------------- /src/test/step_into_lib.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/step_signal.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record sigrt$bitness 3 | debug_gdb_only step_signal 4 | -------------------------------------------------------------------------------- /src/test/step_thread.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/stray_time_slice_signal.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | RECORD_ARGS = "-c3" 3 | compare_test EXIT-SUCCESS 4 | -------------------------------------------------------------------------------- /src/test/strict_priorities.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | export RR_DISABLE_ROUND_ROBIN=1 3 | compare_test EXIT-SUCCESS 4 | -------------------------------------------------------------------------------- /src/test/subprocess_exit_ends_session.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | record fork_child_crash$bitness 4 | TARGET_PID=$(grep 'child ' record.out | awk '{print $2}') 5 | 6 | debug_gdb_only subprocess_exit_ends_session "-f $TARGET_PID" 7 | -------------------------------------------------------------------------------- /src/test/switch_processes.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | # Restart at the first debuggable event, which will be in a different 5 | # process! We should stay focused on the child process, instead of 6 | # trying to switch to that process. At least we shouldn't crash. 7 | restart_replay(1) 8 | expect_gdb('(rr)') 9 | expect_list([re.compile('Program stopped'), re.compile('exited normally')]) 10 | 11 | ok() 12 | -------------------------------------------------------------------------------- /src/test/switch_processes.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | save_exe write_race$bitness 4 | saved_exe="write_race$bitness-$nonce" 5 | record target_process$bitness $saved_exe 6 | 7 | debug_gdb_only switch_processes "-g 1000" 8 | -------------------------------------------------------------------------------- /src/test/symlink.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | static const char token_file[] = "rr-link-file.txt"; 7 | static const char link_name[] = "rr-link-file.link"; 8 | 9 | test_assert(0 == symlink(token_file, link_name)); 10 | test_assert(0 == unlink(link_name)); 11 | test_assert(0 == symlinkat(token_file, AT_FDCWD, link_name)); 12 | test_assert(0 == unlink(link_name)); 13 | 14 | atomic_puts("EXIT-SUCCESS"); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/sync.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | #define FILENAME "foo.txt" 6 | 7 | int main(void) { 8 | int fd; 9 | 10 | sync(); 11 | 12 | fd = open(FILENAME, O_CREAT | O_RDWR, 0600); 13 | test_assert(0 == unlink(FILENAME)); 14 | test_assert(fd >= 0); 15 | test_assert(0 == syncfs(fd)); 16 | 17 | atomic_puts("EXIT-SUCCESS"); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /src/test/sync_file_range.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd = open("dummy.txt", O_RDWR | O_CREAT | O_TRUNC, 0600); 7 | int ret; 8 | test_assert(fd >= 0); 9 | ret = write(fd, "x", 1); 10 | test_assert(ret == 1); 11 | ret = sync_file_range(fd, 0, 1, SYNC_FILE_RANGE_WAIT_BEFORE); 12 | test_assert(ret == 0); 13 | atomic_puts("EXIT-SUCCESS"); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/test/syscallbuf_fd_disabling.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | atomic_puts("Line 1"); 7 | atomic_puts("Line 2"); 8 | atomic_puts("Line 3"); 9 | atomic_puts("EXIT-SUCCESS"); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/test/syscallbuf_fd_disabling.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | GLOBAL_OPTIONS="$GLOBAL_OPTIONS -M" 3 | record $TESTNAME 4 | if [[ "record.out" != $(grep -l '^\[.*\]Line 2$' record.out) ]]; then 5 | failed "Missing line annotation" 6 | exit 7 | fi 8 | compare_test EXIT-SUCCESS 9 | -------------------------------------------------------------------------------- /src/test/syscallbuf_signal_blocking_read.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="-c100" 4 | compare_test EXIT-SUCCESS 5 | 6 | -------------------------------------------------------------------------------- /src/test/syscallbuf_timeslice2.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int fd; 7 | char buf[10]; 8 | int i; 9 | 10 | for (i = 0; i < 1 << 12; ++i) { 11 | fd = open("/dev/zero", O_RDONLY); 12 | read(fd, buf, sizeof(buf)); 13 | close(fd); 14 | if (!(i & ((1 << 8) - 1))) { 15 | atomic_printf("."); 16 | } 17 | } 18 | 19 | atomic_puts("\nEXIT-SUCCESS"); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /src/test/syscallbuf_timeslice2_250.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="-c250" 4 | 5 | record syscallbuf_timeslice2$bitness 6 | replay 7 | check 'EXIT-SUCCESS' 8 | -------------------------------------------------------------------------------- /src/test/syscallbuf_timeslice_250.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="-c250" 4 | 5 | record syscallbuf_timeslice$bitness 6 | replay 7 | check 'EXIT-SUCCESS' 8 | -------------------------------------------------------------------------------- /src/test/sysconf_onln.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record $TESTNAME "--expected-cpus=1" 3 | replay 4 | check EXIT-SUCCESS 5 | RECORD_ARGS="--num-cores=2" 6 | record $TESTNAME "--expected-cpus=2" 7 | replay 8 | check EXIT-SUCCESS 9 | -------------------------------------------------------------------------------- /src/test/sysinfo.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | struct sysinfo* info; 7 | 8 | ALLOCATE_GUARD(info, 0); 9 | test_assert(0 == sysinfo(info)); 10 | test_assert(info->mem_unit > 0); 11 | test_assert(info->procs > 0); 12 | VERIFY_GUARD(info); 13 | 14 | atomic_puts("EXIT-SUCCESS"); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/target_fork.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | EVENTS=1000 4 | record $TESTNAME $EVENTS 5 | TARGET_PID=$(grep 'child ' record.out | awk '{print $2}') 6 | 7 | echo Targeting recorded pid $TARGET_PID ... 8 | debug_gdb_only bad_good_break "-f $TARGET_PID -g $EVENTS" 9 | -------------------------------------------------------------------------------- /src/test/target_process.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | save_exe breakpoint$bitness 4 | saved_breakpoint="breakpoint$bitness-$nonce" 5 | 6 | record $TESTNAME "$saved_breakpoint" 7 | TARGET_PID=$(grep 'child ' record.out | awk '{print $2}') 8 | 9 | echo Targeting recorded pid $TARGET_PID ... 10 | debug_gdb_only restart_breakpoint "-p $TARGET_PID -g 1" 11 | -------------------------------------------------------------------------------- /src/test/term_nonmain.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | compare_test 'killing ...' 3 | -------------------------------------------------------------------------------- /src/test/term_rr.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | signal(SIGTERM, SIG_IGN); 7 | kill(getppid(), SIGTERM); 8 | atomic_puts("EXIT-SUCCESS"); 9 | sleep(10000); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/test/term_rr.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('handle SIGKILL stop') 4 | send_gdb('handle SIGTERM stop') 5 | send_gdb('break main') 6 | expect_gdb('Breakpoint 1') 7 | send_gdb('c') 8 | expect_gdb('Breakpoint 1') 9 | send_gdb('c') 10 | expect_gdb('received signal SIGTERM') 11 | send_gdb('c') 12 | expect_gdb('received signal SIGKILL') 13 | 14 | ok() 15 | -------------------------------------------------------------------------------- /src/test/term_rr.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/term_rr_ok.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void handler(__attribute__((unused)) int sig) { 6 | exit(0); 7 | } 8 | 9 | int main(void) { 10 | signal(SIGTERM, handler); 11 | atomic_puts("EXIT-SUCCESS"); 12 | kill(getppid(), SIGTERM); 13 | sleep(10000); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/test/term_rr_ok.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record $TESTNAME || failed "$TESTNAME failed" 3 | replay 4 | check EXIT-SUCCESS -------------------------------------------------------------------------------- /src/test/term_trace_reset.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | volatile int dummy; 6 | 7 | int main(void) { 8 | int i = 0; 9 | 10 | atomic_puts("ready"); 11 | atomic_puts("EXIT-SUCCESS"); 12 | 13 | struct timespec ts; 14 | clock_gettime(CLOCK_MONOTONIC, &ts); 15 | 16 | while (1) { 17 | dummy += i % (1 << 20); 18 | dummy += i % (79 * (1 << 20)); 19 | } 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /src/test/term_trace_reset.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | record $TESTNAME & 4 | 5 | until grep -q ready record.out; do 6 | sleep 0 7 | done 8 | 9 | sleep 0.01 10 | rrpid=$(parent_pid_of $(pidof $TESTNAME-$nonce)) 11 | kill -TERM $rrpid >& /dev/null 12 | 13 | # Wait for 'record' to actually terminate. Otherwise we might start 14 | # replaying before the trace file has been completely written. 15 | wait 16 | 17 | echo "Replaying ..." 18 | replay 19 | check 'EXIT-SUCCESS' 20 | -------------------------------------------------------------------------------- /src/test/term_trace_syscall.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void handle_SIGTERM(__attribute__((unused)) int sig) { 6 | atomic_puts("EXIT-SUCCESS"); 7 | exit(0); 8 | } 9 | 10 | int main(void) { 11 | struct timespec ts = { 1000000, 0 }; 12 | 13 | signal(SIGTERM, handle_SIGTERM); 14 | atomic_puts("sleeping"); 15 | 16 | nanosleep(&ts, NULL); 17 | atomic_puts("FAILED"); 18 | return 1; 19 | } 20 | -------------------------------------------------------------------------------- /src/test/test_setup.gdb: -------------------------------------------------------------------------------- 1 | set pagination off 2 | handle SIGSEGV stop 3 | handle SIGKILL nostop 4 | # This fails in gdb < 8.3 5 | set style enabled off 6 | # gdb >= 10 7 | set debuginfod enabled off 8 | -------------------------------------------------------------------------------- /src/test/test_setup.lldb: -------------------------------------------------------------------------------- 1 | process handle -p true -s true SIGSEGV 2 | process handle -p false -s false SIGKILL 3 | 4 | -------------------------------------------------------------------------------- /src/test/thread_open_race.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # This test requires syscallbuf syscall patching 4 | skip_if_no_syscall_buf 5 | 6 | if [ $TIMEOUT -lt 300 ]; then TIMEOUT=300; fi 7 | compare_test EXIT-SUCCESS 8 | 9 | -------------------------------------------------------------------------------- /src/test/thread_stress.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 4 | compare_test EXIT-SUCCESS 5 | -------------------------------------------------------------------------------- /src/test/threaded_syscall_spam.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Without the syscallbuf, trying to record the large number of 4 | # syscalls in this test is impractical. 5 | skip_if_no_syscall_buf 6 | 7 | # 2^17 iterations is arbitrarily chosen to take ~3s on a fast machine 8 | record $TESTNAME 17 9 | 10 | # Because of issue #184, replay takes longer than practical. So for 11 | # now we'll skip it and hope other tests exercise the relevant code 12 | # well enough. 13 | #replay 14 | #check 'EXIT-SUCCESS' 15 | passed 16 | -------------------------------------------------------------------------------- /src/test/threads.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # When the syscallbuf is enabled, this test looks to rr like a long 4 | # series of CPU chewing, with buffer flushes at each time-slice 5 | # interrupt. This makes replay take a pathologically long time 6 | # because of all the async-signal replaying. So speed things up by 7 | # bumping up the timeslice. 8 | RECORD_ARGS="-c20000000" 9 | 10 | compare_test EXIT-SUCCESS 11 | -------------------------------------------------------------------------------- /src/test/tick0.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record tick0$bitness 3 | debug_gdb_only tick0 4 | -------------------------------------------------------------------------------- /src/test/tick0_less.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record tick0_less$bitness 3 | debug_gdb_only tick0 4 | -------------------------------------------------------------------------------- /src/test/tls.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | __thread int tlsvar; 6 | 7 | void breakpoint_fn(void) {} 8 | 9 | void* thread_fn(void* arg) { 10 | tlsvar = *(int*)arg; 11 | breakpoint_fn(); 12 | return NULL; 13 | } 14 | 15 | int main(void) { 16 | pthread_t thread; 17 | 18 | int value = 97; 19 | pthread_create(&thread, NULL, thread_fn, &value); 20 | pthread_join(thread, NULL); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /src/test/tls.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint_fn') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1') 8 | send_gdb('print tlsvar') 9 | expect_gdb(' = 97') 10 | 11 | send_gdb('reverse-stepi') 12 | send_gdb('print tlsvar') 13 | expect_gdb(' = 97') 14 | 15 | ok() 16 | -------------------------------------------------------------------------------- /src/test/tls.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/trace_events.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | exe=simple$bitness 4 | cp ${OBJDIR}/bin/$exe $exe-$nonce 5 | just_record $exe-$nonce 6 | if [[ `rr dump -e latest-trace|grep --count TraceTaskEvent::EXEC` != 1 ]]; then 7 | failed "Wrong number of TraceTaskEvent::EXECs" 8 | fi 9 | if [[ `rr dump -e latest-trace|grep --count TraceTaskEvent::EXIT` != 1 ]]; then 10 | failed "Wrong number of TraceTaskEvent::EXITs" 11 | fi 12 | -------------------------------------------------------------------------------- /src/test/tracee_unmap_vdso.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | # Unmapping the rr page breaks ssycallbuf; we don't support that. 3 | skip_if_syscall_buf 4 | # Unmapping the VDSO breaks all syscalls on 32-bit x86. 5 | skip_if_test_32_bit 6 | skip_if_rr_32_bit 7 | compare_test EXIT-SUCCESS 8 | -------------------------------------------------------------------------------- /src/test/transient_fault_replay_all.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | skip_if_rr_32_bit_with_shell_64_bit 4 | 5 | RECORD_ARGS=-M 6 | just_record seq "1 100" 7 | RR_SIMULATE_ERROR_AT_EVENT=300 replay -M 8 | check 100 || exit 1 9 | RR_SIMULATE_ERROR_AT_EVENT=301 replay -M 10 | check 100 11 | -------------------------------------------------------------------------------- /src/test/tty.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | replay "--tty tty-output" 4 | 5 | token=EXIT-SUCCESS 6 | if [[ "tty-output" != $(grep -l $token tty-output) ]]; then 7 | failed ": token '$token' not in tty-output:" 8 | echo "--------------------------------------------------" 9 | cat tty-output 10 | echo "--------------------------------------------------" 11 | else 12 | passed 13 | fi 14 | -------------------------------------------------------------------------------- /src/test/ttyname.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record $TESTNAME 3 | replay 4 | token=EXIT-SUCCESS 5 | if [[ "replay.err" != $(grep -l $token replay.err) ]]; then 6 | failed ": token '$token' not in replay.err:" 7 | echo "--------------------------------------------------" 8 | cat replay.err 9 | echo "--------------------------------------------------" 10 | cat replay.out 11 | echo "--------------------------------------------------" 12 | else 13 | passed 14 | fi 15 | -------------------------------------------------------------------------------- /src/test/unexpected_stack_growth.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | send_gdb('finish') 8 | 9 | send_gdb('watch -l *(&v - 1000000)') 10 | expect_gdb('Hardware[()/a-z ]+watchpoint 2') 11 | 12 | send_gdb('c') 13 | expect_gdb('signal SIGSEGV') 14 | 15 | send_gdb('c') 16 | expect_gdb('exited normally') 17 | 18 | ok() 19 | -------------------------------------------------------------------------------- /src/test/unexpected_stack_growth.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/unicode.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('break breakpoint') 5 | expect_gdb('Breakpoint 1') 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1') 8 | send_gdb('finish') 9 | 10 | send_gdb('checkpoint') 11 | expect_gdb(re.compile(r'Checkpoint 1 at.*"𝕨ā≥3"')) 12 | 13 | ok() 14 | -------------------------------------------------------------------------------- /src/test/unicode.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | set_utf_locale 3 | debug_test_gdb_only 4 | -------------------------------------------------------------------------------- /src/test/unjoined_thread.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void* thread(__attribute__((unused)) void* unused) { 6 | sleep(-1); 7 | return NULL; 8 | } 9 | 10 | int main(void) { 11 | pthread_t t; 12 | 13 | pthread_create(&t, NULL, thread, NULL); 14 | /* Don't join |t|. */ 15 | 16 | atomic_puts("EXIT-SUCCESS"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/test/unmap_vdso.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | RECORD_ARGS="--unmap-vdso" 3 | just_record cat /proc/self/maps 4 | if grep "vdso" record.out; then 5 | failed "vdso should have been unmapped" 6 | fi 7 | -------------------------------------------------------------------------------- /src/test/unwind_on_signal.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b main') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('p (int)strdup(0)') 9 | expect_gdb('received signal SIGSEGV') 10 | send_gdb('c') 11 | expect_rr('EXIT-SUCCESS') 12 | expect_gdb('SIGKILL') 13 | 14 | ok() 15 | -------------------------------------------------------------------------------- /src/test/unwind_on_signal.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only unwind_on_signal 4 | -------------------------------------------------------------------------------- /src/test/user_ignore_sig.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # Ignore SIGUSR1; block its delivery to tracees. 4 | RECORD_ARGS="-i10" 5 | 6 | compare_test EXIT-SUCCESS 7 | -------------------------------------------------------------------------------- /src/test/userfaultfd.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int ret = syscall(RR_userfaultfd, 0); 7 | test_assert(ret == -1 && errno == ENOSYS); 8 | atomic_puts("EXIT-SUCCESS"); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/test/vdso_clock_gettime_stack.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int i; 7 | struct timespec ts; 8 | for (i = 0; i < 160000; ++i) { 9 | clock_gettime(CLOCK_MONOTONIC, &ts); 10 | } 11 | 12 | atomic_puts("EXIT-SUCCESS"); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /src/test/vdso_gettimeofday_stack.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int i; 7 | struct timeval tv; 8 | for (i = 0; i < 160000; ++i) { 9 | gettimeofday(&tv, NULL); 10 | } 11 | 12 | atomic_puts("EXIT-SUCCESS"); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /src/test/vdso_stack.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break main') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('break traced_raw_syscall') 9 | expect_gdb('Breakpoint 2') 10 | send_gdb('c') 11 | expect_gdb('Breakpoint 2') 12 | 13 | send_gdb('where') 14 | expect_gdb(' main ') 15 | 16 | ok() 17 | -------------------------------------------------------------------------------- /src/test/vdso_time_stack.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int i; 7 | for (i = 0; i < 160000; ++i) { 8 | time(NULL); 9 | } 10 | 11 | atomic_puts("EXIT-SUCCESS"); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/test/vfork.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | save_exe simple$bitness 4 | record $TESTNAME simple$bitness-$nonce 5 | replay 6 | check vforker-EXIT-SUCCESS 7 | -------------------------------------------------------------------------------- /src/test/vfork_break_parent.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1, breakpoint') 8 | 9 | ok() 10 | -------------------------------------------------------------------------------- /src/test/vfork_break_parent.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | save_exe simple$bitness 4 | saved_exe="simple$bitness-$nonce" 5 | 6 | record vfork$bitness "$saved_exe" 7 | debug_gdb_only vfork_break_parent 8 | -------------------------------------------------------------------------------- /src/test/vfork_done_clone.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | save_exe vfork_done$bitness 4 | just_record vfork_done$bitness-$nonce clone 5 | replay 6 | check EXIT-SUCCESS 7 | -------------------------------------------------------------------------------- /src/test/vfork_exec.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | save_exe rr_exec_stub$bitness 4 | saved_exe="rr_exec_stub$bitness-$nonce" 5 | 6 | record vfork$bitness "$saved_exe" 7 | TARGET_PID=$(grep 'child ' record.out | awk '{print $2}') 8 | 9 | echo Targeting recorded pid $TARGET_PID ... 10 | debug_gdb_only first_instruction "-p $TARGET_PID" 11 | -------------------------------------------------------------------------------- /src/test/vfork_read_clone_stress.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('handle SIGKILL stop') 5 | 6 | send_gdb('c') 7 | expect_gdb('Program received signal SIGKILL') 8 | 9 | send_gdb('rc') 10 | expect_gdb([f'({history_end_regex()})', '(child)']) 11 | 12 | assert 'child' not in last_match().group(1) 13 | 14 | send_gdb('c') 15 | expect_gdb('Program received signal SIGKILL') 16 | 17 | ok() 18 | -------------------------------------------------------------------------------- /src/test/vfork_read_clone_stress.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | record $TESTNAME 4 | TARGET_PID=$(grep 'child ' record.out | awk '{print $2}' | tail -n 5 | head -n 1) 5 | echo Targeting recorded pid $TARGET_PID ... 6 | debug_gdb_only vfork_read_clone_stress "-f $TARGET_PID" 7 | -------------------------------------------------------------------------------- /src/test/vsyscall_reverse_next.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | time(NULL); 7 | atomic_puts("EXIT-SUCCESS"); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /src/test/vsyscall_reverse_next.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break vsyscall_reverse_next.c:6') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | send_gdb('disable 1') 8 | 9 | send_gdb('n') 10 | expect_gdb('atomic_puts') 11 | 12 | send_gdb('reverse-next') 13 | expect_gdb('time') 14 | 15 | ok() 16 | -------------------------------------------------------------------------------- /src/test/vsyscall_reverse_next.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 3 | debug_test_gdb_only 4 | -------------------------------------------------------------------------------- /src/test/vsyscall_singlestep.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | skip_if_test_32_bit 3 | record vsyscall$bitness 4 | _RR_TRACE_DIR="$workdir" rr rerun -s 300 --singlestep=rip > /dev/null || failed "Singlestepping through vsyscall failed" 5 | -------------------------------------------------------------------------------- /src/test/wait_for_all.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static int do_child(void) { 6 | sleep(1); 7 | atomic_puts("EXIT-SUCCESS"); 8 | return 0; 9 | } 10 | 11 | int main(void) { 12 | if (!fork()) { 13 | return do_child(); 14 | } 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/test/wait_for_all.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="-w" 4 | compare_test EXIT-SUCCESS 5 | -------------------------------------------------------------------------------- /src/test/watch_code.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b main') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('watch -l *(int*)$pc') 9 | expect_gdb('Hardware watchpoint 2') 10 | 11 | send_gdb('reverse-continue') 12 | expect_history_end() 13 | 14 | ok() 15 | -------------------------------------------------------------------------------- /src/test/watch_code.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug_gdb_only watch_code 4 | -------------------------------------------------------------------------------- /src/test/watchpoint.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/watchpoint_at_sched.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('handle SIGKILL stop') 4 | 5 | send_gdb('c') 6 | expect_gdb('SIGKILL') 7 | 8 | send_gdb('watch -l x') 9 | expect_gdb('Hardware[()/a-z ]+watchpoint 1') 10 | 11 | send_gdb('rc') 12 | expect_gdb('watchpoint 1') 13 | expect_gdb('New value = 1564779003') 14 | 15 | ok() 16 | -------------------------------------------------------------------------------- /src/test/watchpoint_at_sched.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | RECORD_ARGS="-c50" 3 | debug_test_gdb_only 4 | -------------------------------------------------------------------------------- /src/test/watchpoint_before_signal.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('watch -l x') 4 | expect_gdb('Hardware[()/a-z ]+watchpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Old value = 0') 8 | expect_gdb('New value = 1') 9 | 10 | send_gdb('c') 11 | expect_gdb('Old value = 1') 12 | expect_gdb('New value = -1931448864') 13 | 14 | send_gdb('c') 15 | expect_rr('EXIT-SUCCESS') 16 | expect_gdb('exited normally') 17 | 18 | ok() 19 | -------------------------------------------------------------------------------- /src/test/watchpoint_before_signal.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | RECORD_ARGS="-c50" 3 | debug_test_gdb_only 4 | -------------------------------------------------------------------------------- /src/test/watchpoint_cond.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | # Test conditional hardware breakpoint. For some reason 4 | # gdb doesn't seem to use agent conditions for hardware 5 | # watchpoint types other than conditional breakpoints. 6 | 7 | send_gdb('hbreak main') 8 | expect_gdb('reakpoint 1') 9 | send_gdb('cond 1 var==0x1234') 10 | send_gdb('c') 11 | expect_rr('EXIT-SUCCESS') 12 | expect_gdb('exited normally') 13 | 14 | ok() 15 | -------------------------------------------------------------------------------- /src/test/watchpoint_cond.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record watchpoint$bitness 3 | debug_gdb_only watchpoint_cond 4 | -------------------------------------------------------------------------------- /src/test/watchpoint_no_progress.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | arch = get_exe_arch() 5 | 6 | send_gdb('hbreak *syscall_instruction') 7 | expect_gdb('breakpoint 1') 8 | send_gdb('c') 9 | expect_gdb('Breakpoint 1') 10 | send_gdb('stepi') 11 | if arch == 'aarch64': 12 | send_gdb('print $pc == syscall_instruction + 4') 13 | else: 14 | send_gdb('print $pc == syscall_instruction + 2') 15 | expect_gdb('= 1') 16 | send_gdb('reverse-stepi') 17 | send_gdb('print $pc == syscall_instruction') 18 | expect_gdb('= 1') 19 | 20 | ok() 21 | -------------------------------------------------------------------------------- /src/test/watchpoint_no_progress.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/watchpoint_size_change.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | # Test conditional hardware breakpoint. For some reason 4 | # gdb doesn't seem to use agent conditions for hardware 5 | # watchpoint types other than conditional breakpoints. 6 | 7 | send_gdb('break string_store') 8 | expect_gdb('reakpoint 1') 9 | send_gdb('c') 10 | expect_gdb('reakpoint 1') 11 | send_gdb('watch -l *(void**)(dest + 4095)') 12 | expect_gdb('Hardware watchpoint 2') 13 | send_gdb('c') 14 | expect_gdb('Hardware watchpoint 2') 15 | 16 | ok() 17 | -------------------------------------------------------------------------------- /src/test/watchpoint_size_change.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/watchpoint_step.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record watchpoint$bitness 3 | debug_gdb_only watchpoint_step 4 | -------------------------------------------------------------------------------- /src/test/watchpoint_syscall.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/watchpoint_unaligned.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test 3 | -------------------------------------------------------------------------------- /src/test/watchpoint_unaligned2.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('b main') 4 | expect_gdb('Breakpoint 1') 5 | 6 | send_gdb('c') 7 | expect_gdb('Breakpoint 1') 8 | send_gdb('watch -l value.high') 9 | expect_gdb('Hardware watchpoint 2') 10 | send_gdb('c') 11 | expect_gdb('watchpoint 2') 12 | send_gdb('delete 2') 13 | 14 | ok() 15 | -------------------------------------------------------------------------------- /src/test/watchpoint_unaligned2.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/when.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record simple$bitness 3 | debug when 4 | -------------------------------------------------------------------------------- /src/test/when_threads.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void* do_thread(__attribute__((unused)) void* p) { 6 | return NULL; 7 | } 8 | 9 | int main(void) { 10 | pthread_t thread; 11 | pthread_create(&thread, NULL, do_thread, NULL); 12 | sleep(1); 13 | atomic_puts("EXIT-SUCCESS"); 14 | return 0; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/test/when_threads.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test 3 | -------------------------------------------------------------------------------- /src/test/x86/arch_prctl_x86.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | #ifdef __x86_64__ 7 | unsigned long addr; 8 | test_assert(0 == syscall(SYS_arch_prctl, ARCH_GET_FS, &addr)); 9 | #endif 10 | 11 | atomic_puts("EXIT-SUCCESS"); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/test/x86/blocked_sigsegv.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | ( record $TESTNAME ) >& /dev/null 3 | replay 4 | check EXIT-SUCCESS 5 | -------------------------------------------------------------------------------- /src/test/x86/break_rdtsc.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record rdtsc$bitness 3 | debug_gdb_only generic_break 4 | -------------------------------------------------------------------------------- /src/test/x86/cpuid.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | extern int cpuid_loop(int iterations); 6 | 7 | int main(void) { 8 | int sum; 9 | getegid(); 10 | sum = cpuid_loop(1000); 11 | atomic_printf("EXIT-SUCCESS; sum=%d\n", sum); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/test/x86/cpuid_singlestep.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | # Try recording without CPUID faulting and then replaying with it 3 | GLOBAL_OPTIONS=--disable-cpuid-faulting 4 | record $TESTNAME 5 | GLOBAL_OPTIONS= 6 | debug_gdb_only x86/cpuid_singlestep 7 | -------------------------------------------------------------------------------- /src/test/x86/diversion_rdtsc.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('call do_stuff()') 9 | expect_gdb('Printed stuff OK') 10 | 11 | ok() 12 | -------------------------------------------------------------------------------- /src/test/x86/diversion_rdtsc.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record diversion_rdtsc$bitness 3 | debug_gdb_only x86/diversion_rdtsc 4 | -------------------------------------------------------------------------------- /src/test/x86/explicit_checkpoints.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/x86/fxregs.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/x86/gdb_avx512.run: -------------------------------------------------------------------------------- 1 | # check if we have avx512, if not, don't run test 2 | 3 | if ! lscpu | grep -q "avx512f"; then 4 | echo "not running avx512 test" 5 | exit 0 6 | fi 7 | 8 | source `dirname $0`/util.sh 9 | debug_test_gdb_only 10 | -------------------------------------------------------------------------------- /src/test/x86/int3_ok.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void breakpoint(void) { 6 | debug_trap(); 7 | /* NB: the above instruction *must* be at line 6 in this file. 8 | * Tests rely on that. */ 9 | } 10 | 11 | int main(void) { 12 | atomic_puts("doing int3 ..."); 13 | 14 | breakpoint(); 15 | 16 | atomic_puts("EXIT-SUCCESS"); 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /src/test/x86/int3_ok.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | RECORD_ARGS=-t5 3 | compare_test EXIT-SUCCESS 4 | 5 | -------------------------------------------------------------------------------- /src/test/x86/ioperm.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int ret; 7 | ret = syscall(SYS_ioperm, 0, 1024, 1); 8 | atomic_printf("ioperm returned %d\n", ret); 9 | atomic_puts("EXIT-SUCCESS"); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/test/x86/iopl.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int ret; 7 | ret = syscall(SYS_iopl, 3); 8 | atomic_printf("iopl returned %d\n", ret); 9 | atomic_puts("EXIT-SUCCESS"); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/test/x86/lsl.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | int value; 7 | asm volatile ("lsl %1,%0" : "=r"(value) : "r"(0x7b)); 8 | atomic_printf("%d\n", value); 9 | atomic_puts("EXIT-SUCCESS"); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/test/x86/morestack_unwind.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void breakpoint(void) { 6 | int break_here = 1; 7 | (void)break_here; 8 | } 9 | 10 | int main(void) { 11 | atomic_puts("EXIT-SUCCESS"); 12 | breakpoint(); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /src/test/x86/morestack_unwind.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break main') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('break _syscall_hook_trampoline') 9 | expect_gdb('Breakpoint 2') 10 | send_gdb('c') 11 | expect_gdb('Breakpoint 2') 12 | 13 | send_gdb('fin') 14 | send_gdb('fin') 15 | send_gdb('fin') 16 | 17 | # Verify we didn't run too far 18 | 19 | send_gdb('b breakpoint') 20 | expect_gdb('Breakpoint 3') 21 | 22 | send_gdb('c') 23 | expect_gdb('Breakpoint 3') 24 | 25 | ok() 26 | -------------------------------------------------------------------------------- /src/test/x86/morestack_unwind.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | skip_if_no_syscall_buf 3 | debug_test_gdb_only 4 | -------------------------------------------------------------------------------- /src/test/x86/old_fork.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | pid_t child; 7 | int status; 8 | 9 | if (0 == (child = syscall(SYS_fork))) { 10 | return 11; 11 | } 12 | 13 | test_assert(child == waitpid(child, &status, 0)); 14 | test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 11); 15 | 16 | atomic_puts("EXIT-SUCCESS"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/test/x86/patch_40_80_f6_81.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # This test requires syscallbuf syscall patching 4 | skip_if_no_syscall_buf 5 | compare_test EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/x86/rdtsc_interfering.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | skip_if_no_syscall_buf 3 | skip_if_test_32_bit 4 | skip_if_rr_32_bit 5 | compare_test EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/x86/rdtsc_loop.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | skip_if_no_syscall_buf 3 | compare_test EXIT-SUCCESS 4 | -------------------------------------------------------------------------------- /src/test/x86/rdtsc_loop2.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static void do_rdtsc(void) { 6 | asm("rdtsc"); 7 | } 8 | 9 | int main(void) { 10 | int i; 11 | for (i = 0; i < 2000000; ++i) { 12 | do_rdtsc(); 13 | } 14 | atomic_puts("EXIT-SUCCESS"); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/x86/rdtsc_loop2.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | skip_if_no_syscall_buf 3 | skip_if_test_32_bit 4 | skip_if_rr_32_bit 5 | compare_test EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/x86/sigreturn_checksum.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | GLOBAL_OPTIONS="$GLOBAL_OPTIONS --checksum=on-all-events" 3 | record sigreturn$bitness 4 | replay 5 | check EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/x86/singlestep_pushf.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | int main(void) { 6 | uintptr_t val; 7 | #if defined(__x86_64__) || defined(__i386__) 8 | asm ("breakpoint: pushf\n" 9 | "pop %0\n" 10 | : "=a"(val)); 11 | #else 12 | #error Unknown architecture 13 | #endif 14 | 15 | if (val & 0x100) { 16 | atomic_puts("TF set!"); 17 | return 1; 18 | } 19 | 20 | atomic_puts("EXIT-SUCCESS"); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /src/test/x86/singlestep_pushf.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break breakpoint') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('stepi') 9 | 10 | send_gdb('c') 11 | expect_rr('EXIT-SUCCESS') 12 | expect_gdb('exited normally') 13 | 14 | ok() 15 | -------------------------------------------------------------------------------- /src/test/x86/singlestep_pushf.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/x86/step_rdtsc.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | record rdtsc$bitness 3 | debug_gdb_only x86/step_rdtsc 4 | -------------------------------------------------------------------------------- /src/test/x86/string_instructions.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 4 | compare_test EXIT-SUCCESS 5 | -------------------------------------------------------------------------------- /src/test/x86/string_instructions_async_signals.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="-c1000" 4 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 5 | compare_test EXIT-SUCCESS 6 | 7 | -------------------------------------------------------------------------------- /src/test/x86/string_instructions_async_signals_shared.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | RECORD_ARGS="-c1000" 4 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 5 | compare_test EXIT-SUCCESS 6 | 7 | -------------------------------------------------------------------------------- /src/test/x86/string_instructions_break.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break string_store') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('watch -l p[0]') 9 | expect_gdb('watchpoint 2') 10 | send_gdb('c') 11 | expect_gdb('watchpoint 2') 12 | 13 | send_gdb('break') 14 | expect_gdb('Breakpoint 3') 15 | send_gdb('disable 3') 16 | send_gdb('finish') 17 | expect_gdb('main') 18 | 19 | send_gdb('enable 3') 20 | send_gdb('reverse-continue') 21 | expect_gdb('Breakpoint 3') 22 | 23 | ok() 24 | -------------------------------------------------------------------------------- /src/test/x86/string_instructions_break.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 4 | record string_instructions_replay$bitness 5 | debug_gdb_only x86/string_instructions_break 6 | -------------------------------------------------------------------------------- /src/test/x86/string_instructions_multiwatch.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | import re 3 | 4 | send_gdb('b my_memmove') 5 | expect_gdb('Breakpoint 1') 6 | send_gdb('c') 7 | expect_gdb(re.compile(r'Buf is at ([^ \n]+)')) 8 | buf = eval(last_match().group(1)); 9 | expect_gdb('Breakpoint 1') 10 | 11 | send_gdb('watch -l *(char*)%d'%(buf + 14000)) 12 | expect_gdb('atchpoint 2') 13 | 14 | send_gdb('c') 15 | expect_gdb('atchpoint 2') 16 | 17 | ok() 18 | -------------------------------------------------------------------------------- /src/test/x86/string_instructions_multiwatch.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 4 | debug_test_gdb_only 5 | -------------------------------------------------------------------------------- /src/test/x86/string_instructions_replay.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 4 | 5 | record $TESTNAME & 6 | 7 | for i in $(seq 1 30); do 8 | sleep 0.05 9 | kill -CHLD $rrpid $(pidof $TESTNAME-$nonce) >& /dev/null 10 | done 11 | 12 | # Wait for 'record' to actually terminate. Otherwise we might start 13 | # replaying before the trace file has been completely written. 14 | wait 15 | 16 | echo "Replaying ..." 17 | replay 18 | check 'EXIT-SUCCESS' 19 | -------------------------------------------------------------------------------- /src/test/x86/string_instructions_replay_quirk.py: -------------------------------------------------------------------------------- 1 | from util import * 2 | 3 | send_gdb('break string_store') 4 | expect_gdb('Breakpoint 1') 5 | send_gdb('c') 6 | expect_gdb('Breakpoint 1') 7 | 8 | send_gdb('disable') 9 | send_gdb('watch -l p[0]') 10 | expect_gdb('watchpoint') 11 | send_gdb('c') 12 | expect_gdb('Old value = 0') 13 | expect_gdb('New value = 1') 14 | send_gdb('p p[0]') 15 | expect_gdb('= 1') 16 | send_gdb('p p[1]') 17 | expect_gdb('= 0') 18 | 19 | ok() 20 | -------------------------------------------------------------------------------- /src/test/x86/string_instructions_replay_quirk.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | if [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi 4 | record string_instructions_replay$bitness 5 | debug_gdb_only x86/string_instructions_replay_quirk 6 | -------------------------------------------------------------------------------- /src/test/x86/string_instructions_singlestep_fastforward.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | static int string_cmp_equal(char* s, char* t, uintptr_t size) { 4 | int b; 5 | __asm__("repe cmpsb\n\t;" 6 | "sete %%al\n\t;" 7 | "movzx %%al,%0;": "=r"(b) : "S"(t), "D"(s), "c"(size) : "al"); 8 | return b; 9 | } 10 | 11 | int main(void) { 12 | char* STRING1 = "almost_the_same1"; 13 | char* STRING2 = "almost_the_same2"; 14 | int x = string_cmp_equal(STRING1, STRING2, 17); 15 | return x; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/x86/string_instructions_singlestep_fastforward.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | rerun_singlestep_test 4 | -------------------------------------------------------------------------------- /src/test/x86/string_instructions_watch.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test_gdb_only 3 | -------------------------------------------------------------------------------- /src/test/x86/syscallbuf_branch_check.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | 3 | # This test requires syscallbuf syscall patching 4 | skip_if_no_syscall_buf 5 | compare_test EXIT-SUCCESS 6 | -------------------------------------------------------------------------------- /src/test/x86/syscallbuf_rdtsc_page.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | skip_if_no_syscall_buf 3 | compare_test EXIT-SUCCESS 4 | -------------------------------------------------------------------------------- /src/test/x86/util.h: -------------------------------------------------------------------------------- 1 | #include "../util.h" 2 | -------------------------------------------------------------------------------- /src/test/x86/util.py: -------------------------------------------------------------------------------- 1 | ../util.py -------------------------------------------------------------------------------- /src/test/x86/util.sh: -------------------------------------------------------------------------------- 1 | TEST_PREFIX=x86/ 2 | source `dirname $0`/../util.sh 3 | -------------------------------------------------------------------------------- /src/test/x86/watchpoint_error.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ 2 | 3 | #include "util.h" 4 | 5 | static char buffer[64]; 6 | 7 | int main(void) { 8 | atomic_puts("EXIT-SUCCESS"); 9 | strcpy(buffer, "hello"); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/test/x86/watchpoint_error.run: -------------------------------------------------------------------------------- 1 | source `dirname $0`/util.sh 2 | debug_test watchpoint_error 3 | -------------------------------------------------------------------------------- /third-party/blake2/README: -------------------------------------------------------------------------------- 1 | Taken verbatim from https://github.com/BLAKE2/BLAKE2/commit/997fa5ba1e14b52c554fb03ce39e579e6f27b90c 2 | 3 | Sources are in the public domain. 4 | -------------------------------------------------------------------------------- /third-party/brotli/common/dictionary.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rr-debugger/rr/daaab24f10c81394f209cf05ef1191af3365ccd8/third-party/brotli/common/dictionary.bin -------------------------------------------------------------------------------- /third-party/brotli/common/dictionary.bin.br: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rr-debugger/rr/daaab24f10c81394f209cf05ef1191af3365ccd8/third-party/brotli/common/dictionary.bin.br -------------------------------------------------------------------------------- /third-party/gdb/32bit-linux.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /third-party/gdb/32bit-pkeys.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /third-party/gdb/64bit-linux.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /third-party/gdb/64bit-pkeys.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /third-party/gdb/64bit-seg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /third-party/gdb/README: -------------------------------------------------------------------------------- 1 | These files, with the exception of 64bit-seg.xml, are taken from 2 | binutils-gdb/gdb/features, git tag gdb-7.7-release, with the 3 | following change: 4 | 5 | * A reference to 64bit-seg.xml was added to amd64-avx-linux.xml 6 | and amd64-linux.xml 7 | 8 | Using the latest gdb files we get errors with gdb 10.1 and probably 9 | earlier versions, which require flags to have both "start" and 10 | "end" attributes. 11 | 12 | These files all have the same BSD-ish license (thanks FSF!). 13 | -------------------------------------------------------------------------------- /third-party/gdb/aarch64-pauth.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /third-party/zen-pmu-workaround/Makefile: -------------------------------------------------------------------------------- 1 | obj-m = zen_workaround.o 2 | 3 | all: 4 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 5 | 6 | clean: 7 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 8 | -------------------------------------------------------------------------------- /third-party/zen-pmu-workaround/README: -------------------------------------------------------------------------------- 1 | Zen workaround kernel module, Copyright 2020, Mike Hommey. 2 | 3 | This has the same effect as `scripts/zen_workaround.py`, but persists after resuming from sleep. 4 | 5 | There is no upstream, but we put it in third-party because it's technically a derived work of the Linux kernel. The license is GPL 2.0. See LICENSE at the root of this repo. 6 | --------------------------------------------------------------------------------